JAX-WS MarshalException with custom JAX-B bindings: Unable to marshal type "java.lang.String" as an

Posted by MoneyMark on Stack Overflow See other posts from Stack Overflow or by MoneyMark
Published on 2010-04-13T03:22:58Z Indexed on 2010/04/13 3:33 UTC
Read the original article Hit count: 693

Filed under:
|
|
|
|

I seem to be having an issue with Jax-WS and Jax-b playing nicely together. I need to consume a web-service, which has a predefined WSDL. When executing the generated client I am receiving the following error:

javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an @XmlRootElement annotation]

This started occurring when I used an external custom binding file to map needlessly complex types to java.lang.string. Here is an excerpt from my binding file:

<?xml version="1.0" encoding="UTF-8"?>
  <bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
    <bindings schemaLocation="http://localhost:7777/GESOR/services/RegistryUpdatePort?wsdl#types?schema1" node="/xs:schema">
      <bindings node="//xs:element[@name='StwrdCompany']//xs:complexType//xs:sequence//xs:element[@name='company_name']">
        <property>
          <baseType name="java.lang.String" />
        </property>
      </bindings>
      <bindings node="//xs:element[@name='StwrdCompany']//xs:complexType//xs:sequence//xs:element[@name='address1']">
        <property>
          <baseType name="java.lang.String" />
        </property>
      </bindings>
      <bindings node="//xs:element[@name='StwrdCompany']//xs:complexType//xs:sequence//xs:element[@name='address2']">
        <property>
          <baseType name="java.lang.String" />
        </property>
      </bindings>
      ...more fields
  </bindings>
</bindings>

When executing wsimport against the provided WSDL, StwrdCompany is generated with the following variables declared:

@XmlRootElement(name = "StwrdCompany")
public class StwrdCompany 
{
    @XmlElementRef(name = "company_name", type = JAXBElement.class)
    protected String companyName;
    @XmlElementRef(name = "address1", type = JAXBElement.class)
    protected String address1;
    @XmlElementRef(name = "address2", type = JAXBElement.class)
    ... more fields

    ... getters/setters

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "value"
    })
    public static class CompanyName {

        @XmlValue
        protected String value;
        @XmlAttribute
        protected Boolean updateToNULL;

        /**
         * Gets the value of the value property.
         * 
         * @return
         *     possible object is
         *     {@link String }
         *     
         */
        public String getValue() {
            return value;
        }

        /**
         * Sets the value of the value property.
         * 
         * @param value
         *     allowed object is
         *     {@link String }
         *     
         */
        public void setValue(String value) {
            this.value = value;
        }

        /**
         * Gets the value of the updateToNULL property.
         * 
         * @return
         *     possible object is
         *     {@link Boolean }
         *     
         */
        public boolean isUpdateToNULL() {
            if (updateToNULL == null) {
                return false;
            } else {
                return updateToNULL;
            }
        }

        /**
         * Sets the value of the updateToNULL property.
         * 
         * @param value
         *     allowed object is
         *     {@link Boolean }
         *     
         */
        public void setUpdateToNULL(Boolean value) {
            this.updateToNULL = value;
        }

       ... more inner classes
       }
   }

Finally, here is the associated snippet from the WSDL that seems to be causing such grief.

<xs:element name="StwrdCompany">
  <xs:complexType>
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="company_name" nillable="true">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute default="false" name="updateToNULL" type="xs:boolean"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
      <xs:element maxOccurs="1" minOccurs="0" name="address1" nillable="true">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute default="false" name="updateToNULL" type="xs:boolean"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
      ... more fields in the same format

      <xs:element maxOccurs="1" minOccurs="0" name="p_source_timestamp" nillable="false" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="company_xid" type="xs:string"/>
  </xs:complexType>
</xs:element>

The reason for the custom binding is so I can map user input from a pojo into the StwrdCompany object more easily, whether it be direct instantiation or through the use of Dozer for bean mapping. I was unable to successfully map between the objects without the custom binding.

Finally, one other thing I tried was setting a globalBinding definition:

<globalBindings generateValueClass="false"></globalBindings>  

This caused the server to through an argument mismatch exception since the Soap Message was using xs:string xml types instead of passing the defined complex types, so I abandoned that idea.

Any insight into what is causing the MarshalException or how to go about solving the issue of calling the webservice and mapping these objects more easily, is greatly appreciated. I've been searching for days and I sadly think I am stumped.

© Stack Overflow or respective owner

Related posts about jaxb

Related posts about java