4
Vote

WCF generated consumer classes receive null values from Metro 2.3

description

Summary

MetroHello WebService

I previously posted this issue on the Metro issue tracking page.

This is a simple jax-ws bottom-up WebService implementation that produces a bug in Metro 2.3 and WCF.

The issue occurs when a WCF consumer class receives an object from the endpoint that contains a nested class instance whose name matches that of the class: it comes back null.

MetroHello.java

package com.michaelt.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface MetroHello {
    
    @WebMethod Hello getNewHello();
    
    @WebMethod Hello sayHelloWorld(Hello hello);

}
When sayHelloWorld method below sends the Hello object back to WCF consumer, its "world" member variable is null.

MetroHelloImpl.java

package com.michaelt.ws;

import javax.jws.WebService;

@WebService(endpointInterface="com.michaelt.ws.MetroHello")
public class MetroHelloImpl implements MetroHello {
    
    @Override
    public Hello getNewHello() {
        return new Hello();
    }
    
    @Override
    public Hello sayHelloWorld(Hello pHello) {
        pHello.world.message = "Hello World";
        return pHello;
    }
    
}
The problem arises when there is a nested class instance whose name matches the class like the example of "World world" below.

Hello.java

package com.michaelt.ws;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Hello {
    
    // The endpoint will always return this as null
    public World world = new World();
    
}
When "world" is renamed to anything else, it does not return null.

World.java

World.java

package com.michaelt.ws;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class World {
    
    public String message;
    
}

Cause

Metro 2.3 vs. Metro 2.0.1

In this scenario, the cause of the problem can be found in the .xsd's generated by Metro. This issue doesn't exist in older Metro versions, and it has to do with the xml definition of the nested class being referenced in version 2.3. Notice the difference inside the body of the <sequence> tag between the two versions.

Metro 2.3

<xs:schema version="1.0" targetNamespace="http://ws.michaelt.com/">
    <xs:element name="hello" type="tns:hello"/>
    <xs:element name="world" type="tns:world"/>
    <xs:complexType name="hello">
        <xs:sequence>
            <xs:element ref="tns:world" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="world">
        <xs:sequence>
            <xs:element name="message" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
The ref attribute in 2.3 is possibly confused by member variable "world"?

Metro 2.0.1

<xs:schema version="1.0" targetNamespace="http://ws.michaelt.com/">
    <xs:element name="hello" type="tns:hello"/>
    <xs:element name="world" type="tns:world"/>
    <xs:complexType name="hello">
        <xs:sequence>
            <xs:element name="world" type="tns:world" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="world">
        <xs:sequence>
            <xs:element name="message" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

file attachments

comments