1

History

I am generating Java classes from a schema not under my control. I am exporting it to a jar that is a dependency for a web service project. This works correctly. I attempted to add a custom binding to marshal and unmarshal xs:date and xs:dateTime as instances of org.joda.DateTime instead of XMLGregorianCalendar. I am able to generate the jar, compile it within the webservice, and deploy without issue. Once deployed however, the XML requests that previously worked, now throw the following exception:

unexpected element (uri:"", local:"ElementName"). Expected elements are <{schemaNamespace}ElementName>

This exception does not occur at the root element. Several earlier instances of xs:date and xs:dateTime are parsed without issue, the exception first appears on a complex type that contains an xs:date.

Here's an example of the XML structure:

<soap:Envelope xmlns:ns="webServiceNamespace">
    <soap:Body>
        <request>
           <root>
                  <child1>
                       <Date /> <--Works fine.
                       <childList>
                             <childListElement> <-- Exception thrown on this element.
                                  <Date />
                             </childListElement>
                        </childList>
                  </child1>
             </root>
       </request>
    </soap:Body>
</soap:Envelope>

The webServiceNamespace and schemaNamespace are different, but previously only the one was required in the soap envelope.

Question

Why, after adding a custom binding, is the parser asking me to put a namespace on only a handful of parent elements who have a child affected by the custom binding ?

BindingAdapter

 package myPackage;

 @XmlTransient
 public class JodaDateTimeAdapter extends XmlAdapter<String, DateTime> {

    private static final DateTimeFormatter XML_DATE_FORMAT = ISODateTimeFormat.dateTimeNoMillis();

    @Override
    public DateTime unmarshal(String date) throws Exception {
        return XML_DATE_FORMAT.parseDateTime(date);
    }

    @Override
    public String marshal(DateTime dateTime) throws Exception {
        return XML_DATE_FORMAT.print(dateTime);
    }
 }

Binding.xjb

 <?xml version="1.0" encoding="UTF-8"?>
 <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"
                xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb           http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
                jaxb:extensionBindingPrefixes="xjc"
                version="2.1" >
     <jaxb:globalBindings>
         <xjc:javaType name="org.joda.time.DateTime" xmlType="xs:dateTime" adapter="myPackage.JodaDateTimeAdapter" />
         <xjc:javaType name="org.joda.time.DateTime" xmlType="xs:date" adapter="myPackage.JodaDateAdapter" />
     </jaxb:globalBindings>
 </jaxb:bindings>

POM.xml(relevant bits anyway)

 <project>
     ...
     <build>
         <pluginManagement>
             <plugins>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
                     <configuration>
                         <source>1.7</source>
                         <target>1.7</target>
                     </configuration>
                 </plugin>
             </plugins>
         </pluginManagement>
         <plugins>
             ...
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>jaxb2-maven-plugin</artifactId>
                 <version>1.6</version>
                 <executions>
                     ...
                         <execution>
                         <id>generateSchema</id>
                         <goals>
                             <goal>xjc</goal>
                         </goals>
                         <configuration>
                             <packageName>myPackage</packageName>
                             ...
                             <extension>true</extension>
                             <arguments>-no-header -Xxew</arguments>
                             <bindingDirectory>src/main/bindings</bindingDirectory>
                             <bindingFiles>JodaBinding.xjb</bindingFiles>
                         </configuration>     
                     </execution>           
                 </executions>
                 <dependencies>
                <dependency>
                        <groupId>com.github.jaxb-xew-plugin</groupId>
                        <artifactId>jaxb-xew-plugin</artifactId>
                        <version>RELEASE</version>
                    </dependency>            
                 </dependencies>
             </plugin>
         </plugins>
     </build>
 </project>

Comments

I want to stress that this works perfectly fine without the binding, as far as I can tell the generated class files are identical (except for the extra annotations specific to wrappers). The xml used in the SOAP request is valid for the WSDL generated by the web service, and the WSDL is the same whether or not I use a custom binding. Only elements who have are a member of a collection and have a child with a date require the schema namespace. Lastly, once I provide the namespaces in my request, the response puts the request object in the webServiceNamespace and all the children other than the schema-defined root in the schemaNamespace. Previously the entire response was in the webServiceNamespace.

Clearly the addition of the custom binding is doing something wonky (technical term) with the namespace resolution, but I'm not well versed enough in the topic to make any headway.

Suggestions ?

Update: Removing the XEW plugin for pretty-collections generation did not affect this issue.

Update: This is an example of a class containing a date before the binding and after. This is the only property to change:

Before

 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "QuestionAnswerType", propOrder = {
     "question",
     "answer",
     "questionDate"
 })
 public class QuestionAnswerType {

     @XmlElement(name = "Question")
     protected String question;
     @XmlElement(name = "Answer")
     protected String answer;
     @XmlElement(name = "QuestionDate")
     @XmlSchemaType(name = "date")
     protected XMLGregorianCalendar questionDate;
      ...

After

 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "QuestionAnswerType", propOrder = {
     "question",
     "answer",
     "questionDate"
 })
 public class QuestionAnswerType {

     @XmlElement(name = "Question")
     protected String question;
     @XmlElement(name = "Answer")
     protected String answer;
     @XmlElement(name = "QuestionDate", type = String.class)
     @XmlJavaTypeAdapter(JodaDateAdapter.class)
     @XmlSchemaType(name = "date")
     protected DateTime questionDate;
      ...

Update: This works without issue if I execute the build against a schema with no namespace. Obviously not the fix, but a workaround for now.

dma_k
  • 10,431
  • 16
  • 76
  • 128
JHarnach
  • 3,944
  • 7
  • 43
  • 48
  • Can you diff the Java sources with/without customization? What exactly is different? `xjc:javaType` should actually only add the adapter. Either something else is changed (you should be able to see it in the diff) or an additional annotation produces the error. Either way this will make the problem more specific. – lexicore Nov 19 '14 at 06:39
  • @lexicore I've updated the question to show what annotations changed. Thanks – JHarnach Nov 19 '14 at 16:01
  • And nothing else? Strange. Did you run the full dif on directories or just on files? Is `package-info.java` the same? Sorry, I'm puzzled. – lexicore Nov 19 '14 at 16:04
  • @lexicore package-info is the same yes. This also happens if I suppress generating package-info and let each property get a namespace annotation. The diff was on the jars that I created from the build. Each occurrence of an XMLGregorianCalendar now has this annotation. – JHarnach Nov 19 '14 at 16:07
  • Puzzling. Looks like a bug - but plenty of people actualy customize date/time using JodaTime. Try creating an isolated test case (just a test with inner static classes, with and without adapter). I'll run it the to confirm (or not) the bug theory. – lexicore Nov 19 '14 at 16:13
  • @JHarnach: `jaxb-xew-plugin` had problems with namespaces, try using latest (v1.3) version. But if you say it does not depend on `Xew` activation, maybe you could share the piece of XSD that triggered the problem (or complete tiny project to reproduce the problem)? – dma_k Jan 18 '16 at 11:23

0 Answers0