Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using custom jaxb bindings to get xs:datetime to Joda time but getting XMLGregorianCalender

Java 1.7 Spring 3.1.1 with Spring-WS 2.1.1 Joda Hibernate 3.6 MySQL 5.0.57 Maven 3 Tomcat 7 Eclipse 3.7

Have got the web service deployed and the web client deployed and the web service and web client talking to each other.

But just like in a vintage video game, slaying a batch of dragons just spawns another batch of dragons.

Now it's the whole Joda Datetime xs:dateTime jaxb binding thingy thats spewing fire at me.

Googling turns up lots of solutions which I have tried to follow.

a representative entity

@Entity
@Table(name="form_templates", catalog="mycomp")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class FormTemplate implements java.io.Serializable
{
    private static final long serialVersionUID = 8533964268513480152L;
    ....

    @Column(name="revision_datetime")
    @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
    @XmlElement(name="revisionTimestamp")
    @XmlJavaTypeAdapter(JodaDateTimeAdapter.class)
    @XmlSchemaType(name="dateTime")
    DateTime revisionTimestamp;
    .... 
}

JodaDateTimeAdapter

@XmlTransient
public class JodaDateTimeAdapter extends XmlAdapter<String, DateTime>
{
    private static final DateTimeFormatter XML_DATE_FORMAT =      ISODateTimeFormat.dateTimeNoMillis();  
    private static final DateTimeFormatter XML_DATE_TIME_FORMAT = ISODateTimeFormat.localDateOptionalTimeParser();  
    private static final DateTimeFormatter DATE_PATTERN =         DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");  

    public DateTime unmarshal(String dateStr) throws Exception  
    {   //parsing from schema to java class  
        DateTime result = DATE_PATTERN.parseDateTime(dateStr);  
        return result;  
    }  

    public String marshal(DateTime dateTime) throws Exception  
    {   //printing from java class to schema  
        String result   = DATE_PATTERN.print(dateTime);  
        return result;  
    }  
}

relavent part of pom

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-java2ws-plugin</artifactId>
    <version>${cxfVersion}</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxfVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-simple</artifactId>
            <version>${cxfVersion}</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>process-classes</id>
            <phase>process-classes</phase>
            <configuration>
                <outputFile>src/main/webapp/WEB-INF/wsdl/FormsService.wsdl</outputFile>
                <className>com.mycomp.forms.web.endpoint.FormsEndpoint</className>
                <genWsdl>true</genWsdl>
                <verbose>true</verbose>
            </configuration>
            <goals>
                <goal>java2ws</goal>
            </goals>
        </execution>
    </executions>
</plugin>

So the web service compiles and deploys successfully. I look in the wsdl and see

...
<xs:complexType name="formTemplate">
    <xs:sequence>
      ...
      <xs:element minOccurs="0" name="revisionTimestamp" type="xs:dateTime"/>
      ...

so it seems I'm headed in the right direction. With the web service deployed I turn my attention to the web client

I compile the web client with this relavent pom snippet

  ...
  <plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxfVersion}</version>
    <executions>
      <execution>
        <id>generate-sources</id>
        <phase>generate-sources</phase>
        <configuration>
          <sourceRoot>${project.build.directory}/generated_sources</sourceRoot>
          <wsdlOptions>
            <wsdlOption>
              <wsdl>http://localhost:8080/dept_forms_webservice/formsService?wsdl</wsdl>
              <bindingFiles>
                <bindingFile>${basedir}/src/main/resources/jaxb-custom-bindings.xml</bindingFile>
              </bindingFiles>
            </wsdlOption>
          </wsdlOptions>
        </configuration>
        <goals>
          <goal>wsdl2java</goal>
        </goals>
      </execution>
    </executions>
  </plugin>     
  ...

