java JAXB、自定义绑定、Adapter1.class 和 Joda-time

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12513361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:11:21  来源:igfitidea点击:

JAXB, Custom bindings, Adapter1.class and Joda-time

javabindingannotationsjaxb

提问by mdm

I have a problem with the way JAXB is generating the bound classes for an XML schema (which, for sake of precision, I cannot modify). I want to map a xsd:date type to a Joda-time LocalDate object and, reading here, hereand here, I created the following DateAdapter class:

我对 JAXB 为 XML 模式生成绑定类的方式有问题(为了精确起见,我无法修改)。我想将一个 xsd:date 类型映射到一个 Joda 时间的 LocalDate 对象,并且这里这里这里阅读,我创建了以下 DateAdapter 类:

public class DateAdapter extends XmlAdapter<String,LocalDate> {
    private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");

    public LocalDate unmarshal(String v) throws Exception {
        return fmt.parseLocalDate(v);
    }

    public String marshal(LocalDate v) throws Exception {
        return v.toString("yyyyMMdd");
    }
}

And I added the following to my global binding file:

我将以下内容添加到我的全局绑定文件中:

  <jaxb:globalBindings>
        <jaxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
            parseMethod="my.classes.adapters.DateAdapter.unmarshal"
            printMethod="my.classes.adapters.DateAdapter.marshal" />
    </jaxb:globalBindings>

The problem is that, when I try to maven compile my project, it fails with the following error:

问题是,当我尝试 maven 编译我的项目时,它失败并出现以下错误:

[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[20,59] non-static method unmarshal(java.lang.String) cannot be referenced from a static context
[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[24,59] non-static method marshal(org.joda.time.LocalDate) cannot be referenced from a static context

...and this is where things get weird. JAXB generates a class Adapter1 that contains the following:

……这就是事情变得奇怪的地方。JAXB 生成一个类 Adapter1,其中包含以下内容:

public class Adapter1
    extends XmlAdapter<String, LocalDate>
{


    public LocalDate unmarshal(String value) {
        return (my.classes.adapters.DateAdapter.unmarshal(value));
    }

    public String marshal(LocalDate value) {
        return (my.classes.adapters.DateAdapter.marshal(value));
    }

}

....which is the source of the compilation error.

....这是编译错误的来源。

Now, my questions are:

现在,我的问题是:

  • being that my adapter is overriding XmlAdapter, I cannot make the methods static....how do I avoid this?
  • Can I avoid the generation of Adapter1.class altogether?? Maybe using package-level annotation XmlJavaTypeAdapters, and if so, how do I do it exactly?? (JAXB generates already a package-info.java of its own....)
  • 因为我的适配器覆盖了 XmlAdapter,所以我不能使方法静态......我该如何避免这种情况?
  • 我可以完全避免 Adapter1.class 的生成吗??也许使用包级注释 XmlJavaTypeAdapters,如果是这样,我该怎么做?(JAXB 已经生成了自己的 package-info.java ......)

Hope I made my situation clear.
Thanks

希望我把我的情况说清楚了。
谢谢

采纳答案by Wilhelm Kleu

You do not need to extend XmlAdapter.

您不需要扩展XmlAdapter.

Just create static methods on a POJO and it will work.

只需在 POJO 上创建静态方法即可。

Example:

例子:

 public class DateAdapter {
    private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");

    public static LocalDate unmarshal(String v) throws Exception {
        return fmt.parseLocalDate(v);
    }

    public static String marshal(LocalDate v) throws Exception {
        return v.toString("yyyyMMdd");
    }
 }

回答by Sylvain

I was in a WSDL first context: no java at all, just generate a CXF Client from a provided WSDL.

我在 WSDL 优先上下文中:根本没有 java,只是从提供的 WSDL 生成一个 CXF 客户端。

I was stuck with the ugly Adapter1.javafor a long time, but I found the solution there.

我被丑陋困住Adapter1.java了很长时间,但我在那里找到了解决方案。

You will use a custom XMLAdapter like already explained.

您将使用已经解释过的自定义 XMLAdapter。

The key of this problem was adding the xjcextension to the global binding file:

这个问题的关键是xjc在全局绑定文件中添加扩展名:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
 xmlns:xs="http://www.w3.org/2001/XMLSchema" 
 xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
 jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1">
    <jaxb:globalBindings>
       <xjc:javaType adapter="com.xxx.tools.xjc.DateAdapter" 
        name="java.util.Date" xmlType="xs:dateTime" />
    </jaxb:globalBindings>
</jaxb:bindings>

xjcextension allow the usage of xjc:javaTypethat accept adapterparameter. No more static method required !

xjc扩展允许使用xjc:javaType该接受适配器参数。不再需要静态方法!

Notethis seems to work with jaxb 2.1+ only.

请注意,这似乎仅适用于 jaxb 2.1+。

回答by Andrej Herich

You do not need to extend XmlAdapterand with Joda-Time v2, you do not even need to implement static methods, as they are already provided.

您不需要扩展XmlAdapter,使用 Joda-Time v2,您甚至不需要实现静态方法,因为它们已经提供。

<jaxb:javaType xmlns="http://java.sun.com/xml/ns/jaxb" 
    name="org.joda.time.LocalDate"
    xmlType="xs:date"
    parseMethod="org.joda.time.LocalDate.parse"
    printMethod="java.lang.String.valueOf"
/>

See JAXB datatype converters for xs:date xs:time and xs:dateTime

请参阅xs:date xs:time 和 xs:dateTime 的 JAXB 数据类型转换器

回答by ramsinb

You are extending XmlAdapterwhich is used when you want to annotation your Java model for JaxB, that is through the annotation @XmlJavaTypeAdapter(Adapter1.class). For your case you just need a class with static methods that does not extend XmlAdapter. You will need the parse method (take a string and return date) and print method (take a date and return a string) and that's about it.

XmlAdapter当您想要为 JaxB 注释 Java 模型时,您正在扩展which ,即通过 annotation @XmlJavaTypeAdapter(Adapter1.class)。对于您的情况,您只需要一个带有不扩展的静态方法的类XmlAdapter。您将需要 parse 方法(获取字符串并返回日期)和打印方法(获取日期并返回字符串),仅此而已。

回答by raisercostin

I found this solution as useful http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html

我发现这个解决方案很有用 http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html

You will create an adapter

您将创建一个适配器

package blog.jodatime;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;

public class DateTimeAdapter 
    extends XmlAdapter<String, DateTime>{

    public DateTime unmarshal(String v) throws Exception {
        //return new DateTime(v); - old solution that didn't properly handled the timezone
        return DateTime.parse(v);
    }

    public String marshal(DateTime v) throws Exception {
        return v.toString();
    }

}

Then register it with annotations by defining a blog/jodatime/package-info.java in your sources

然后通过在你的源代码中定义一个 blog/jodatime/package-info.java 来注册它

@XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(type = DateTime.class, value = JodaDateTimeJaxbAdapter.class) })
package blog.jodatime;

