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

前端 未结 7 1611
时光说笑
时光说笑 2021-01-11 15:38

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

相关标签:
7条回答
  • 2021-01-11 15:46

    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.

    <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

    0 讨论(0)
  • 2021-01-11 15:48

    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.

    0 讨论(0)
  • 2021-01-11 15:49

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

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

    You will use a custom XMLAdapter like already explained.

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

    <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>
    

    xjc extension allow the usage of xjc:javaType that accept adapter parameter. No more static method required !

    Note this seems to work with jaxb 2.1+ only.

    0 讨论(0)
  • 2021-01-11 15:54

    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.

    Complete Example

    • http://blog.bdoughan.com/2011/08/xml-schema-to-java-generating.html
    0 讨论(0)
  • 2021-01-11 15:55

    A complete example. This is your 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:

    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:

    <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>
    
    0 讨论(0)
  • 2021-01-11 16:01

    You do not need to extend XmlAdapter.

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

    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");
        }
     }
    
    0 讨论(0)
提交回复
热议问题