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
JAXB, Custom bindings, Adapter1.class and Joda-time
提问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.java
for 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 xjc
extension 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:javaType
that 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 XmlAdapter
and 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
回答by ramsinb
You are extending XmlAdapter
which 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 XmlAdapter
that 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>