XmlAdapter到JAXB绑定Joda时间间隔? [英] XmlAdapter to JAXB-bind Joda Time Interval?

查看:138
本文介绍了XmlAdapter到JAXB绑定Joda时间间隔?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的网页服务的JAXB绑定问题已经困了几个小时:

I've been stuck for a few hours with a problem in my JAXB bindings for a web service:

为了准备一个更大的网络服务返回Joda时间类实例(即时,持续时间,间隔等)我已经开始使用只有一种方法返回间隔的Web服务:

In order to prepare for a bigger web service that has to return Joda Time class instances (Instant, Duration, Interval, etc.) I've started with a web service that has only one method returning an Interval:

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());
    }
}

发布此网络服务我收到一条说明org的例外情况.joda.time.Interval没有no-arg默认构造函数:

Publishing this web service I receive an exception stating "org.joda.time.Interval does not have a no-arg default constructor":

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 - 第一个实现返回有效但是常量值:

So I've read several tutorials etc. and ended up writing my own XmlAdapter for the Interval class - the first implementation returns valid but constant values:

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";
    }
}

此外我还注释了我的网络方法使用适配器:

And additionally I've annotated my web method to use the adapter:

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服务时,我仍然收到一个异常,但是另一个例外:

Now it should work. But when I start the web service again, I still receive an exception, though a different one:

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

这就是我被困的地方。我做错了什么?

And that's where I'm stuck. What am I doing wrong?

推荐答案

你是正确的,你需要使用 XmlAdapter 供此用途使用案件。以下是如何完成的示例:

You are correct that you will need to use an XmlAdapter for this use case. Below is an example of how it could be done:

IntervalStringAdapter

下面的适配器将以格式start-end的形式将Interval的实例转换为/来自Strings。

The adapter below will convert instances of Interval to/from Strings in the format start-end.

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();
    }

}

Root

以下是如何配置属性以使用适配器的示例:

Below is an example of how to configure the property to use the adapter:

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>

更多信息

  • http://bdoughan.blogspot.com/2011/05/jaxb-and-joda-time-dates-and-times.html

这篇关于XmlAdapter到JAXB绑定Joda时间间隔?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