Sending message from Spring WS client with empty RequestPayload - java

I'm a bit stuck here. We're trying to write WS Client using Spring WS. The challenge is to handle web services like getVersion() that do not need to pass any values to the server.
Here's a typical Client implementation you'd normally use:
public class MyServiceClient extends WebServiceGatewaySupport {
public String getVersion() {
SomeJaxbGeneratedClass request = new SomeJaxbGeneratedClass();
String response = (String) getWebServiceTemplate().marshalSendAndReceive(request,
new SoapActionCallback("someNameSpace/getVersion"));
return response;
}
}
The issue is when calling getVersion there's no SomeJaxbGeneratedClass to be passed as a request since it's only requesting to get the version number. So my question is what should be passed in as a request (RequestPayload) in this case? Does WebServiceTemplate have another method that would work better?
Here's how getVersion is defined in WSDL:
<WSDL:message name="getVersionRequest"/>
<WSDL:message name="getVersionResponse">
<WSDL:part name="version" type="xsd:string"/>
</WSDL:message>
<portType>
<WSDL:operation name="getVersion">
<WSDL:input message="tns:getVersionRequest"/>
<WSDL:output message="tns:getVersionResponse"/>
</WSDL:operation>
</portType>
<binding>
<WSDL:operation name="getVersion">
<SOAP:operation soapAction="someNameSpace/getVersion"/>
<WSDL:input>
<SOAP:body namespace="someNameSpace" use="literal"/>
</WSDL:input>
<WSDL:output>
<SOAP:body namespace="someNameSpace" use="literal"/>
</WSDL:output>
</WSDL:operation>
</binding>
Any help will be greatly appreciated.

Just want to give everyone an update in case you run into a similar issue. I got this resolved by switching from Spring WS to Spring JAX-WS solution using JaxWsPortProxyFactoryBean.

Related

wsimport uses SOAP 1.2 for SOAP 1.1 wsdl

I've got this wsdl supplied for a SOAP 1.1, once I try to generate my java code using wsimport, it handles the wsdl as being 1.2. Which subsiquentially throws an error:
com.sun.tools.ws.wsdl.framework.ParseException: invalid extension element: "soap:body" (in namespace "http://schemas.xmlsoap.org/wsdl/soap/")
If I change the soap name change from:
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/
to
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/
It generates my code, but I'm not sure what other consequences this has (I can't yet connect to the endpoint at this time). Plus I don't want to hack the wsdl.
Is there any known error in wsimport that let's it incorrectly handle a 1.1 wsdl as being 1.2? (well, known... I can't find anything about this after hours of searching)
Is there a work around where for example I can force wsimport to use soap 1.1?
Any other solution without editting the wsdl?
wsdl code here:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:rpa="urn:ns:cdm:reisinformatie:data:vi:1" xmlns:tns="urn:ns:cdm:reisinformatie:message:actuelelandelijkeberichten:1" xmlns:ns="urn:ns:cdm:reisinformatie:message:actuelelandelijkeberichten:1" targetNamespace="urn:ns:cdm:reisinformatie:message:actuelelandelijkeberichten:1">
<wsdl:types>
<xsd:schema xmlns:rpa="urn:ns:cdm:reisinformatie:data:vi:1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:ns:cdm:reisinformatie:message:actuelelandelijkeberichten:1" targetNamespace="urn:ns:cdm:reisinformatie:message:actuelelandelijkeberichten:1" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:import schemaLocation="ri-cdm-vi-lab.xsd" namespace="urn:ns:cdm:reisinformatie:data:vi:1"/>
<xsd:element name="GeefActueleLandelijkeBerichtenRequestMessage" type="rpa:GeefActueleLandelijkeBerichtenRequestMessageType"/>
<xsd:element name="GeefActueleLandelijkeBerichtenResponseMessage" type="rpa:GeefActueleLandelijkeBerichtenResponseMessageType"/>
<xsd:element name="GeefActueleLandelijkeBerichtenFaultMessage" type="rpa:GeefActueleLandelijkeBerichtenFaultMessageType"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="GeefActueleLandelijkeBerichtenRequest">
<wsdl:part name="parameter" element="tns:GeefActueleLandelijkeBerichtenRequestMessage"/>
</wsdl:message>
<wsdl:message name="GeefActueleLandelijkeBerichtenResponse">
<wsdl:part name="parameter" element="tns:GeefActueleLandelijkeBerichtenResponseMessage"/>
</wsdl:message>
<wsdl:message name="GeefActueleLandelijkeBerichtenFault">
<wsdl:part name="Fout" element="tns:GeefActueleLandelijkeBerichtenFaultMessage"/>
</wsdl:message>
<wsdl:portType name="ActueleLandelijkeBerichtenSoap">
<wsdl:documentation>Actuele LandelijkeBerichten Soap Port</wsdl:documentation>
<wsdl:operation name="GeefActueleLandelijkeBerichten">
<wsdl:input message="tns:GeefActueleLandelijkeBerichtenRequest"/>
<wsdl:output message="tns:GeefActueleLandelijkeBerichtenResponse"/>
<wsdl:fault name="Fout" message="tns:GeefActueleLandelijkeBerichtenFault"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ActueleLandelijkeBerichtenSoap" type="tns:ActueleLandelijkeBerichtenSoap">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:documentation>Actuele LandelijkeBerichten Soap Binding</wsdl:documentation>
<wsdl:operation name="GeefActueleLandelijkeBerichten">
<soap:operation soapAction="urn:GeefActueleLandelijkeBerichten"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="Fout">
<soap:body use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ActueleLandelijkeBerichten">
<wsdl:documentation>Actuele LandelijkeBerichten Service</wsdl:documentation>
<wsdl:port name="RPAActueleLandelijkeBerichtenSoap" binding="tns:ActueleLandelijkeBerichtenSoap">
<soap:address location="NotDefined"/>
<wsdl:documentation>Reisinformatie Pull Applicatie Actuele LandelijkeBerichten Soap Service</wsdl:documentation>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
note: two .xsd's not included
Right, we've decided to generate the code with CXF (which works) and then add that to the delivery file.
Also, another team at our company ran into same problem and couldn't find a solution for this as well.
So, the answer seems to be: use CXF.

