Moving namespace declaration to root element when using JaxWS - web-services

I want to call an external SOAP web service using JaxWS. JaxWS sends a request in the form
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<messageRootElement xmlns="some.ns">
<sampleChild>Content</sampleChild>
</messageRootElement>
</soap:Body>
</soap:Envelope>
Calling a mock service setup in SoapUI works fine. The actual external web service allegedly does not work with that format (I have no access to the system with the external web service for developement).
The external web service, seems to work with a request of the form
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sns="some.ns">
<soap:Body>
<sns:messageRootElement>
<sns:sampleChild>Content</sns:sampleChild>
</sns:messageRootElement>
</soap:Body>
</soap:Envelope>
which is how SoapUI generates a sample request from the WSDL in question as well.
My question is: how do I tell JaxWS to send its request in the latter form? I assume, both are valid according to some standard, but I have not the slightest clue, what technology the external web service is based on, and how well it conforms to the involved standards.
Explaining to me that, it is not possible to change JaxWS behaviour in that way (if that is the case), would be a helpful answer as well.

You need to modify the package-info.java file that's generated as part of the entities that are required for your web service call. Modify the file as follows:
#javax.xml.bind.annotation.XmlSchema(
namespace = "some.ns",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#javax.xml.bind.annotation.XmlNs(
prefix = "sns",
namespaceURI = "some.ns")
})
package some.ns;

Related

use soap services to get information

I'm new in learning Web services.
I was trying to use soap services to get a city weather from a website.
Here is the website
http://www.bom.gov.au/australia/majorcities.shtml?ref=hdr
I want to get the weather of Broome City on Friday.
While articulating my self doing this I came across two terms: EndPoint and SOAP Action
Can anyone please help me to understand these two terms ?
Is EndPoint is the URL from where I want to get information ?
SOAP Action ? What's this, why we use this and how we can use this ?
The only thing I know about SOAP services is It sends the request in xml format to server and response also comes up in xml format.(Might be am wrong)
Thanks in Advance !! :)
If you are starting fresh on web-services, I would recommend building REST service instead of soap service. That would be easier to start with.
If you go for REST service, your url would be:
http://serverxyz.com/{city}/{day}
Coming back to your questions:
EndPoint is the URL from where I want to get information ? - Correct
One web service usually has many operations which are called soap
action/soap method. Here is sample SOAP request from w3school which is also called
SOAP envelope:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body>
<m:GetPrice xmlns:m="http://www.w3schools.com/prices">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>

Technically,to create soap message, WSDL file is a must?

