@XmlJavaTypeAdapter vs @XmlSchemaType with java.time.LocalDateTime

时间:2014-09-04 08:22:01

标签: web-services netbeans jaxb glassfish jax-ws

我正在Netbeans(8)中开发EJB模块和JAVAFX客户端中的JAXWS(在Glassfish 4.0上部署)。我正在使用IDE从Java类方向构建我的WS。我正在努力解决通过WS 传递java.time.LocalDateTime并在客户端获取LocalDateTime。

重要的是,我需要/想要一起开发服务器和客户端!如果我更改WS,WSDL会发生变化,它应该由Netbeans(通过JAXWS)一次传播到客户端源代码(类型安全)......,但它在某种程度上无法解决java.time( .localdate)..

为什么WS在编组期间不会向LocalDateTime字段写入任何内容。为什么? 这是我用的好方法吗? 我错过了什么吗?感谢。

如果我在WebService中使用@XmlJavaTypeAdapter来处理 LocalDateTime编组到String ,则XSD生成会将xs:string放入我的localDateTime字段...所以@XMLSchemaType被@XmlJavaTypeAdapter覆盖。 如何解决此问题?

服务器端,在WebService中,我使用包级别

    @XmlSchemaTypes({
      @XmlSchemaType(name="date", type=LocalDate.class)
      ,@XmlSchemaType(name="dateTime", type=LocalDateTime.class)
      ,@XmlSchemaType(name="time", type=LocalTime.class)
    })

这使IDE生成正确的XSD元素,例如包含

    <xs:element name="validTo" type="xs:dateTime" minOccurs="0"/>

服务器上的 XmlADapter :(如果我用@XmlJavaTypeAdapter (String,LocalDateTime)注入它,那么XSD生成会从LocalDateTime创建String。)

    public class LocalDateTimeAdapter
        extends XmlAdapter<String, LocalDateTime>{
        @Override
        public LocalDateTime unmarshal(String v) throws Exception {
            return LocalDateTime.parse(v,DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        }
        @Override
        public String marshal(LocalDateTime v) throws Exception {
            return v.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        }
    }

在客户端,我附加了WS,让IDE生成类。 我在附加的Webservice和 Adapter 类中添加了一个外部绑定文件来处理LocalDateTime字段:

绑定文件                      

            <jxb:globalBindings>
                <jxb:javaType name="java.time.LocalDateTime" xmlType="xs:dateTime"
                      parseMethod="test.app.utils.JaxBDateConverter.parseDateTime"
                      printMethod="test.app.utils.JaxBDateConverter.printDateTime" />
                <jxb:javaType name="java.time.LocalDate" xmlType="xs:date"
                      parseMethod="test.app.utils.JaxBDateConverter.parseDate"
                      printMethod="test.app.utils.JaxBDateConverter.printDate" />
                <jxb:javaType name="java.time.LocalTime" xmlType="xs:time"
                      parseMethod="test.app.utils.JaxBDateConverter.parseTime"
                      printMethod="test.app.utils.JaxBDateConverter.printTime" />

            </jxb:globalBindings>

        </jxb:bindings> 
    </jxb:bindings>

客户端上的适配器类:         package test.app.client;

    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;

    public class JaxBDateConverter {

    static final DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
    static final DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_DATE;
    static final DateTimeFormatter tf = DateTimeFormatter.ISO_LOCAL_TIME;

    public static LocalDateTime parseDateTime(String s) {
        try {
            if (s.trim().isEmpty()) {
                return null;
            } else {
            }
            LocalDateTime r = LocalDateTime.parse(s, dtf);
            return r;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static String printDateTime(LocalDateTime d) {
        try {
            if (d == null)
                return null;
            return d.format(dtf);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static LocalDate parseDate(String s) {
        try {
            if (s.trim().isEmpty()) {
                return null;
            } else {
            }
            LocalDate r = LocalDate.parse(s, df);
            return r;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static String printDate(LocalDate d) {
        try {
            if (d == null)
                return null;
            return d.format(df);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
    public static LocalTime parseTime(String s) {
        try {
            if (s.trim().isEmpty()) {
                return null;
            } else {
            }
            LocalTime r = LocalTime.parse(s, tf);
            return r;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static String printTime(LocalTime d) {
        try {
            if (d == null)
                return null;
            return d.format(tf);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    }

1 个答案:

答案 0 :(得分:1)

  

为什么WS不会在LocalDateTime字段中写入任何内容   在编组期间。为什么?这是我创造的好方法吗?我想念   什么?感谢。

自最新的JAXB(JSR-222)发布以来,已添加java.time.LocalDateTime类型,所以现在需要XmlAdapter来处理转换。


  

如果我在WebService中使用@XmlJavaTypeAdapter来处理LocalDateTime   编组,XSD生成将xs:string放入我的localDateTime   fields ...所以@XMLSchemaType被@XmlJavaTypeAdapter覆盖。怎么样   我能解决这个问题吗?

@XmlJavaTypeAdapter不会覆盖@XmlSchemaType。相反,引用的XmlAdapter正在将LocalDateTime转换为String。现在,就JAXB而言,它现在属于String属性,因此@XmlSchemaType不再适用。


  

我该如何解决这个问题?

您可以直接在已调整的@XmlSchemaType媒体资源上使用LocalDateTime注释。

@XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
@XmlSchemaType(name="dateTime")
public LocalDateTime getMyLocalDateTime() {
    return myLocalDateTime;
}