Web service generated client - does it use Holder objects for return values?

For production used web service-client mechanism we are implementing new feature pretty much similar to already used.
New method is using the same description like the previous features inside wsdl.
The client side is generated inside Eclipse using Apache Axis (1.).
wsdl
<wsdl:operation name="Work">
<soap:operation soapAction="WORK" style="document"/>
<wsdl:input>
<soap:header message="llws:Header2" part="Header" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Work">
<wsdl:input message="test:WorkRequestObject"/>
<wsdl:output message="test:WorkResponseObject"/>
</wsdl:operation>
What is confusing me is different syntax of generated method. First method is generated with signature:
public ResponseObject doSomething(RequestObject)
while second method is generated with signature like
public void doSomeOtheWork (RequestObject, javax.xml.rpc.holders.BigIntegerHolder, javax.xml.rpc.holders.StringHolder)
Why is this done this way? Why both methods aren't generated using the same syntax? Could it be that first method is already present and generator is leaving it unchanged whilst second one is generated with the another version/lib are therefor I get another signature?

Change part name with Jaxb binding

I have a WSDL like that :
...
<wsdl:message name="myHeader">
<wsdl:part name="parameter" element="header:myHeader"/>
</wsdl:message>
...
<wsdl:operation name="myOperation">
<soap:operation soapAction="myOperation" style="document" />
<wsdl:input name="myOperationRequest">
<soap:header message="mySession:myHeader" part="header" use="literal"/>
<soap:body parts="parameters" use="literal" />
</wsdl:input>
<wsdl:output name="myOperationResponse">
<soap:body parts="parameters" use="literal" />
</wsdl:output>
<wsdl:fault name="myOperationException">
<soap:fault name="createTroubleTicketByValueException" use="literal" />
</wsdl:fault>
</wsdl:operation>
....
I convert my WSDL into Java with wsdl2java, not problem during the conversion with the exsh set to true.
But when I start my application (Spring 4, CXF 2.7), I'm getting the following warning :
2015-09-28 14:19:04,640 WARN [main] o.a.c.s.f.ReflectionServiceFactoryBean(1525) - Method interface ....XXXSessionWSPort.myOperation is configured as BARE but there are more than one parameters with wrong #Webparam annotated or without #WebParam annotated.
If I look closer to the WsPort generated :
#WebResult(name = "myOperationResponse", targetNamespace = "http://myNamespace", partName = "parameters")
#WebMethod(action = "myOperation")
public myOperationResponse myOperation(
#WebParam(partName = "parameters", name = "myOperationRequest", targetNamespace = "http://myNameSpace")
myOperationRequest parameters,
#WebParam(partName = "parameters", name = "myheader", targetNamespace = "http://headerNameSpace", header = true)
myHeader parameters1) throws myOperationException;
Moreover, as a client when I make a call to myOperation CXF/JAXB/Jax-ws/...(?) add a "1" at the end of the myHeader tag, consequently the server cannot handle the header...
After debugging in the class ReflectionServiceFactoryBean, I see the problem coming from the same partName in the two #WebParam.
To correct this, I have to change the header's part name into the WSDL, but I can't : it's not mine.
So I would made this change in the jaxb binding xml file, if possible, how can I do that?
If you have a better solution don't hesitate!
A bit late, but maybe this can help you: "A customization file"
http://java-soa.blogspot.pe/2008/07/parameter-customization-in-jax-ws.html