import javax.xml.bind.annotation.adapters.*;

import org.joda.time.*;

Then you should expect that the serialization of DateTime is done without any other changes, just don't forget to annotate your class with @XmlRootElement.

然后您应该期望 DateTime 的序列化完成而没有任何其他更改,只是不要忘记使用 @XmlRootElement 注释您的类。

回答by bdoughan

When generating XmlAdapters from an XML schema you need to put the logic for the conversion in static methods not in an XmlAdapter. This is so an XmlAdapterthat leverages that logic can be generated. I recognize that this is an odd mechanism.

从 XML 架构生成 XmlAdapter 时,您需要将转换逻辑放在静态方法中,而不是放在XmlAdapter. 这就是XmlAdapter利用可以生成的逻辑。我承认这是一种奇怪的机制。

Complete Example

完整示例

回答by luckyluke

A complete example. This is your bindings.xml:

一个完整的例子。这是您的 bindings.xml:

<jaxws:bindings wsdlLocation="YourWsdl"
      xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
      jxb:extensionBindingPrefixes="xjc">
    <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='YourTargetNameSpace']">
       <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
          <xjc:javaType adapter="com.xxx.your.package.DateAdapter" name="java.util.Date" xmlType="xs:dateTime" />
       </jxb:globalBindings>
    </jaxws:bindings>
</jaxws:bindings>

plus the Java Class:

加上 Java 类:

package com.yourpackage;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date>
{

    @Override
    public Date unmarshal(final String date) {
        return DatatypeConverter.parseDate(date).getTime();
    }

    @Override
    public String marshal(final Date date)
    {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        return DatatypeConverter.printDate(calendar);
    }

}

plus the pom.xml definition:

加上 pom.xml 定义:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <dependencies>
        <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-basics</artifactId>
            <version>0.6.4</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
                <defaultOptions>
                    <autoNameResolution>true</autoNameResolution>
                </defaultOptions>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>${basedir}/src/main/resources/your.wsdl</wsdl>
                        <extraargs>
                            <extraarg>-verbose</extraarg>
                            <extraargs>-xjc-npa</extraargs>
                            <extraarg>-xjc-Xsetters</extraarg>
                        </extraargs>
                        <bindingFiles>
                        <bindingFile>${basedir}/src/main/resources/binding.xml</bindingFile>
                        </bindingFiles>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>