Используя пользовательские привязки jaxb для получения xs:datetime и Joda time, но получая XMLGregorianCalender

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

Развернут веб-сервис и веб-клиент, а веб-сервис и веб-клиент общаются друг с другом.

Но, как и в старинной видеоигре, убийство группы драконов порождает еще одну партию драконов.

Теперь весь Joda Datetime xs: dateTime jaxb связывает штуку, которая извергает меня в огонь.

Поиск в Google дает множество решений, которым я пытался следовать.

представительная организация

@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;  
    }  
}

относительная часть пом

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

Таким образом, веб-сервис успешно компилируется и развертывается. Я смотрю в WSDL и вижу

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

так что, похоже, я направляюсь в правильном направлении. С развернутым веб-сервисом я переключаю свое внимание на веб-клиент

Я скомпилировал веб-клиент с этим фрагментом кода.

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

и jaxb-custom-bindings.xml, расположенный в /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>

и все компилируется, исходники генерируются, веб-клиент успешно разворачивается

НО

глядя в сгенерированную сущность FormTemplate я вижу

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

Так что я явно пропустил какой-то микроскопический фрагмент конфигурации и был бы очень признателен, если бы кто-то указал, что не так и как это исправить.

ТИА,

Все еще учусь Стив

1 ответ

Я использовал эту конфигурацию и отлично работает.

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

я использую этот плагин для генерации бобов

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

и использовать эти аргументы для wsdl2java

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

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

                                    </extraargs>
                                </wsdlOption>

попробуйте использовать эту конфигурацию, у вас есть дополнительная.

<?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>
Другие вопросы по тегам