You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Arnold Morein <ar...@me.com.INVALID> on 2018/10/17 22:06:06 UTC

Tweaking cxf-codegen-plugin Java class generation using binding file – duplicate annotation injected

 CXF: 3.1.10
JDK 1.8
Tomcat 8.0.18
 
I have a situation with a WSDL that is very terse and the resultant stubs, though they compile in the WSDL’s JAR project, cannot be used in the main application’s WAR project.
 
The WSDL’s single message structure is like this:
 
Message
----(2 string attributes)
--Header
----(4 string attributes)
--Body
----(sequence)
------Request
--------(xsd:any)
------Response
--------(xsd:any)
 
The first problem was that the classes weren’t serializable. So I started building a binding file to add that aspect. That part was easy.
 
But the Header, Body, Response, and Request classes are generated as internal static sub-classes of Message (because in the WSDL schema section, they are all internal to the Message).
 
When CXF tries to marshal a call to the service, an exception occurs saying:
 
org.apache.cxf.interceptor.Fault: Marshalling Error: unable to marshal type "a.b.Message$Header" as an element because it is missing an @XmlRootElement annotation
 
The Message class has an @XmlRootElement annotation, but not the subclasses. The class looks like this:
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "content"
})
@XmlRootElement(name = "TLETSMessage")
public class TLETSMessage
    implements Serializable
{
 
    private final static long serialVersionUID = 1L;
    @XmlElementRefs({
        @XmlElementRef(name = "Header", type = JAXBElement.class),
        @XmlElementRef(name = "Body", type = JAXBElement.class)
    })
    @XmlMixed
    protected List<Serializable> content;
    @XmlAttribute(name = "key", required = true)
    protected String key;
    @XmlAttribute(name = "version", required = true)
    protected String version;
 
    public List<Serializable> getContent() {
        if (content == null) {
            content = new ArrayList<Serializable>();
        }
        return this.content;
    }
…
 
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "request",
        "response"
    })
    public static class Body
        implements Serializable
    {
 
        private final static long serialVersionUID = 1L;
        @XmlElement(name = "Request", required = true)
        protected TLETSMessage.Body.Request request;
        @XmlElement(name = "Response")
        protected TLETSMessage.Body.Response response;
 
        public TLETSMessage.Body.Request getRequest() {
            return request;
        }
 
        public void setRequest(TLETSMessage.Body.Request value) {
            this.request = value;
        }
 
        public TLETSMessage.Body.Response getResponse() {
            return response;
        }
…
 
I then added entries to the binding file and pom.xml to add the @XmlRootElement annotation to the Header and Body classes:
 
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb <http://java.sun.com/xml/ns/jaxb>"
    xmlns:annox="http://annox.dev.java.net <http://annox.dev.java.net/>" extensionBindingPrefixes="xjc annox"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc <http://java.sun.com/xml/ns/jaxb/xjc>"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/ <http://schemas.xmlsoap.org/wsdl/>" version="2.1"
> 
    <globalBindings>
        <serializable uid="1" />
    </globalBindings>
 
    <bindings schemaLocation="META-INF/DMVService.wsdl#types1"
        node="/xsd:schema"
    >
 
   <!-- Annotate the following classes with XmlRootElement -->
        <bindings node="//xsd:element[@name='Header']">
            <annox:annotate>
                <annox:annotate
                    annox:class="javax.xml.bind.annotation.XmlRootElement"
                    name="Header" />
            </annox:annotate>
        </bindings>
 
        <bindings node="//xsd:element[@name='Body']">
            <annox:annotate>
                <annox:annotate
                    annox:class="javax.xml.bind.annotation.XmlRootElement"
                    name="Body" />
            </annox:annotate>
        </bindings>
 
    </bindings>
 
</bindings>
 
And I thought I had it done, but what is generated is wrong, the annotation is put on a method that isn’t explicit in the WSDL so I guess a generic one was generated.
 
    @XmlRootElement(name = "Body")
    public List<Serializable> getContent() {
        if (content == null) {
            content = new ArrayList<Serializable>();
        }
        return this.content;
    }
 
But not where I hoped it would be:
 
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "request",
        "response"
    })
    public static class Body
        implements Serializable
    {
 
Here is an extract from the WSDL, hopefully someone can tell me how to fix the binding?
 
    <wsdl:types>
        <xsd:schema xmlns="http://www.openfox.com <http://www.openfox.com/>"
            targetNamespace="http://www.openfox.com <http://www.openfox.com/>"
        >
<!-- TLETSMessage -->
            <xsd:element name="TLETSMessage">
                <xsd:complexType mixed="true">
                    <xsd:sequence>
      <!-- Header -->
                        <xsd:element name="Header">
                            <xsd:complexType>
                                <xsd:sequence>
        <!-- Initiator -->
                                    <xsd:element name="Initiator">
                                        <xsd:simpleType>
                                            <xsd:restriction
                                                base="xsd:string"
                                            >
                                                <xsd:maxLength
                                                    value="9"
                                                ></xsd:maxLength>
                                                <xsd:minLength
                                                    value="4"
                                                ></xsd:minLength>
                                            </xsd:restriction>
                                        </xsd:simpleType>
                                    </xsd:element>
 
        <!-- Destination -->
                                    <xsd:element name="Destination">
                                        <xsd:simpleType>
                                            <xsd:restriction
                                                base="xsd:string"
                                            >
                                                <xsd:maxLength
                                                    value="9"
                                                ></xsd:maxLength>
                                                <xsd:minLength
                                                    value="2"
                                                ></xsd:minLength>
                                            </xsd:restriction>
                                        </xsd:simpleType>
                                    </xsd:element>
 
        <!-- ControlField -->
                                    <xsd:element name="ControlField">
                                        <xsd:simpleType>
                                            <xsd:restriction
                                                base="xsd:string"
                                            >
            <!--xsd:pattern value="\d{6}"/-->
                                                <xsd:length
                                                    value="10"
                                                ></xsd:length>
                                            </xsd:restriction>
                                        </xsd:simpleType>
                                    </xsd:element>
 
        <!-- UserId -->
                                    <xsd:element name="UserId">
                                        <xsd:simpleType>
                                            <xsd:restriction
                                                base="xsd:string"
                                            >
                                                <xsd:length value="7"></xsd:length>
                                            </xsd:restriction>
                                        </xsd:simpleType>
                                    </xsd:element>
                                </xsd:sequence>
                            </xsd:complexType>
                        </xsd:element> <!-- end Header -->
 
      <!-- Body -->
                        <xsd:element name="Body">
                            <xsd:complexType>
                                <xsd:sequence>
                                    <xsd:element name="Request">
                                        <xsd:complexType>
                                            <xsd:sequence>
                                                <xsd:any></xsd:any>
                                            </xsd:sequence>
                                        </xsd:complexType>
                                    </xsd:element>
                                    <xsd:element name="Response"
                                        minOccurs="0" maxOccurs="1"
                                    >
                                        <xsd:complexType>
                                            <xsd:sequence>
                                                <xsd:any></xsd:any>
                                            </xsd:sequence>
                                        </xsd:complexType>
                                    </xsd:element>
                                </xsd:sequence>
                            </xsd:complexType>
                        </xsd:element>
                    </xsd:sequence>
     <!-- TLETSMessage attributes -->
                    <xsd:attribute name="key" type="xsd:string"
                        use="required"
                    ></xsd:attribute>
                    <xsd:attribute name="version"
                        type="xsd:string" use="required"
                    ></xsd:attribute>
                </xsd:complexType>
            </xsd:element> <!-- end TLETSMessage -->
        </xsd:schema>

Re: Tweaking cxf-codegen-plugin Java class generation using binding file – duplicate annotation injected

Posted by Daniel Kulp <dk...@apache.org>.
I don’t think it’s possible that that would be a valid WSDL.    The element tags for the message parts must point to a top level element.   It cannot point to a child element of another structure.    

Any chance to see the full WSDL as well as the code you are using to try and invoke on the service?   I assume you are using the generated stubs.   With that schema, the method signature for the method SHOULD be something like:

TLETSMessge doFoo(TLETSMessge msg);

And you’d have to construct the full TLETSMessage object to pass in.

Dan




> On Oct 17, 2018, at 6:06 PM, Arnold Morein <ar...@me.com.INVALID> wrote:
> 
> 
> CXF: 3.1.10
> JDK 1.8
> Tomcat 8.0.18
> 
> I have a situation with a WSDL that is very terse and the resultant stubs, though they compile in the WSDL’s JAR project, cannot be used in the main application’s WAR project.
> 
> The WSDL’s single message structure is like this:
> 
> Message
> ----(2 string attributes)
> --Header
> ----(4 string attributes)
> --Body
> ----(sequence)
> ------Request
> --------(xsd:any)
> ------Response
> --------(xsd:any)
> 
> The first problem was that the classes weren’t serializable. So I started building a binding file to add that aspect. That part was easy.
> 
> But the Header, Body, Response, and Request classes are generated as internal static sub-classes of Message (because in the WSDL schema section, they are all internal to the Message).
> 
> When CXF tries to marshal a call to the service, an exception occurs saying:
> 
> org.apache.cxf.interceptor.Fault: Marshalling Error: unable to marshal type "a.b.Message$Header" as an element because it is missing an @XmlRootElement annotation
> 
> The Message class has an @XmlRootElement annotation, but not the subclasses. The class looks like this:
> 
> @XmlAccessorType(XmlAccessType.FIELD)
> @XmlType(name = "", propOrder = {
>    "content"
> })
> @XmlRootElement(name = "TLETSMessage")
> public class TLETSMessage
>    implements Serializable
> {
> 
>    private final static long serialVersionUID = 1L;
>    @XmlElementRefs({
>        @XmlElementRef(name = "Header", type = JAXBElement.class),
>        @XmlElementRef(name = "Body", type = JAXBElement.class)
>    })
>    @XmlMixed
>    protected List<Serializable> content;
>    @XmlAttribute(name = "key", required = true)
>    protected String key;
>    @XmlAttribute(name = "version", required = true)
>    protected String version;
> 
>    public List<Serializable> getContent() {
>        if (content == null) {
>            content = new ArrayList<Serializable>();
>        }
>        return this.content;
>    }
> …
> 
>    @XmlAccessorType(XmlAccessType.FIELD)
>    @XmlType(name = "", propOrder = {
>        "request",
>        "response"
>    })
>    public static class Body
>        implements Serializable
>    {
> 
>        private final static long serialVersionUID = 1L;
>        @XmlElement(name = "Request", required = true)
>        protected TLETSMessage.Body.Request request;
>        @XmlElement(name = "Response")
>        protected TLETSMessage.Body.Response response;
> 
>        public TLETSMessage.Body.Request getRequest() {
>            return request;
>        }
> 
>        public void setRequest(TLETSMessage.Body.Request value) {
>            this.request = value;
>        }
> 
>        public TLETSMessage.Body.Response getResponse() {
>            return response;
>        }
> …
> 
> I then added entries to the binding file and pom.xml to add the @XmlRootElement annotation to the Header and Body classes:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <bindings xmlns="http://java.sun.com/xml/ns/jaxb <http://java.sun.com/xml/ns/jaxb>"
>    xmlns:annox="http://annox.dev.java.net <http://annox.dev.java.net/>" extensionBindingPrefixes="xjc annox"
>    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc <http://java.sun.com/xml/ns/jaxb/xjc>"
>    xmlns:xsd="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>"
>    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/ <http://schemas.xmlsoap.org/wsdl/>" version="2.1"
>> 
>    <globalBindings>
>        <serializable uid="1" />
>    </globalBindings>
> 
>    <bindings schemaLocation="META-INF/DMVService.wsdl#types1"
>        node="/xsd:schema"
>> 
> 
>   <!-- Annotate the following classes with XmlRootElement -->
>        <bindings node="//xsd:element[@name='Header']">
>            <annox:annotate>
>                <annox:annotate
>                    annox:class="javax.xml.bind.annotation.XmlRootElement"
>                    name="Header" />
>            </annox:annotate>
>        </bindings>
> 
>        <bindings node="//xsd:element[@name='Body']">
>            <annox:annotate>
>                <annox:annotate
>                    annox:class="javax.xml.bind.annotation.XmlRootElement"
>                    name="Body" />
>            </annox:annotate>
>        </bindings>
> 
>    </bindings>
> 
> </bindings>
> 
> And I thought I had it done, but what is generated is wrong, the annotation is put on a method that isn’t explicit in the WSDL so I guess a generic one was generated.
> 
>    @XmlRootElement(name = "Body")
>    public List<Serializable> getContent() {
>        if (content == null) {
>            content = new ArrayList<Serializable>();
>        }
>        return this.content;
>    }
> 
> But not where I hoped it would be:
> 
>    @XmlAccessorType(XmlAccessType.FIELD)
>    @XmlType(name = "", propOrder = {
>        "request",
>        "response"
>    })
>    public static class Body
>        implements Serializable
>    {
> 
> Here is an extract from the WSDL, hopefully someone can tell me how to fix the binding?
> 
>    <wsdl:types>
>        <xsd:schema xmlns="http://www.openfox.com <http://www.openfox.com/>"
>            targetNamespace="http://www.openfox.com <http://www.openfox.com/>"
>> 
> <!-- TLETSMessage -->
>            <xsd:element name="TLETSMessage">
>                <xsd:complexType mixed="true">
>                    <xsd:sequence>
>      <!-- Header -->
>                        <xsd:element name="Header">
>                            <xsd:complexType>
>                                <xsd:sequence>
>        <!-- Initiator -->
>                                    <xsd:element name="Initiator">
>                                        <xsd:simpleType>
>                                            <xsd:restriction
>                                                base="xsd:string"
>> 
>                                                <xsd:maxLength
>                                                    value="9"
>> </xsd:maxLength>
>                                                <xsd:minLength
>                                                    value="4"
>> </xsd:minLength>
>                                            </xsd:restriction>
>                                        </xsd:simpleType>
>                                    </xsd:element>
> 
>        <!-- Destination -->
>                                    <xsd:element name="Destination">
>                                        <xsd:simpleType>
>                                            <xsd:restriction
>                                                base="xsd:string"
>> 
>                                                <xsd:maxLength
>                                                    value="9"
>> </xsd:maxLength>
>                                                <xsd:minLength
>                                                    value="2"
>> </xsd:minLength>
>                                            </xsd:restriction>
>                                        </xsd:simpleType>
>                                    </xsd:element>
> 
>        <!-- ControlField -->
>                                    <xsd:element name="ControlField">
>                                        <xsd:simpleType>
>                                            <xsd:restriction
>                                                base="xsd:string"
>> 
>            <!--xsd:pattern value="\d{6}"/-->
>                                                <xsd:length
>                                                    value="10"
>> </xsd:length>
>                                            </xsd:restriction>
>                                        </xsd:simpleType>
>                                    </xsd:element>
> 
>        <!-- UserId -->
>                                    <xsd:element name="UserId">
>                                        <xsd:simpleType>
>                                            <xsd:restriction
>                                                base="xsd:string"
>> 
>                                                <xsd:length value="7"></xsd:length>
>                                            </xsd:restriction>
>                                        </xsd:simpleType>
>                                    </xsd:element>
>                                </xsd:sequence>
>                            </xsd:complexType>
>                        </xsd:element> <!-- end Header -->
> 
>      <!-- Body -->
>                        <xsd:element name="Body">
>                            <xsd:complexType>
>                                <xsd:sequence>
>                                    <xsd:element name="Request">
>                                        <xsd:complexType>
>                                            <xsd:sequence>
>                                                <xsd:any></xsd:any>
>                                            </xsd:sequence>
>                                        </xsd:complexType>
>                                    </xsd:element>
>                                    <xsd:element name="Response"
>                                        minOccurs="0" maxOccurs="1"
>> 
>                                        <xsd:complexType>
>                                            <xsd:sequence>
>                                                <xsd:any></xsd:any>
>                                            </xsd:sequence>
>                                        </xsd:complexType>
>                                    </xsd:element>
>                                </xsd:sequence>
>                            </xsd:complexType>
>                        </xsd:element>
>                    </xsd:sequence>
>     <!-- TLETSMessage attributes -->
>                    <xsd:attribute name="key" type="xsd:string"
>                        use="required"
>> </xsd:attribute>
>                    <xsd:attribute name="version"
>                        type="xsd:string" use="required"
>> </xsd:attribute>
>                </xsd:complexType>
>            </xsd:element> <!-- end TLETSMessage -->
>        </xsd:schema>

-- 
Daniel Kulp
dkulp@apache.org <ma...@apache.org> - http://dankulp.com/blog <http://dankulp.com/blog>
Talend Community Coder - http://talend.com <http://coders.talend.com/>