how to parse data from SOAP reponse message in java - soap

I am using Dom4j to parse SOAP message. I had a problem:
Node node = document.selectSingleNode( "/*/soapenv:Envelope/soapenv:Body/ns:addResponse" );
when I use the above XPath, I got the following exception:
Exception: XPath expression uses unbound namespace prefix ns1
I found ways to do this: remove namespace, which is not recommended.
Any help will be appreciated. Thanks
BTW, is there a better way or toolkit for this work?

You need to create a org.dom4j.XPath object and attach suitable namespace bindings to it. Something like this:
XPath xpath = document.createXPath("/*/soapenv:Envelope/soapenv:Body/ns:addResponse");
Map<String, String> nsb = new HashMap<String, String>();
nsb.put("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
nsb.put("ns", ".....");
Node node = xpath.selectSingleNode(document);
Is there a better way? Well, these days there is JAX-WS, and if there is WSDL available for your service, it is usually very simple to generate Java interfaces and classes for it.

Related

Spring WS remove flexible URL, Restricting WSDL URL and service URL

I'm trying to make a Spring Boot Soap WebService application, and was following the Get Started (https://spring.io/guides/gs/producing-web-service/) example to learn how to do this.
I've created what I want, but I have two URL problems with this setup and I could not find what configuration should I change to fix this :
WSDL URL basic is localhost:8080/ws/countries.wsdl but anything like localhost:8080/ws/whatever/countries.wsdl is correct
service URL for SoapUI request is localhost:8080/ws but anything like localhost:8080/ws/whatever is correct
I know that this is a feature for Spring WS, but I want a fixed URL (without 'whatever' in both cases) and could not find what to change for this
There is no straight forward way to restrict the way you want.
SOAP service is not URL based.
SOAP message body describe the endpoint.
The thing you wanted is possible following way.
Changing URL mapping in ServletRegistrationBean to restrict URL access
Existing /ws/* mapping is the reason why all the /ws/whatever url successfully responded.
Change as new ServletRegistrationBean(servlet, "/ws");
Effect will be you can not request other than /ws URL
Now the problem is, you can not get WSDL by this mapping.
Solution to get WSDL
The DefaultWsdl11Definition is actually generating WSDL from XSD on every request.
Save countries.wsdl to resource folder as static WSDL file.
Remove DefaultWsdl11Definition bean.
Create a new SimpleWsdl11Definition bean as like
#Bean(name = "countries")
public SimpleWsdl11Definition orders() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("countries.wsdl"));
return wsdl11Definition;
}
Now add another static URL mapping in ServletRegistrationBean. As it will be finally look like new ServletRegistrationBean(servlet, "/ws", "/ws/countries.wsdl");
This practice is good for development phase as you can publish easily the changed definition. But it is recommended to use static-wsdl for production environment. Details ** here
Just change
return new ServletRegistrationBean(servlet, "/ws/*");
for example to
return new ServletRegistrationBean(servlet, new String[]{
"/ws/v1/countries.wsdl",
"/ws/v2/countries.wsdl"
});

How to call REST service by setting Matrix Params using Camel-Http4 component?

I have a problem trying to use Camel-http4 component. What I want to do is to set from my camel route the Matrix Params that the REST service needs to work properly. Is there any way to do that?
Thank you,
Roxana
Using traditional query parameters, the Camel URI looks as follows:
from("direct:start")
.to("http4://oldhost?order=123&detail=short");
Thus, using matrix parameters should work as well:
from("direct:start")
.to("http4://oldhost;order=123;detail=short");
Edit:
Use Exchange.HTTP_URI for dynamically setting the properties or use recipientList such as:
from("direct:start")
.recipientList(simple("http4://oldhost;order=${header.123Header};detail={{value.from.cfg}}"));

Alternative to REST when passing objects between servers

I have a spring-mvc project as a frontend project. My datasources are accessed by a second javaee project. This backend grands access to all data my frontend requires, by providing REST services. The REST-Service provides objects, by returning XML. This XML will then get marshaled by my frontend.
So when my frontend project requires current data, I create an HttpUrlConnection, then I call the REST-Service of my backend.
E.g. I want to get a collection of all movie objects:
URL url = new URL(URLSAFE.REST_ALL_MOVIES);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/xml");
connection.getResponseCode();
InputStream is = connection.getInputStream();
Source sauce = new StreamSource(is);
JAXBContext jaxbContext = JAXBContext.newInstance(Movies.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
JAXBElement<Movies> e = unmarshaller.unmarshal(sauce, Movies.class);
Movies m = e.getValue();
this.MOVIELIST = m;
connection.disconnect();
After I added some remote ejb lookups for logging services, I came up with the idea to use rmi for passing objects. However I learned I cant cast the object to my frontend and that there is a big difference between a local object and a object you access by rmi.
But what would be a good attempt for passing objects between servers? I need to pass objects to the frontend because I got to use them with JSP.
I would suggest to take a look at this Spring.io guide. Usage of RestTemplate can remove a lot of boilerplate you have in example, and map REST resources onto POJOs. XML shouldn't be any barrier, because Spring should significantly help you abstract it.

JAX-RS(CXF) JSONProvider

I am new to JAX-RS, I am just starting with apache CXF, I am struck at "No message body writer has been found for response class" while trying to return "application/jason". I know, I can set the JSONProvider using spring context loader file, but I dont want to use spring. Is there any way to set JSONProvider to the application directly?
I made a mistake in my code, instead "application/json" I wrote "application/jason", I corrected it, and it is working. And I found that no need to set JSON Provider explicitly.

How to know strong name of GWT serialization policy at the time of host page generation?

There is an excellent article describing a way to embed GWT RPC payload into the host page. A key element is missing there is how to know Strong Name of RPC serialization policy at run time.
Strong Name is computed at the compile time, put into the client and obfurscated. Strong name is sent to the server with RPC request as described here. What would you suggest to make this parameter available at the time of host page generation?
I have integrated GWT with spring with a custom SerializationPolicyProvider where I always had to rename <strong name>.gwt.rpc file and hard code the name in my custom SerializationPolicyProvider class. I got work around by looking at GWT docs. Strong Name is MD5 hash with length of 32. Each time RPC call is made to Spring based Controller's method: public String processCall(String payload), I parse the payload using following code to get strong name:
String strongName = null;
if(payload!=null){
StringTokenizer tokens = new StringTokenizer(payload,String.valueOf(AbstractSerializationStream.RPC_SEPARATOR_CHAR));
while(tokens.hasMoreTokens()){
String s = tokens.nextToken();
if(s.length() == 32){
strongName = s;
break;
}
}
}
Then in your SerializationPolicyProvider impl class use following:
to get SerializationPolicy:
return SerializationPolicyLoader.loadFromStream(servletContext.getResourceAsStream(moduleBaseURL+"/"+strongName+"gwt.rpc");
One solution seems to be using compiler -gen option. Get _Proxy.java from compiler output and extract SERIALIZATION_POLICY from it.