我最近遇到了一个依赖于UPS Tracking API的遗留应用程序的问题. UPS改变了他们的通信协议以要求TLSv1.2.不幸的是,jdk 1.6的最新公共版本似乎不支持这个协议,所以我的选择是支付oracle支持合同或升级到jdk 1.7.我升级到1.7
我更改了项目的依赖项,一切都很好.当我尝试实际部署到应用程序服务器时,它失败并显示错误:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1
counts of IllegalAnnotationExceptions java.lang.StackTraceElement does
not have a no-arg default constructor
我做了一些研究,显然这个问题是由jaxb @WebMethod注释的方法引起的,这些方法抛出了throwable的异常. (我认为)的解决方案是在异常类中添加@WebFault批注.我按照这里的说明操作:http://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-exceptions-faults-annotation-exception-and-fault-handling-examples/
并重新部署.
结果是同样的错误.唯一的区别是我的stacktrace表明它正在使用我的自定义故障bean而不是尝试生成包装器.我也查看了这里给出的解决方案:map exceptions to faults,据我所知,我的课程符合规范,但问题仍然存在.
这个问题使我无法解决UPS问题并导致用户头痛.任何帮助将非常感激.
我的错误日志
Caused by: org.jboss.ws.WSException: Failed to create JAXBContext at
jaxb.hibernate.XMLAcccesorAvailableContextFactory.createContext(XMLAcccesorAvailableContextFactory.java:41)
at
org.jboss.ws.metadata.builder.jaxws.JAXWSMetaDataBuilder.createJAXBContext(JAXWSMetaDataBuilder.java:940)
… 82 more Caused by:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of
IllegalAnnotationExceptions java.lang.StackTraceElement does not have
a no-arg default constructor. this problem is related to the
following location: at java.lang.StackTraceElement at public
java.lang.StackTraceElement[] java.lang.Throwable.getStackTrace() at
java.lang.Throwable at private java.lang.Throwable[]
com.tura.common.server.service.addressvalidation.AddressServiceFault.suppressed
at
com.tura.common.server.service.addressvalidation.AddressServiceFaultat
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;
}
}
我的WebService类
@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();
}
解决方法:
看起来没有人及时提出解决方案,所以我将继续发布如何解决这个问题. JAX-WS使用反射来确定是否应该包装异常类.因此,对于异常中包含的构造函数和方法非常挑剔.如果仔细查看AddressValidationServiceException类,您会注意到它具有以下方法:
protected AddressServiceFault getFaultInfo() {
return faultInfo;
}
问题在于该方法的可见性. getFaultInfo()必须是一个公共方法,否则jax-ws将无法正确识别并包装异常类.一旦我将该方法改为公开,一切都开始起作用了.事实上,我完全可以删除@WebFault注释.只要异常类和错误的格式正确,就不需要显式注释.
另一个’陷阱’需要注意. Java构造函数不是继承的.如果您有其他扩展异常的类,则层次结构中的每个类都必须明确定义
public MyClass(String message, MyServiceFault fault)
和
public MyClass(String message, MyServiceFault fault, Throwable cause)
构造函数.