jax-ws/wsimport generates WebMethod with void return - same Request/ResponseWrapper
Asked Answered
M

2

18

I'm working with a client's WSDL file that uses the same element definition for the input and output messages, but I'm having trouble getting JAX-WS/JAXB to unmarshal the response.

<wsdl:message name="invokeServiceRequest">
    <wsdl:part element="impl:requests" name="multiRequestWrapper"/>
</wsdl:message>
<wsdl:message name="invokeServiceResponse">
    <wsdl:part element="impl:requests" name="result"/>
</wsdl:message>
<wsdl:portType name="GCGatewayPortType">
    <wsdl:operation name="requests">
        <wsdl:input message="impl:invokeServiceRequest" name="invokeServiceRequest"/>
        <wsdl:output message="impl:invokeServiceResponse" name="invokeServiceResponse"/>
    </wsdl:operation>
</wsdl:portType>

For some reason, the code generated by wsimport has a void return, and the INOUT params don't seem to be updated when the response is received.

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.1.7-b01-
 * Generated source version: 2.1
 */
...
@WebMethod
@RequestWrapper(localName = "requests", targetNamespace = "http://cg.test.com/", className = "com.test.cg.RequestsType")
@ResponseWrapper(localName = "requests", targetNamespace = "http://cg.test.com/", className = "com.test.cg.RequestsType")
public void requests(
    @WebParam(name = "paramOne", targetNamespace = "http://cg.test.com/", mode = WebParam.Mode.INOUT)
    Holder<String> paramOne,
    @WebParam(name = "paramTwo", targetNamespace = "http://cg.test.com/", mode = WebParam.Mode.INOUT)
    Holder<String> paramTwo,
    @WebParam(name = "requestList", targetNamespace = "http://cg.test.com/", mode = WebParam.Mode.INOUT)
    Holder<List<RequestType>> requestList);

When I call port.request( paramOne, paramTwo, requestList ), I can see that the SOAP request is sent to the server, which responds with a valid SOAP response:

<soapenv:Envelope ...>
    <soapenv:Header />
    <soapenv:Body>
        <requests ...>
            <paramOne>1</paramOne>
            <paramTwo>2</paramTwo>
            <requestList>
                <!-- various elements that JAXB has generated code for -->

However, when I run my app in debug mode, I can see each RequestType instance in the debugger variables view, but because RequestsType has an <xsd:choice> with RequestData or ResponseData, the latter is null and the RequestData is as I provided.

I've successfully used JAX-WS on other projects, but in those cases it generated code with a @WebResult and non-void return type named after the WebResult. In this project, I think I'm not getting the WebResult because JAX-WS has decided that the request and response types are the same and it can reuse the same object - but how do I get it to update that object with data from the response?

Macknair answered 16/4, 2012 at 5:24 Comment(1)
Could you please post your WSDL document?Land
B
19

You can solve this by instructing JAX-WS to disable wrapping. This is done through a JAX-WS bindings file.

<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
    <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>
Blacksnake answered 3/10, 2014 at 12:30 Comment(2)
This is the right answer, upvoting. Just a note: you save the code above in the *.xjb file and instruct wsimport to use it like so: "wsimport -b disable-wrappings.xjb your.wsdl"Deration
Isaac and @Deration I burst in tears of joy when I found your answer. Thank you so much.Hindsight
K
14

I was having exactly the same problem. I experimented with the names I was using for the various types, elements, message names, operations names, and such. I finally found the key, and something you said in your question actually got me close to the answer:

In this project, I think I'm not getting the WebResult because JAX-WS has decided that the request and response types are the same and it can reuse the same object - but how do I get it to update that object with data from the response?

I looked at my wsdl, which was generating similar java code (with void return and a parameter list instead of a single object parameter). But I have different input and output types. What about my wsdl was similar to yours?

The name of the operation was the same as the name of the element defined for the input type. I would suggest that you change your operation name from 'requests' to something like 'processRequests', or leave the operation name alone, and change the name of the element used for the message definitions.

<wsdl:operation name="requests">

becomes

<wsdl:operation name="processRequests">

I'd love to hear if this works for you.

Kasten answered 23/1, 2013 at 16:52 Comment(5)
Sorry, I've moved on to a different company and no longer have access to the code for that project. If I had control of the WSDL schema I would have change the root element of the response from "requests" to "response"Macknair
Hi! I'm encountering the same error. Changing the operation name works. Zach, would you know if this is a limitation of wsimport or is there a way to let wsimport handle cases wherein the operation name is the same with the name of the request parameter type?Lanfri
@Lanfri I am not sure about that. If changing the operation name is not a solution that you can actually go with (perhaps the wsdl is outside of your control), then it might be worth generating classes with another tool such as Axis.Kasten
Thanks, i've solved the same issue with the way you've provided.Brachial
Great! How did you find the workaround? And it was the same on CXF 2.1.x and 3.1.xLeprosy

© 2022 - 2024 — McMap. All rights reserved.