WSDL customization: XMLGregorianCalender to java.u

2019-06-20 14:24发布

问题:

I have several wsdl files almost hundreds. Whenever I create client jaxb client classes for them the Jaxb automatically maps all the date/time fields to XMLGregorianCalender. After a lot of googling, I found out providing a separate binding file is the only solution.

I don't want to provide the wsdl location, since I've so many, as otherwise I'd have to create a separate binding files for each wsdl.

Below is the binding file I used.

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" >
    <globalBindings>
        <javaType name="java.util.Date" xmlType="xsd:dateTime"  />
    </globalBindings>
</bindings>

It created the jaxb classes with Date types but it also created an adapter called Adapter1.java automatically which was put in which I don't want. I've my own package structure and can't deviate from it.

org.w3._2001.xmlschema

and this adapter converts the date from String to java.util.Date and my application fails as the converter should convert from XMLGregorianCalender to java.util.Date

So, I wrote an Adapter myself

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

import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import java.util.Calendar;
import javax.xml.bind.annotation.adapters.XmlAdapter;



public class DateAdapter extends XmlAdapter<XMLGregorianCalendar, Date> {

    @Override
    public XMLGregorianCalendar marshal(Date date) throws Exception {
        GregorianCalendar gregorianCalendar = new GregorianCalendar();
        gregorianCalendar.setTime(date);
        XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar);
        return xmlGregorianCalendar;
    }

    @Override
    public Date unmarshal(XMLGregorianCalendar xmlGregorianCalendar) throws Exception {
        return xmlGregorianCalendar.toGregorianCalendar().getTime();
    }

}

and changed my customization file like this:

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" >
    <globalBindings>
        <javaType name="java.util.Date" xmlType="xsd:dateTime"
        parseMethod="DateAdapter.marshal"
            printMethod="DateAdapter.unmarshal" />
    </globalBindings>
</bindings>

Then I ran the wsimport tool and it failed.

C:\Users\stuart\Desktop\code>wsimport -s src -d gen -b cust.txt http://localhost:8080/webservice-jaxws/DummyService?wsdl


parsing WSDL...


generating code...


compiling code...

C:\Users\stuart\Desktop\code\src\org\w3\_2001\xmlschema\Adapter1.java:13: cannot find symbol
symbol  : variable DateAdapter
location: class org.w3._2001.xmlschema.Adapter1
        return (DateAdapter.marshal(value));
                ^
C:\Users\stuart\Desktop\code\src\org\w3\_2001\xmlschema\Adapter1.java:17: cannot find symbol
symbol  : variable DateAdapter
location: class org.w3._2001.xmlschema.Adapter1
        return (DateAdapter.unmarshal(value));
                ^
2 errors
compilation failed, errors should have been reported

And I kept my customization settings in cust.txt as given in wsimport command, and my DateAdapter class source file was also in the same directory. The class was without package. The following is my directory structure.

³   cust.txt
³   DateAdapter.java
³   
ÃÄÄÄgen
³   ÃÄÄÄorg
³   ³   ÀÄÄÄw3
³   ³       ÀÄÄÄ_2001
³   ³           ÀÄÄÄxmlschema
³   ³                   Adapter1.class
³   ³                   
³   ÀÄÄÄwebservice
³       ÀÄÄÄjaxws
³           ÀÄÄÄgenerated
³                   GetBook.class
³                   GetBookResponse.class
³                   ObjectFactory.class
³                   package-info.class
³                   Book.class
³                   BookService.class
³                   BookServiceImpl.class
³                   ReturnBook.class
³                   ReturnBookResponse.class
³                   
ÀÄÄÄsrc
    ÃÄÄÄorg
    ³   ÀÄÄÄw3
    ³       ÀÄÄÄ_2001
    ³           ÀÄÄÄxmlschema
    ³                   Adapter1.java
    ³                   
    ÀÄÄÄwebservice
        ÀÄÄÄjaxws
            ÀÄÄÄgenerated
                    GetBook.java
                    GetBookResponse.java
                    ObjectFactory.java
                    package-info.java
                    Book.java
                    BookService.java
                    BookServiceImpl.java
                    ReturnBook.java
                    ReturnBookResponse.java

回答1:

Solved this by using the same bindings declaration you did except my DateAdapter actually looked like this :

public class DateAdapter {

    private DateAdapter() {}

    public static String marshal(Date date) {
        Calendar cal = GregorianCalendar.getInstance();
        cal.setTime(date);
        return DatatypeConverter.printDateTime(cal);
    }

    public static Date unmarshal(String xmlDate) {
        return DatatypeConverter.parseDate(xmlDate).getTime();
    }
}

And it works like a charm. XML side I have dateTime and java side I have java.util.Date. I actually made another that uses java.time.Instant instead of Date, which I find easier to work with.