I'm using the SoapUI to generate the soap request. It hints me to input the wsdl file. I do it, and it create the soap-style message. Everything is OK.
But I have a doubt. If I have webservice without any WSDL file, can I still generate the soap-style message by hand? If it can, how to?
Or if I know the webservice need to input two int paramaters and return one string value, can I speculate the soap message only by these limited information?
If you are just doing -requests- then you don't need to have the WSDL file if you know the specific service you're asking and the parameters as you say. You can even do it by hand by creating the request and then sending it over HTTP (for example you could create it with your editor in a file and then send it via wget or curl).
As for an example I'll cite wikipedia:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
</soap:Header>
<soap:Body>
<m:GetStockPrice xmlns:m="http://www.example.org/stock">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
What you need to change is the parts in the soap:Body: of course the GetStockPrice (which is the service you're accessing) and StockName which is the parameter (in your case you may have more than one).
If in doubt you can put something to listen on a socket (for example netcat) and make your application with WSDL do a query to it and see the exact informations, then remove WSDL and work "by hand".
In Java: If you have webservice (annotated class etc.), the your server create one WSDL file when you deployed it. This WSDL you can use for soapUi.
If you have any structure (endpoint, class, XSD etc.), you can create soap message by hand.
If you weren't use WSDL for soap message, it wouldn't call/send this message. So the wsdl document is a required element according to the protocol. WSDL describes of how the service can be called, what parameters it expects, and what data structures it returns.
From Wikipedia:
WSDL is often used in combination with SOAP and an XML Schema to
provide Web services over the Internet. A client program connecting to
a Web service can read the WSDL file to determine what operations are
available on the server. Any special datatypes used are embedded in
the WSDL file in the form of XML Schema. The client can then use SOAP
to actually call one of the operations listed in the WSDL file using
for example XML over HTTP.
Here is in example for invoking web service dynamically. In this case the author doesn't know the description of the WSDL.
The purpose of the WSDL is to describe the service.
This machine-readable description allows computer programs to create clients that know how to call the service and process the responses.

Can A Header Be Added & Body Modified In A Salesforce SOAP Response?

From doing some testing on SOAP requests to a webservice I created in Salesforce I note the response returned is of the following format.
Note my request function I called is GetMsgRQ
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/schemas/class/MyIntegrationServices">
<soapenv:Body>
<GetMsgRQResponse>
<result>
<acctId>001J000000leVpEIAU</acctId>
<acctName>MyTest</acctName>
</result>
</lGetMsgRQResponse>
</soapenv:Body>
</soapenv:Envelope>
Relating to this I wonder is it possible to add a SOAP:Header?
Also I note the response has created an element "GetMsgRQResponse" (adding "Response" to "GetMsgRQ". Is it possible to create/specify the SOAP:Body without this occuring? Can I just set what the whole SOAP body response will be or will Salesforce always add such additional elements as the "GetMsgRQResponse" here and "result"?
Thanks in advance for any help on this. I know I can use a HTTP Request to send a full SOAP envelope but for my requirement I need to just provide a response instead of doing so.
I don't believe you can directly add any kind SOAP headers in an Apex defined WebService methods.
If you have absolutely no other option you could construct your own custom SOAP response via a REST web service (via #RestResource annotation) but that is a pretty ugly solution.

WSO2 ESB - How to build soapenv:Body for remote service call

I have the WSDL file of the remote web service I need to call from a proxy service in the WSO2 ESB and would like to know if I need to construct the soap:Body's elements manually through XSLT/Enrich or there is a way to generate the soapenv:Body's contains from the WSDL and maybe replace '?' for the values.
For example, if you've used soapUI before you'll know that when you import a WSDL file in a project a soapenv:Envelope gets generated automatically with all the XML elements and question marks for their values. Same goes for the TryIt tool in the WSO2 ESB.
Here is an example of an auto-generated soapenv:Envelope in soapUI after importing WSDL:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:abc="http://abc.com/">
<soapenv:Header/>
<soapenv:Body>
<abc:RegisterCandidate>
<abc:NameFirst>?</abc:NameFirst>
<abc:NameMiddle>?</abc:NameMiddle>
<abc:NameLast>?</abc:NameLast>
<abc:PhoneHome>?</abc:PhoneHome>
<abc:EmailAddress>?</abc:EmailAddress>
<abc:Address1>?</abc:Address1>
<abc:Address2>?</abc:Address2>
<abc:City>?</abc:City>
<abc:State>?</abc:State>
<abc:ZipCode>?</abc:ZipCode>
<abc:Country>?</abc:Country>
</abc:RegisterCandidate>
</soapenv:Body>
</soapenv:Envelope>
Is this possible in the Proxy Service through any of the mediators available to read a WSDL and generate soapenv:Body with its XML tags (in the code above it would be abc:RegisterCandidate with its children)? I've done it with the use of the XSL templates, but it's manual and not very elegant.
I've found a few articles/blogs online about writing proxy services in the WSO2 ESB that call remote web services and what the developers were doing in there was to insert the XML elements needed in the soapenv:Body with the use of XSL templates to have the correct/full SOAP message that is then sent (send mediator) to the remote web service server.
Thank you.
There is no way to generate the soap body from the remote service's wsdl as in your requirement. But there is an easier way than using xslt. That is to use the payload factory mediator. You can define the payload and assign values using xpath as shown in the sample.

Move namespace declaration from payload to envelope on an axis created web service

I just created a web service client using axis and eclipse that does not work with my web service provider. The message created by the web service client looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
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:Body>
<enviarMensajeRequest
xmlns="http://www.springframework.org/spring-ws/Imk-Zenkiu-Services">
<usuario>someuser</usuario>
<clave>somepassword</clave>
<mensaje>somemessage</mensaje>
<contacto>
<buzonSMS>somenumber</buzonSMS>
<primerNombre>somefirstname</primerNombre>
<primerApellido>somelastname</primerApellido>
</contacto>
</enviarMensajeRequest>
</soapenv:Body>
</soapenv:Envelope>
I see nothing wrong with the message but my provider insists the message should be:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
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"
xmlns:imk="http://www.springframework.org/spring-ws/Imk-Zenkiu-Services">
<soapenv:Body>
<imk:enviarMensajeRequest>
<imk:usuario>someuser</imk:usuario>
<imk:clave>somepassword</imk:clave>
<imk:mensaje>somemessage</imk:mensaje>
<imk:contacto>
<imk:buzonSMS>somenumber</imk:buzonSMS>
<imk:primerNombre>somefirstname</imk:primerNombre>
<imk:primerApellido>somelastname</imk:primerApellido>
</imk:contacto>
</imk:enviarMensajeRequest>
</soapenv:Body>
</soapenv:Envelope>
Notice the namespace declaration moving from the enviarMensajeRequest to the soapenv:Envelope and the qualification with imk: on the parameters. I've tried many combinations on the process but my web service, wsdl and xml knowledge is very limited. The provider says that they can't help beyond telling me this. Any ideas? Perhaps a different framework that I can use to create the correct client.
Your provider is wrong, the messages are semantically equivalent; yours is unqualified, theirs is qualified. Are you using Axis or Axis2? If you're using Axis, I suggest you switch to Axis2 for a more robust, standards-compliant SOAP stack (both products are bad, but Axis2 is less-bad).
I assume you are creating your client with wsdl2java? If you can't get this tool to generate the message the way you like, then your best bet is to generate the message programmatically.
With Axis2, you can do this with the AXIOM API. See this link for some example API usage. Note that with most of the methods, e.g. createOMElement, you optionally pass the namespace prefix. So, if your provider requires it, then you could pass a String containing "imk" as the namespacePrefix parameter.
If you end up doing this programmatically and you are only going to be writing a simple client, then I STRONGLY suggest you abandon the Axis/Axis2 approach and use the JAX-WS stack instead, as it is part of Java since 1.6. The API is cleaner and the documentation is better. For example, following is a very simple client I wrote to send a SOAP request to our JIRA server. The sample code creates both qualified and unqualified elements.
QName port = new QName(endpoint, "subversionsoapservice-v2");
QName serviceName = new QName(endpoint, "ISubversionSoapServiceService");
Service service = Service.create(serviceName);
service.addPort(port, SOAPBinding.SOAP11HTTP_BINDING, endpoint);
Dispatch<SOAPMessage> dispatch = service.createDispatch(port, SOAPMessage.class, Service.Mode.MESSAGE);
MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage request = factory.createMessage();
SOAPBody body = request.getSOAPBody();
SOAPElement reindexRepository = body.addChildElement("reindexRepository", "jira", "http://soap.ext.plugin.jira.atlassian.com");
SOAPElement in0 = reindexRepository.addChildElement("in0");
in0.addTextNode("test");
request.saveChanges();
dispatch.invoke(request);
The XML sent by the client looks like this:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<jira:reindexRepository xmlns:jira="http://soap.ext.plugin.jira.atlassian.com">
<in0>test</in0>
</jira:reindexRepository>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>