我的网页服务的JAXB绑定出现问题,我被困了几个小时:
为了准备一个必须返回Joda Time类实例(即时,持续时间,间隔等)的更大的Web服务,我已经开始使用只有一个方法返回Interval的Web服务:
package jodaws;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import org.joda.time.Interval;
@WebService(name = "JodaWS")
public class JodaWebService {
public Interval readInterval() {
return new Interval(30, 40);
}
public static void main(String[] args) {
Endpoint.publish("http://localhost:10100/JodaWS", new JodaWebService());
}
}
发布此Web服务我收到一个异常,指出“org.joda.time.Interval没有no-arg默认构造函数”:
29.05.2011 17:24:07 com.sun.xml.internal.ws.model.RuntimeModeler getRequestWrapperClass
INFO: Dynamically creating request wrapper Class jodaws.jaxws.ReadInterval
29.05.2011 17:24:07 com.sun.xml.internal.ws.model.RuntimeModeler getResponseWrapperClass
INFO: Dynamically creating response wrapper bean Class jodaws.jaxws.ReadIntervalResponse
Exception in thread "main" javax.xml.ws.WebServiceException: Unable to create JAXBContext
at com.sun.xml.internal.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:153)
at com.sun.xml.internal.ws.model.AbstractSEIModelImpl.postProcess(AbstractSEIModelImpl.java:83)
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:244)
at com.sun.xml.internal.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:312)
at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:178)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:456)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:475)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:102)
at javax.xml.ws.Endpoint.publish(Endpoint.java:170)
at jodaws.JodaWebService.main(JodaWebService.java:17)
Caused by: java.security.PrivilegedActionException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
org.joda.time.Interval does not have a no-arg default constructor.
this problem is related to the following location:
at org.joda.time.Interval
at public org.joda.time.Interval jodaws.jaxws.ReadIntervalResponse._return
at jodaws.jaxws.ReadIntervalResponse
org.joda.time.base.BaseInterval does not have a no-arg default constructor.
this problem is related to the following location:
at org.joda.time.base.BaseInterval
at org.joda.time.Interval
at public org.joda.time.Interval jodaws.jaxws.ReadIntervalResponse._return
at jodaws.jaxws.ReadIntervalResponse
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.xml.internal.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:140)
... 11 more
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
org.joda.time.Interval does not have a no-arg default constructor.
this problem is related to the following location:
at org.joda.time.Interval
at public org.joda.time.Interval jodaws.jaxws.ReadIntervalResponse._return
at jodaws.jaxws.ReadIntervalResponse
org.joda.time.base.BaseInterval does not have a no-arg default constructor.
this problem is related to the following location:
at org.joda.time.base.BaseInterval
at org.joda.time.Interval
at public org.joda.time.Interval jodaws.jaxws.ReadIntervalResponse._return
at jodaws.jaxws.ReadIntervalResponse
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
at com.sun.xml.internal.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:95)
at com.sun.xml.internal.ws.developer.JAXBContextFactory$1.createJAXBContext(JAXBContextFactory.java:97)
at com.sun.xml.internal.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:148)
at com.sun.xml.internal.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:140)
... 13 more
所以我已经阅读了几个教程等,最后为Interval类编写了自己的XmlAdapter - 第一个实现返回有效但是常量值:
package jodaws;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.Interval;
public class IntervalAdapter extends XmlAdapter<String, Interval> {
@Override
public Interval unmarshal(String v) throws Exception {
return new Interval(10, 20);
}
@Override
public String marshal(Interval v) throws Exception {
return "10-20";
}
}
另外我已经注释了我的web方法以使用适配器:
package jodaws;
import javax.jws.WebService;
// import added
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.ws.Endpoint;
import org.joda.time.Interval;
@WebService(name = "JodaWS")
public class JodaWebService {
// annotation added
@XmlJavaTypeAdapter(IntervalAdapter.class)
public Interval readInterval() {
return new Interval(30, 40);
}
public static void main(String[] args) {
Endpoint.publish("http://localhost:10100/JodaWS", new JodaWebService());
}
}
现在它应该工作了。但是,当我再次启动Web服务时,我仍然会收到一个例外,但不同的是:
29.05.2011 17:27:33 com.sun.xml.internal.ws.model.RuntimeModeler getRequestWrapperClass
INFO: Dynamically creating request wrapper Class jodaws.jaxws.ReadInterval
29.05.2011 17:27:34 com.sun.xml.internal.ws.model.RuntimeModeler getResponseWrapperClass
INFO: Dynamically creating response wrapper bean Class jodaws.jaxws.ReadIntervalResponse
Exception in thread "main" javax.xml.ws.WebServiceException: java.lang.IllegalArgumentException: value class jodaws.IntervalAdapter
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createResponseWrapperBean(WrapperBeanGenerator.java:269)
at com.sun.xml.internal.ws.model.RuntimeModeler.getResponseWrapperClass(RuntimeModeler.java:293)
at com.sun.xml.internal.ws.model.RuntimeModeler.processDocWrappedMethod(RuntimeModeler.java:688)
at com.sun.xml.internal.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:612)
at com.sun.xml.internal.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:401)
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:240)
at com.sun.xml.internal.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:312)
at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:178)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:456)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:475)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:102)
at javax.xml.ws.Endpoint.publish(Endpoint.java:170)
at jodaws.JodaWebService.main(JodaWebService.java:18)
Caused by: java.lang.IllegalArgumentException: value class jodaws.IntervalAdapter
at com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter.newConstItem(ClassWriter.java:893)
at com.sun.xml.internal.ws.org.objectweb.asm.AnnotationWriter.visit(AnnotationWriter.java:185)
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createBeanImage(WrapperBeanGenerator.java:111)
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createResponseWrapperBean(WrapperBeanGenerator.java:265)
... 14 more
这就是我被困住的地方。我做错了什么?
答案 0 :(得分:7)
您是正确的,您需要在此用例中使用XmlAdapter
。以下是如何完成的示例:
<强> IntervalStringAdapter 强>
下面的适配器将以“开始结束”格式将Interval的实例转换为Strings的数据。
package blog.joda;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.Interval;
public class IntervalStringAdapter extends XmlAdapter<String, Interval>{
@Override
public Interval unmarshal(String v) throws Exception {
int dashIndex = v.indexOf('-');
long start = Long.valueOf(v.substring(0, dashIndex));
long end = Long.valueOf(v.substring(dashIndex + 1));
return new Interval(start, end);
}
@Override
public String marshal(Interval v) throws Exception {
return v.getStartMillis() + "-" + v.getEndMillis();
}
}
<强>根强>
以下是如何配置属性以使用适配器的示例:
package blog.joda;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.joda.time.Interval;
@XmlRootElement
public class Root {
private Interval interval;
@XmlJavaTypeAdapter(IntervalStringAdapter.class)
public Interval getInterval() {
return interval;
}
public void setInterval(Interval interval) {
this.interval = interval;
}
}
<强>演示强>
package blog.joda;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new File("src/blog/joda/input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
<强> input.xml中强>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<interval>10-20</interval>
</root>
了解更多信息