Method overloading with JAX-WS reference implementation

1.4k views Asked by At

Method overloading is not allowed in the WS-I profile. The usual trick seems to be to add @WebMethod(operationName="...") annotations. If I do that, I get a ClassCastException.

Minimal example follows.

Interface:

package org.example.test;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService(name = "service", targetNamespace = "http://www.example.org/test")
public interface IThing {

    @WebMethod(operationName = "f1")
    public String f(String s);

    @WebMethod(operationName = "f2")
    public String f(Integer i);
}

Implementation:

package org.example.test;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService(endpointInterface = "org.example.test.IThing", targetNamespace = "http://www.example.org/test", portName = "ThingPort", serviceName = "service")
public class Thing implements IThing {

    @Override
    @WebMethod(operationName = "f1")
    public String f(String s) {
        return "f1";
    }

    @Override
    @WebMethod(operationName = "f2")
    public String f(Integer i) {
        return "f2";
    }

}

JUnit Test case:

package org.example.test;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import org.junit.Test;

public class TestThing {

    @Test
    public void testThing() throws Exception {
        URL urlURL = new URL("http://localhost:8080/wstest/SOAP");
        QName qname = new QName("http://www.example.org/test", "service");
        Service service = Service.create(urlURL, qname);
        IThing thing = service.getPort(IThing.class);
        thing.f("s");
        thing.f(1);
    }
}

Used JAX-WS implementation:

    compile group:'com.sun.xml.ws', name:'jaxws-rt', version:'2.2.7', transitive:true

Strack trace:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at org.example.test.jaxws.F$JaxbAccessorF_arg0.set(FieldAccessor_Ref.java:60)
    at com.sun.xml.bind.v2.runtime.reflect.Accessor.setUnadapted(Accessor.java:166)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl$6.set(JAXBContextImpl.java:980)
    at com.sun.xml.ws.db.glassfish.RawAccessorWrapper.set(RawAccessorWrapper.java:73)
    at com.sun.xml.ws.client.sei.BodyBuilder$DocLit.build(BodyBuilder.java:264)
    at com.sun.xml.ws.client.sei.BodyBuilder$JAXB.createMessage(BodyBuilder.java:103)
    at com.sun.xml.ws.client.sei.StubHandler.createRequestPacket(StubHandler.java:231)
    at com.sun.xml.ws.db.DatabindingImpl.serializeRequest(DatabindingImpl.java:195)
    at com.sun.xml.ws.db.DatabindingImpl.serializeRequest(DatabindingImpl.java:257)
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:117)
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:102)
    at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:154)
    at com.sun.proxy.$Proxy31.f(Unknown Source)
    at org.example.test.TestThing.testThing(TestThing.java:19)

Runtime environment is Tomcat7.

I assumed that I was not forced to rename the Java methods, too. Am I?

A zip containing an eclipse project is available at http://ge.tt/1JrLxFh/v/0

1

There are 1 answers

0
Catweazle On

You need to make sure you distinguish between the parameters as well. Otherwise the schema will associate the same types with the parameters of both methods, effectively defeating your intention with overloading.

@Override  
@WebMethod(operationName = "f2")  
@ResponseWrapper(className = "f2Response")  
@RequestWrapper(className = "f2")   
public String f(Integer i) {  
        return "f2";  
}