【问题标题】:Switching from Java 1.6 to 1.7 causes JAXB Exception从 Java 1.6 切换到 1.7 会导致 JAXB 异常
【发布时间】:2018-05-06 17:04:28
【问题描述】:

我最近遇到了一个依赖于 UPS Tracking API 的旧应用程序的问题。 UPS 将其通信协议更改为需要 TLSv1.2。不幸的是,最新的 jdk 1.6 公开版本似乎不支持该协议,所以我的选择是支付 oracle 支持合同或升级到 jdk 1.7。我升级到 1.7

我更改了项目的依赖项,一切看起来都很好。当我尝试实际部署到应用程序服务器时,它失败并出现错误:

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 IllegalAnnotationExceptions java.lang.StackTraceElement 的计数 没有无参数默认构造函数

我做了一些研究,显然这个问题是由 jaxb @WebMethod 注释方法引起的,这些方法抛出 throwable 异常。解决方案(我认为)是在异常类中添加一个 @WebFault 注释。我按照这里的说明进行操作:http://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-exceptions-faults-annotation-exception-and-fault-handling-examples/ 并重新部署。

结果是同样的错误。唯一的区别是我的堆栈跟踪表明它正在使用我的自定义故障 bean,而不是尝试生成包装器。我还查看了此处给出的解决方案:map exceptions to faults,据我所知,我的课程符合规范,但问题仍然存在。

这个问题使我无法解决 UPS 问题,并让我的用户非常头疼。任何帮助将不胜感激。

我的错误日志

原因:org.jboss.ws.WSException:无法在以下位置创建 JAXBContext jaxb.hibernate.XMLAcccesorAvailableContextFactory.createContext(XMLAcccesorAvailableContextFactory.java:41) 在 org.jboss.ws.metadata.builder.jaxws.JAXWSMetaDataBuilder.createJAXBContext(JAXWSMetaDataBuilder.java:940) ... 82 更多 com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 计数 IllegalAnnotationExceptions java.lang.StackTraceElement 没有 一个无参数的默认构造函数。这个问题与 以下位置:在公共的 java.lang.StackTraceElement java.lang.StackTraceElement[] java.lang.Throwable.getStackTrace() 在 java.lang.Throwable 在私有 java.lang.Throwable[] com.tura.common.server.service.addressvalidation.AddressServiceFault.suppressed 在 com.tura.common.server.service.addressvalidation.AddressServiceFault

在 com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:106)

异常类

@WebFault(faultBean = "com.tura.common.server.service.addressvalidation.AddressServiceFault")
public class AddressValidationServiceException extends Exception {

    private AddressServiceFault faultInfo;

    public AddressValidationServiceException() {
        super();
    }
    public AddressValidationServiceException(AddressServiceFault fault) {
        super(fault.getFaultString());
        this.faultInfo = fault;
    }

    public AddressValidationServiceException(String message, AddressServiceFault fault) {
        super(message);
        this.faultInfo = fault;
    }

    public AddressValidationServiceException(String message, Throwable cause) {
        super(message, cause);
    }

    public AddressValidationServiceException(String message, AddressServiceFault fault, Throwable cause) {
        super(message, cause);
        this.faultInfo = fault;
    }

    protected AddressServiceFault getFaultInfo() {
        return faultInfo;
    }
}

Fault Bean 类

public class AddressServiceFault {

    private String faultCode;

    private String faultString;

    protected String getFaultCode() {
        return faultCode;
    }

    protected void setFaultCode(String faultCode) {
        this.faultCode = faultCode;
    }

    protected String getFaultString() {
        return faultString;
    }

    protected void setFaultString(String faultString) {
        this.faultString = faultString;
    }
}

我的网络服务类

@WebMethod
    public @WebResult(name = "validatedAddresses") String parseAddressStringByLocation(
            @WebParam(name = "sLocation") String sLocation) throws AddressValidationServiceException {
        StringBuffer sbUrl = new StringBuffer();
        StringBuffer sbQueryString = new StringBuffer();

        sbUrl.append("http://test.foo.com");

        try {
            sbQueryString.append("&location=");
            sbQueryString.append(URLEncoder.encode(sLocation, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            AddressServiceFault serviceFault = new AddressServiceFault();
            serviceFault.setMessage("Validation Failed");
            throw new AddressValidationServiceException("Address Validation Error: parseQueryStringByLocation.",
                    serviceFault, e);
        }

        sbUrl.append(sbQueryString);

        return sbUrl.toString();
    }

【问题讨论】:

  • Java 6,现在支持 TLS 1.2,查看下方oracle.com/technetwork/java/javase/…
  • @ LAKHDAR Omar 我知道有一个支持 TLSv1.2 的 java 6 版本。不幸的是,据我所知,这些版本的 JDK 不是公开可用的。获得它们的唯一方法是与 oracle 签订付费支持合同。如果我错了,并且有一些有信誉的方法可以访问 Java 6 jdk 的较新版本,请告诉我。
  • 为支持付费是有信誉的:-)
  • 我猜那是措辞不当。我的意思是一种合法的方式来获得更新的 jdk,而无需每年支付数千美元。

标签: java jboss jaxb tls1.2


【解决方案1】:

您的 Exception 类似乎需要覆盖 getStackTrace() 和 getCause() 方法。 看看here,Domenic D. 的答案可能是解决方案。

可能是 jaxb-impl 版本存在问题,对此也进行了描述。

【讨论】:

    【解决方案2】:

    可抛出对象不能直接序列化为 XML,因为 StackTraceElement 没有 JAXB 要求的无参数构造函数。

    使用自定义 SOAP 错误(使用 @WebFault 注释的类)并使用 soapFault 下的 detail 元素发送异常详细信息。

    【讨论】:

    • 感谢您的建议,但如果您再次查看我发布的代码,那正是我正在做的事情。
    • 我看不到您填充 AddressServiceFault 然后设置 AddressValidationServiceException 然后抛出 AddressValidationServiceException 的代码。在您的服务的方法 getValidAddressXMLByLocation 中捕获异常,填充 AddressServiceFault 并在 AddressValidationServiceException 中设置然后抛出,它将起作用
    • 我更新了示例以包含实际引发异常的代码。填充和抛出异常似乎不是原因。
    【解决方案3】:

    似乎没有人及时提出解决方案,所以我将继续发布我是如何解决这个问题的。 JAX-WS 使用反射来确定是否应该包装异常类。因此,它对异常中包含的构造函数和方法非常挑剔。如果你仔细观察 AddressValidationServiceException 类,你会注意到它有这个方法:

    protected AddressServiceFault getFaultInfo() {
            return faultInfo;
        }
    

    问题在于该方法的可见性。 getFaultInfo() 必须是 public 方法,否则 jax-ws 将无法正确识别和包装异常类。一旦我将该方法更改为公开,一切就开始工作了。事实上,我能够完全删除 @WebFault 注释。只要异常类和故障格式正确,就不需要显式注解。

    另一个需要注意的“问题”。 Java 构造函数不是继承的。如果您有其他类扩展您的异常,则层次结构中的每个类都必须显式定义

    public MyClass(String message, MyServiceFault fault)
    

    public MyClass(String message, MyServiceFault fault, Throwable cause)
    

    构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 2013-09-28
      • 1970-01-01
      • 2012-09-06
      相关资源
      最近更新 更多