and jaxb-custom-bindings.xml located in /src/java/resources

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings wsdlLocation="http://localhost:8080/dept_forms_webservice/formsService?wsdl"
          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">
  <jaxws:bindings>
    <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <jxb:javaType name="org.joda.time.DateTime" xmlType="xs:dateTime"
                      parseMethod="com.mycomp.forms.util.JodaDateTimeAdapter.unmarshall"
                      printMethod="com.mycomp.forms.util.JodaDateTimeAdapter.marshall"/>
    </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>

and everything compiles, sources get generated, web client deploys successfully

BUT

looking in the generated FormTemplate entity I see

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;  // <---- should be joda datetime here

public class FormTemplate
{
    ...
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar revisionTimestamp;   // <-- should be joda datetime here
...

So I've clearly missed some microscopic piece of configuration minutae and would be ever so grateful if someone would point out what is wrong and how to right it.

TIA,

Still-learning Steve

like image 267
user1201168 Avatar asked Sep 29 '22 22:09

user1201168


1 Answers

I used this configuration and works fine.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:annox="http://annox.dev.java.net"
  xmlns:tns="http://esb.tsf.ab.com/enterprise/message"
  xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
  jaxb:extensionBindingPrefixes="xjc annox"
  version="2.1">

  <jaxb:globalBindings>
        <xjc:serializable uid="12343" />
        <jaxb:javaType name="java.util.Date" xmlType="xs:date" printMethod="adapter.DateAdapter.printDate" parseMethod="adapter.DateAdapter.parseDate" />
        <jaxb:javaType name="java.util.Date" xmlType="xs:dateTime" printMethod="adapter.DateTimeAdapter.printDateTime" parseMethod="adapter.DateTimeAdapter.parseDateTime" />
        <jaxb:javaType name="java.util.Date" xmlType="xs:time" printMethod="adapter.TimeAdapter.printTime" parseMethod="adapter.TimeAdapter.parseTime" />
  </jaxb:globalBindings>

</jaxb:bindings>

i use this plugin to generate bean

<plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.8.1</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <args>
                        <arg>-Xannotate</arg>
                        <arg>-nv</arg>
                        <arg>-Xnamespace-prefix</arg>
                    </args>
                    <extension>true</extension>
                    <schemaDirectory>src/main/resources/schema/xsd</schemaDirectory>
                    <schemaIncludes>
                        <schemaInclude>my.xsd</schemaInclude>
                    </schemaIncludes>
                    <bindingDirectory>src/main/resources/schema/xjb</bindingDirectory>
                    <bindingIncludes>
                        <include>*.xjb</include>
                    </bindingIncludes>
                    <debug>true</debug>
                    <verbose>true</verbose>
                    <episode>true</episode>
                    <forceRegenerate>true</forceRegenerate>
                    <plugins>
                        <plugin>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-basics</artifactId>
                            <version>0.6.0</version>
                        </plugin>
                        <plugin>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-basics-annotate</artifactId>
                            <version>0.6.0</version>
                        </plugin>
                        <plugin>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-namespace-prefix</artifactId>
                            <version>1.1</version>
                        </plugin>
                    </plugins>
                </configuration>
            </plugin>

and use this args for wsdl2java

<wsdlOption>
                                    <wsdl>${basedir}/src/main/resources/schema/integration/wsdl/CostPriceMaintenance.wsdl</wsdl>
                                    <extraargs>

                                        <extraarg>-nexclude</extraarg>
                                        <extraarg>http://namespace</extraarg>

                                    </extraargs>
                                </wsdlOption>

try to use this configuration, you have a additional.

<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings 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">

    <jxb:globalBindings>
        <jxb:javaType name="org.joda.time.DateTime" xmlType="xs:dateTime"
                      parseMethod="com.mycomp.forms.util.JodaDateTimeAdapter.unmarshall"
                      printMethod="com.mycomp.forms.util.JodaDateTimeAdapter.marshall"/>
    </jxb:globalBindings>

</jxb:bindings>
like image 168
Xstian Avatar answered Oct 04 '22 03:10

Xstian