SOAP service response cannot be mapped

This problem has had me stumped for almost two days now, I really need some help figuring it out.
I have used wsimport to generate code from two different .wsdl files for a Java project.
The first service works just fine but for some reason the response from the second service cannot be unmarshalled to a response object.
Working service:
#WebMethod(action = "[actionName]")
#WebResult(name = "getSimpleCompanyInfoResponse", partName = "getSimpleCompanyInfoResponse")
public GetSimpleCompanyInfoResponse getSimpleCompanyInfo(
#WebParam(name = "getSimpleCompanyInfoRequest", partName = "getSimpleCompanyInfoRequest") GetSimpleCompanyInfoRequest getSimpleCompanyInfoRequest);
Response POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "getSimpleCompanyInfoResponse", propOrder = {
//variables
})
public class GetSimpleCompanyInfoResponse {
//variables
}
Response XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:getSimpleCompanyInfoResponse>
<getSimpleCompanyInfoResponse>
//variables
</getSimpleCompanyInfoResponse>
</ns1:getSimpleCompanyInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
NOT working service:
#WebMethod(operationName = "PersonnelInfo", action = "[actionName]")
#WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse")
public PersonnelInfoResponse personnelInfo(
#WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest);
Response POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "PersonnelInfoResponse", propOrder = {
//variables
})
public class PersonnelInfoResponse {
//variables
}
Response XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:PersonnelInfoResponse>
//variables
</ns1:PersonnelInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Using -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true or monitoring with Wireshark I can see the Response envelope from the second service coming through just fine and unmarshalling doesn't throw any exceptions but in the end PersonnelInfoResponse is null.
The only difference I can see is that the second service response payload in the XML is missing the outer element which seems to be the problem. However, I do not know how to "fix" it so it doesn't look for the outer element.
If anything was unclear or missing please let me know and I'll try to give you all the information.
EDIT:
No, I unfortunately don't have any control over the service itself, I only have the .wsdl and .xsd.
I'm calling the service like this:
ReportsControllerPortType port = new ReportsControllerService().getReportsControllerPort();
PersonnelInfoRequest request = new PersonnelInfoRequest();
//fill the required fields in the request, username, password, etc.
PersonnelInfoResponse response = port.personnelInfo(request);
The client-side service stubs (ReportsControllerService & ReportsControllerPortType) are also automatically generated by wsimport according to the .wsdl and .xsd.
EDIT 2:
Removing the operation name doesn't work, the service fails to initialize. Following are the definitions from both .wsdl-s:
Working service:
<wsdl:message name="getSimpleCompanyInfoRequest">
<wsdl:part name="getSimpleCompanyInfoRequest" type="tns:getSimpleCompanyInfoRequest" />
</wsdl:message>
<wsdl:message name="getSimpleCompanyInfoResponse">
<wsdl:part name="getSimpleCompanyInfoResponse" type="tns:getSimpleCompanyInfoResponse" />
</wsdl:message>
<wsdl:portType name="MonitoringControllerPortType">
<wsdl:operation name="getSimpleCompanyInfo">
<wsdl:input message="tns:getSimpleCompanyInfoRequest" />
<wsdl:output message="tns:getSimpleCompanyInfoResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MonitoringControllerBinding" type="tns:MonitoringControllerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getSimpleCompanyInfo">
<soap:operation soapAction="[domain]/#getSimpleCompanyInfo" style="rpc" />
<wsdl:input>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MonitoringControllerService">
<wsdl:port name="MonitoringControllerPort" binding="tns:MonitoringControllerBinding">
<soap:address location="[serviceUri]" />
</wsdl:port>
</wsdl:service>
Not working service:
<wsdl:message name="PersonnelInfoRequest">
<wsdl:part name="PersonnelInfoRequest" type="tns:PersonnelInfoRequest" />
</wsdl:message>
<wsdl:message name="PersonnelInfoResponse">
<wsdl:part name="PersonnelInfoResponse" type="tns:PersonnelInfoResponse" />
</wsdl:message>
<wsdl:portType name="ReportsControllerPortType">
<wsdl:operation name="PersonnelInfo">
<wsdl:input message="tns:PersonnelInfoRequest" />
<wsdl:output message="tns:PersonnelInfoResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ReportsControllerBinding" type="tns:ReportsControllerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="PersonnelInfo">
<soap:operation soapAction="[domain]/#PersonnelInfo" style="rpc" />
<wsdl:input>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ReportsControllerService">
<wsdl:port name="ReportsControllerPort" binding="tns:ReportsControllerBinding">
<soap:address location="[serviceUri]" />
</wsdl:port>
</wsdl:service>
EDIT 3:
ReportsControllerService and MonitoringControllerService extend javax.xml.ws.Service and contain the definitions of the .wsdl schema location and namespace used. The service class returns a PortType object as you can see:
/**
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2
*/
#WebServiceClient(name = "ReportsControllerService", targetNamespace = "[namespaceUri]", wsdlLocation = "[wsdlUri]")
public class ReportsControllerService extends Service {
#WebEndpoint(name = "ReportsControllerPort")
public ReportsControllerPortType getReportsControllerPort() {
return super.getPort(new QName("[namespaceUri]", "ReportsControllerPort"), ReportsControllerPortType.class);
}
}
ReportsControllerPortType is an interface which contains methods for every operation endpoint that exists in the service
/**
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2
*/
#WebService(name = "ReportsControllerPortType", targetNamespace = "[namespaceUri]")
#SOAPBinding(style = SOAPBinding.Style.RPC)
#XmlSeeAlso({ObjectFactory.class})
public interface ReportsControllerPortType {
#WebMethod(operationName = "PersonnelInfo", action = "[actionName]")
#WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse")
public PersonnelInfoResponse personnelInfo(
#WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest);
}
}
The thing is, all of those classes are automatically generated by JAX-WS (as you can see from the comments) based on the .wsdl schema. The implementation is abstracted somewhere inside the JDK and I don't have control over that either. Yes, I can refactor the code so I bypass JAX-WS but as I understand it, this is supposed to be like a de facto standard way to consume .wsdl-based SOAP services.
The project uses Spring as a base-framework and I have already confirmed both services will work when I use Spring-WS instead so I can refactor but I want to understand why this way isn't working.
I believe I may have found out why your webservice is misbehaving. According to the specification, an RPC webservice must fulfill the following criteria in its soap binding (i.e. the #SOAPBinding annotation you have there)
A style of RPC: check
A use of LITERAL: check
A parameterStyle of WRAPPED: From the description you've given, it would appear that WRAPPED is not the case here, seeing as you're receiving a naked PersonnelInfoResponse (and possibly sending a naked PersonnelInfoRequest) without any wrapping indicates that the service itself is broken.
An excerpt from the JAX-WS spec:
Use of RPC style requires the use of WRAPPED parameter style. Deviations from this is an error
There is one obvious difference between your 2 calls :
You should try to remove operationName = "PersonnelInfo" from your second call which is not present in the first working one.

How to cunsume Java based Soap Web Service in javascript/ajax?

I've to provide a .jsp page(index.jsp) along with my Web Service project for testing purpose.
Basically the .jsp page has a textarea, for reading a soap request as a string & on submitting it the soap response will come.
I tried it with "javax.xml.ws.Service & Dispatch" class, it's working fine.
But now I'm asked for a javascript/ajax based code.
Can anybody help me regarding this.
I'm giving a sample .wsdl file here :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://zensar.com/greeting" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Greeting"
xmlns:grtng="http://zensar.com/greeting/schema"
targetNamespace="http://zensar.com/greeting">
<wsdl:types>
<xsd:schema targetNamespace="http://zensar.com/greeting">
<xsd:import namespace="http://zensar.com/greeting/schema"
schemaLocation="Greeting.xsd"></xsd:import>
</xsd:schema>
</wsdl:types>
<wsdl:message name="GreetingRequest">
<wsdl:part element="grtng:GreetingRequest" name="GreetingRequest" />
</wsdl:message>
<wsdl:message name="GreetingResponse">
<wsdl:part element="grtng:GreetingResponse" name="GreetingResponse" />
</wsdl:message>
<wsdl:portType name="GreetingPort">
<wsdl:operation name="Greeting">
<wsdl:input message="tns:GreetingRequest" />
<wsdl:output message="tns:GreetingResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Greeting" type="tns:GreetingPort">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Greeting">
<soap:operation soapAction="http://zensar.com/GreetingWS/Greeting" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Greeting">
<wsdl:port binding="tns:Greeting" name="Greeting">
<soap:address location="http://localhost:8085/Greeting/services" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>**
Personally, I'd say consuming the web service directly through javascript is a bit masochistic.
In my opinion it'd be much easier for the javascript to call a server side method (with whatever architecture that may be, c#, java, php etc) then do a CURL request and send the response back to the front end.
Writing out a soap endpoint by hand in javascript just seems pointless when you could use something like Axis2 at the server side to do the boiler plate heavy loading of the SOAP handshake.
You can try this ... http://www.ibm.com/developerworks/webservices/library/ws-wsajax/
This article explains everything in detail.

Categories