SOAP service response cannot be mapped - java

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.

Related

How to plug security into web service with custom SOAP header (java)?

Broadly, I'm looking for a way to secure web service implemented in Java (using Spring Boot). I secured it with HTTP basic first.
Currently it is secured using XWSS. The problem is, that soap header for xwss is
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" wsse:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>user</wsse:Username>
<wsse:Password>password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
while I need
<SecuritySOAPHeader>
<UserName>user</UserName>
<Password>password</Password>
</SecuritySOAPHeader>
It is "wsdl first" WS, how can I plug security in, when header is defined in WSDL?
edit:
If it helps, this is what is defined in WSDL
<wsdl:binding name="CreditLimitServiceSoap" type="tns:CreditLimitServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetCreditLimitAndBalanceDetails">
<soap:operation soapAction="http://cargowise.com/Accounting/GetCreditLimitAndBalanceDetails" style="document" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:GetCreditLimitAndBalanceDetailsSecuritySOAPHeader" part="SecuritySOAPHeader" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
It seems, that I'd be able to access the header when I change my current
#Endpoint
public class CustomerBalancesEndpoint {
...
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "GetCreditLimitAndBalanceDetails", )
#ResponsePayload
public GetCreditLimitAndBalanceDetailsResponse getCustomerBalance(#RequestPayload GetCreditLimitAndBalanceDetails request) {
...
}
...
}
to
#Endpoint
public class CustomerBalancesEndpoint {
...
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "GetCreditLimitAndBalanceDetails", )
#ResponsePayload
public GetCreditLimitAndBalanceDetailsResponse getCustomerBalance(#RequestHeader SecuritySOAPHeader securityHeader, #RequestPayload GetCreditLimitAndBalanceDetails request) {
...
}
...
}
As it seems, maven-jaxb2-plugin had no issue with that WSDL.
edit 2:
Currently I'm more inclined to modify the message from client (the one with SecuritySOAPHeader) and modify it to standard (XWSS) header to have SOAP-ENV:Fault generated if wrong password is passed.

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

Spring-WS endpoints document literal wrapping/unwrapping

I am integrating with a system that expects us to consume WS-I 1.1 document/literal wrapped messages. We have a working solution but it appears like there could be a simpler way to deal with payload wrapping/unwrapping.
I have an endpoint that as follows:
#Endpoint
public class FooEndpoint
{
#Autowired
private FooService FooService;
#PayloadRoot(localPart = "Foo", namespace = "http://foo/service")
#ResponsePayload
public JAXBElement<FooAcknowledgementType> Foo(
#RequestPayload JAXBElement<FooRequestType> requestElement)
{
FooRequestType request = requestElement.getValue();
FooAcknowledgementType response = FooService.Foo(request);
// TODO: Find a better solution with the wrapped response
return new JAXBElement<FooAcknowledgementType>(new QName(
"http://foo/service", "FooAcknowledgement"),
FooAcknowledgementType.class, null, response);
}
}
and a WSDL which defines the contract is like:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:tns="http://foo/service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://www.w3.org/2000/09/xmldsig#" xmlns:ns1="http://foo/schema"
name="Foo" targetNamespace="http://foo/service">
<wsdl:types>
<xsd:schema xmlns:s="http://foo/schema" targetNamespace="http://foo/service">
<xsd:import namespace="http://foo/schema" schemaLocation="foo_types.xsd" />
<xsd:element name="Foo" type="s:FooRequestType" />
<xsd:element name="FooAcknowledgement" type="s:FooAcknowledgementType" />
</xsd:schema>
</wsdl:types>
<wsdl:message name="FooRequest">
<wsdl:part name="parameter" element="tns:Foo" />
</wsdl:message>
<wsdl:message name="FooAcknowledgement">
<wsdl:part name="parameter" element="tns:FooAcknowledgement" />
</wsdl:message>
<wsdl:portType name="FooPortType">
<wsdl:operation name="Foo">
<wsdl:input message="tns:FooRequest" />
<wsdl:output message="tns:FooAcknowledgement" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="FooBinding" type="tns:FooPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Foo">
<soap:operation soapAction="http://foo/serviceFoo" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Foo">
<wsdl:documentation>Foo web service</wsdl:documentation>
<wsdl:port name="FooService" binding="tns:FooBinding">
<soap:address location="http://localhost:8080/foo/services/Foo" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
I've generated jaxb objects from the foo_types.xsd schema as referenced in the endpoint class above.
The issue is that when we receive soap messages in document/literal wrapped style the soap body payload would look like
<x:Foo>
<!-- elements from s:FooRequestType -->
</x:Foo>
and we are expected to respond with a soap body payload like
<x:FooAcknowledgement>
<!-- elements from s:FooAcknowledgementType -->
</x:FooAcknowledgement>
Is there anyway that the Spring-WS can handle this out of the box? We can consume and produce compliant messages with the code as it is but it seems like this might not be the right way to go about it as this style is not referenced in the spring docs at http://docs.spring.io/spring-ws/site/reference/html/tutorial.html#tutorial.xsd
The solution for us was to add the namespace and element name to the #XmlRootElement annotation via our jaxb bindings.xml, E.g.
<jaxb:bindings node="xs:complexType[#name='fooType']">
<annox:annotate target="class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="FooAcknowledgement" namespace="http://foo/service"/>
</annox:annotate>
</jaxb:bindings>

Sending message from Spring WS client with empty RequestPayload

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.

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