I have a Soap service generated by a wsdl file, that expects a certain TargetNamespace
#WebResult(name = "getResponse", targetNamespace = "http://targetNameSpace1.com", partName = "result")
but we have multiple clients calling this api and each one uses a diferente TargetNamespace:
Client one:
<soap:Envelope
xmlns:loc="http://targetNameSpace1.com">
<soap:Header>
<ns3:RequestSOAPHeader>
...
</ns3:RequestSOAPHeader>
</soap:Header>
<soap:Body>
<loc:getResponse>
<loc:value>url/</loc:value>
</loc:getResponse>
</soap:Body>
</soap:Envelope>
Client two:
<soap:Envelope
xmlns:loc="http://targetNameSpace2.com">
<soap:Header>
<ns3:RequestSOAPHeader>
...
</ns3:RequestSOAPHeader>
</soap:Header>
<soap:Body>
<loc:getResponse>
<loc:value>url/</loc:value>
</loc:getResponse>
</soap:Body>
</soap:Envelope>
This is the error i get:
<soap:Envelope>
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Message part {http://targetNameSpace2.com}getResponse was not recognized. (Does it exist in service WSDL?)</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
and i can only make it work with one at a time changing the targetNameSpace tag in the webResult, but my ultimate goal is to ignore this tag, because i dont know witch namespace will each client use.
At the moment i am trying to use an interceptor that extends this
AbstractSoapInterceptor and i get a SoapMessage object i can acess it before the request is made, but i can't seem to change the request, not sure if its the best aproach.
Does anyone have a solution for this?
Thanks!
The wsdl and the (embedded) xsd are the contracts that you specify. Server and client need to follow that contract. Changing the contract single sided will result into invalid messages. Instead of looking for a solution to accept invalid messages you should update the clients so they obey the contracts.
I ended up following this article https://www.javatips.net/blog/cxf-interceptor-example,
I intercept every request, and replace this:
xmlns:loc="http://targetNameSpace2.com"
with the url that i want, i used regex to replace whats inside the loc tag
Related
I am using Camel in our project and requesting WebServices, the dataFormat is POJO. I was able to request when my SOAP message did not contain SOAP headers, but when it had Headers, I was unable to set those. I looked at the documentation but was not able to understand and have several questions.
I want to create a message like the below:
<soapenv:Envelope`enter code here`
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<platformMsgs:documentInfo
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformMsgs:nsId>WEBSERVICES_3479023</platformMsgs:nsId>
</platformMsgs:documentInfo>
</soapenv:Header>
<soapenv:Body>
<addListResponse
xmlns="">
<platformMsgs:writeResponseList
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformCore:status isSuccess="true"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com"/>
<platformMsgs:writeResponse>
<platformCore:status isSuccess="false"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com">
<platformCore:statusDetail type="ERROR">
<platformCore:code>DUP_ENTITY</platformCore:code>
<platformCore:message>This entity already exists.</platformCore:message>
</platformCore:statusDetail>
</platformCore:status>
</platformMsgs:writeResponse>
</platformMsgs:writeResponseList>
</addListResponse>`enter code here`
</soapenv:Body>
</soapenv:Envelope>
I will be able to send the message if there was only Body, but can someone give me a code snippet for including the header section? The dataFormat is POJO.
When using CXF endpoint with dataFormat as POJO, body in Camel Exchange object is an object of org.apache.cxf.message.MessageContentsList. It is an extension of java.util.ArrayList<Object> and it contains parts of SOAP Message in order as defined in WSDL and corresponding method in WebService class.
Element 0 there is a Body.
So, one way to do that with Java is to create a Processor class implementing org.apache.camel.Processor interface and in its process method set your SOAP header. Something like:
#Override
public void process(Exchange camelExchange) throws Exception {
MessageContentsList messageBody = (MessageContentsList) camelExchange.getIn().getBody();
DocumentInfo docInfoHeader = new DocumentInfo();
... set docInfoHeader properties ...
messageBody.add(docInfoHeader);
}
(sample is not tested. It is just an idea, how to handle that...)
Other answer on similar question you can find here: Setting Custom Soap Header-To Pojo Message In Camel Cxf
It describes how to use Camel Exchange headers as SOAP Headers.
I'm not sure for 100% which way will work for you and which one is better...
I guess, it depends on WSDL you use.
UPD: second choice is to use pure CXF solution by using CxfMessageSoapHeaderOutInterceptor custom implementation.
It may look like:
public class MyCxfInterceptor extends CxfMessageSoapHeaderOutInterceptor {
#Override
public void handleMessage( org.apache.cxf.binding.soap.SoapMessage message) {
org.apache.cxf.binding.soap.SoapHeader myCustomHeader = new org.apache.cxf.binding.soap.SoapHeader(new QName(
{custom name space}, {custom local name}), {Custom content object}));
myCustomHeader.setMustUnderstand(true);
message.getHeaders().add(myCustomHeader);
}
and set Interceptor in Camel Cxf Endpoint as :
<cxfEndpoint ...>
<outInterceptors>
<spring:bean class="MyCxfInterceptor"/>
</outInterceptors>
...
Well suppose I request the Web Service and it failed, a Fault message is generated. Will I get the Fault object at position 0 of MessageContentsList then too? Or will I get only the response object at position 0?
A web service I'm connecting to throws a SOAPFaultException for all its exceptions which means the app throws only RuntimeExceptions.
Using wsimport I generated the code and objects to connect and communicate with the service, it also generated the JAXB objects which represents the xml content in the detail element of the SOAPFaultException.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Soap Exception From Server</faultstring>
<faultactor>url</faultactor>
<detail>
<MyResponse>
<myID>123</myId>
<serverName>Test</serverName>
<error>
<desc>Unable to verify id</desc>
</error>
</MyResponse>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Wsimport generated a jaxb object called MyResponse with myId,serverName, error,desc as variables
I want to know how can I populate the MyResponse jaxb object that was generated, with the detail element data or do I have to navigate through the elements by node to get the values?
I have simple web service :
I have the same problem. when I don't append "?wsdl" I have soap faylt. how can I avoid this exception?
#WebService
#SOAPBinding(style = Style.RPC)
public interface TimeServer {
#WebMethod
#WebResult(partName = "time_response")
String getTimeAsString();
#WebMethod
#WebResult(partName = "time_response")
long getTimeAsElapsed();
}
and impl:
#WebService(endpointInterface = "x.y.z.TimeServer")
public class TimeServiceImpl implements TimeServer {
public TimeServiceImpl() {}
#Override
public String getTimeAsString() {return new Date().toString();}
#Override
public long getTimeAsElapsed() {return new Date().getTime();}
}
I run this web service in Jboss As 7.0.1.
Everything works well!
When I open link localhost:8080/project/time?wsdl
everything works well - I have wsdl.
but when I don't append "?wsdl" I have exception.
14:26:58,192 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-localhost-127.0.0.1-8080-1) Interceptor for {http://x.z.y/}HelloWorld has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: No such operation: null (HTTP GET PATH_INFO: /project/timenull)
at org.apache.cxf.interceptor.URIMappingInterceptor.handleMessage(URIMappingInterceptor.java:88)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
and I have this response from server:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>
No such operation: null (HTTP GET PATH_INFO: /soap-service/timenull)
</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
how can I avoid this exception?
It will be better , if client will see another message, instead of this error response? how can I send another XML when client opens link without "?wsdl"?
thnaks
Webservices won't support HTTP GET. If you enter the service url its directly making a HTTP GET. Thats the reason it responds with the error No such operation
Instead you need to make a SOAP POST to get response from webservice. Write a webservice client for this. You can refer this link for creating webservice clients
#grep
I see this post as bit old, but still will try to answer if anyone else with similar problem is able to. Well, I had the same issue and wondered what were the reasons behind those. here are the two steps that i tried and fixed up the issue. make sure you are able to access the wsdl in browser.
Close the SOAPUI, delete the soapui_workspace.xml created in user folder under C:/users.
Restart the Soap_ui and open up preferences>Proxy setting.
Change from automatic to None.
Create new project.
This did solved my issue and got the response from webservice in SOAPUI.
Secondly, in this case, make sure you have deployed the webservice correctly as mentioned by #Dinal.
I have a jaxws webservice with #SchemaValidation on it.
#SchemaValidation(handler = MySchemaValidationHandler.class)
#WebService(portName = "MyService", serviceName = "MyService", targetNamespace = "urn:com.my.urn", wsdlLocation = "/wsdls/mywsdl.wsdl", endpointInterface = "com.my.MyService")
#BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
public class MyServiceImpl
implements MyService {
#Resource
WebServiceContext wsContext;
public void myOperation(Holder<XMLGregorianCalendar> tag1, Holder<XMLGregorianCalendar> tag2, Holder<String> message) {
...
}
}
in xsd I have the following example:
<xsd:choice>
<xsd:element name="tag1" type="xsd:dateTime" minOccurs="0"/>
<xsd:element name="tag2" type="xsd:dateTime" minOccurs="0"/>
</xsd:choice>
When I send the request with empty tags, I get an error concerning the field format (doesn't fit the restrictions of a date format).
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:com.my.urn">
<soapenv:Header/>
<soapenv:Body>
<urn:myOperation>
<Tag1>value1</Tag1>
<Tag2></Tag2>
</urn:myOperation>
</soapenv:Body>
</soapenv:Envelope>
In request description I have mandatory tags and choice tags and have to return the correct error message in the response, so I can't just skip such errors in the handler.
Also I can't modify nor xsd nor wsdl
Logically empty tags mean the same as missing tags. How can I make the validation treat empty tags as missing or how can I delete empty tags before the validation?
Thanks.
Edit: Don't send invalid XML. In the example you give, you should remove <Tag2></Tag2> in whatever your client code is. Don't try to abuse the server's validation to handle invalid XML.
I am about to develop web application with web services. I've already tuned jax-ws and ws-security. I used soapUI and sent next request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="..." >
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-2">
<wsu:Created>2011-11-11T00:05:05.044Z</wsu:Created>
<wsu:Expires>2012-11-11T00:10:05.044Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-1">
<wsse:Username>user</wsse:Username>
<wsse:Password>password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<soap:foo>
<arg0>1</arg0>
</soap:foo>
</soapenv:Body>
</soapenv:Envelope>
I need get Username and Password from header. On the application I can get it by next code:
#Resource
WebServiceContext context;
...
private static final String PRINCIPAL_RESULT = "wss4j.principal.result";
...
WSUsernameTokenPrincipal wsutp = (WSUsernameTokenPrincipal) context.getMessageContext().get(PRINCIPAL_RESULT);
..
String user = wsutp.getName()
String password = wsutp.getPassword();
But I have no idea how should I test it with jUnit tests, because context.getMessageContext() will be NULL on test class.
Does anyone knows a good guide or provide a code-sample?
You need to mock the resources, that are not available in your junit tests. Please have a look at a framework like Mokito (http://mockito.org/). There you can do s.th. like:
//You can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
//stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());
Or for your case:
WSUsernameTokenPrincipal mockedWsutp = mock(WSUsernameTokenPrincipal.class);
when(mockedWsutp.getName()).thenReturn("TheNameRequiredForYourTestCase");
...
With these frameworks, you can simulate the unavailable resources. And they integrate easily with junit. I hope this provides some useful ideas.
Try this:
JAX-WS Webservice secured With XWS-Security (plain text password)
[http://mananvpanchal.blogspot.com/2010/06/jax-ws-webservice-with-plaintext.html][1]