Validate WebService message against Schematron - java

I have generated a web service client using JAX-WS and wsimport.
This is my client code:
URL url = new URL("http://localhost:9999/ws/processstuff?wsdl");
QName qname = new QName("namespace", "ProcessStuffImplService");
Service service = Service.create(url, qname);
ProcessStuffInterface processStuffInterface = service.getPort(ProcessStuffInterface.class);
ProcessStuffObject processStuffObject = new ProcessStuffObject();
//Web service call
processStuffInterface.processStuff(processStuffObject);
I need to validate processStuffObject against given Schematron rules before making the web service call above. I have looked at libraries like ph-schematron, but it seems like validation can only made on objects like File or similar. Does anyone know a way to validate an object generated with JAX-WS, like my ProcessStuffObject, against Schematron rules?
Update:
Now I have marshalled ProcessStuffObject to a File object that can be validated with ph-schematron, but this seems like a really stupid solution.

JAX-WS is normally going to use JAXB to marshal objects to XML for sending over the wire and unmarshal received XML into objects. The JAXB API offers some useful stuff for transparently handling an object like XML without explicitly having to first marshal it to a file, String, byte array or other intermediate representation.
The class you need is JAXBSource. It implements the javax.xml.transform.Source interface and lets you provide an object and a JAXBContext or a Marshaller. You can then supply it as a source for transformations or other methods that take such an instance. Some of the ph-schematron methods accept a Source as input, such as this one.
If you pre-compile the Schematron files to an XSLT you could just use the Java XML transformation API and supply the Source to the transformer.

Related

How does biding happens in JAX-Rs xml to object?

I have been exploring on how to consume the web services and I found a good articles on JAX-Rs and it is the way to consume Rest Webservices. my task is to hit the URL which returns the XML as response and should be converted into Object which I have achieved using following code.
client = ClientBuilder.newClient();
//example query params: ?q=Turku&cnt=10&mode=json&units=metric
target = client.target(
"http://api.openweathermap.org/data/2.5/weather")
.queryParam("appid", apikey)
.queryParam("units", "metric")
;
And here is the piece of code which will map my XML response to java object
Example exampleObject = target.request(MediaType.APPLICATION_XML).get(Example.class);
This works fine, but the issue is my lead is saying use JIBX since it's faster.
Question 1 : How does target.request converts the xml response (does it use jibx or jaxb etc ?? )
Question 2 : If I have use JIBX I need to download the response as stream and do the marshalling and unmarshalling which I found not a right way to consume webservices, I am I right??
Please do help on this.
1: JAX-RS uses MessageBodyReaders to convert the HTTP entity stream into an object. By default, all JAX-RS implementations are required to ship a MessageBodyReader (and Writer) that uses JAXB to serialize/deserialize to/from XML when the content type is application/xml.
2: If you want to use something other than JAXB to deserialize XML, you could write your own MessageBodyReader that consumes “application/xml”. That would override the built-in JAXB reader.
An example of how to do this is available here:
https://memorynotfound.com/jax-rs-messagebodyreader/
Hope this helps, Andy

How to convert JSON to list of POJOs using RestEasy

I have to integrate our j2ee application with a REST webservice. And I wanted to use the RestEasy JAX-RS implementation from JBoss. The webservice returns an array in JSON format. I've this piece of code:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://myservices.com/schemes/all");
Response response = target.request().get();
Can I map this "response" object to List<Scheme> using RestEasy? Thanks
Provided that your JSON provider is capable of converting JSON to appropriate entities, then yes. The get method you call in the code has an overloaded version which accepts the class of entity to which the result is to be converted. Since there are problems with serializing certain collections' implementations, your type has to be wrapped in GenericType class, like that:
List<Scheme> schema = [...].get(new GenericType<List<Scheme>>(){});
The above method should work with just about every JAX-RS-compliant implementation.
You can also use Jackson library, which allows you (amongst other things) to pass collections without need of wrapping them.

getting raw payload from JAX-WS service

Having a SOAP based web service with XML payload, how can I grab the XML payload of the service response in JAX-WS >2.0 client?
I can see how this question will be marked as duplicate, but bear with me.
It seems that the options are:
Use Dispatch API. However this would require me to go low(er) level and create the request payload manually, which I want to avoid.
Use handler infrastructure of the JAX-WS to grab the payload and possibly pass it via MessageContext property back to the client, but this will still unmarshall the XML into JAXB Object tree, which I want to avoid.
So, how can I:
Call a web service using SEI - no messing with creating XML request from scratch
Grab the 'RAW' XML response without the JAXB unmarshalling happening
Sounds simple enough, right?
Among the non-goals the JAX-WS 2 specification says that
'Pluggable data binding JAX-WS 2.0 will defer data binding to JAXB[10]; it is not a goal to provide a
plug-in API to allow other types of data binding technologies to be used in place of JAXB. However,
JAX-WS 2.0 will maintain the capability to selectively disable data binding to provide an XML based
fragment suitable for use as input to alternative data binding technologies.'
So, you should be able to have access to the raw payload.
The following example is also in the specification :
4.3.5.5 Asynchronous, Callback, Payload-Oriented
class MyHandler implements AsyncHandler<Source> {
...
public void handleResponse(Response<Source> res) {
Source resMsg = res.get();
// do something with the results
}
}
Source reqMsg = ...;
Service service = ...;
Dispatch<Source> disp = service.createDispatch(portName,
Source.class, PAYLOAD);
MyHandler handler = new MyHandler();
disp.invokeAsync(reqMsg, handler);
Since the specification also states that a Binding has its own HandlerChain (see chapter 9) you should be able to remove the JAXB handler from the chain, so that JAXB marshalling/unmarshalling doesn't get involved.

Java REST client without schema

Goal
Java client for Yahoo's HotJobs Resumé Search REST API.
Background
I'm used to writing web-service clients for SOAP APIs, where wsimport generates proxy stubs and you're off and running. But this is a REST API, which is new to me.
Details
REST API
No WADL
No formal XML schema (XSD or DTD files). There are example XML request/response pairs.
No example code provided
Progress
I looked at question Rest clients for Java?, but the automated solutions there assume you are providing both the server and the client, with JAXB invoked on POJOs to generate a schema and a REST API.
Using Jersey (a JAX-RS implementation), I have been able to make a manual HTTP request:
import com.sun.jersey.api.client.*;
...
ClientConfig clientConfig = new DefaultClientConfig();
Client client = Client.create(clientConfig);
WebResource webResource = client.resource("https://hj.yahooapis.com/v1/HJAuthTokens");
webResource.accept("application/xml");
// body is a hard-coded string, with replacements for the variable bits
String response = webResource.post(String.class, body);
// parse response into a org.w3c.dom.Document
// interface with Document via XPATH, or write my own POJO mappings
The response can look like:
<?xml version="1.0" encoding="utf-8"?>
<Response>
<ResponseCode>0</ResponseCode>
<ResponseMessage>Login successful</ResponseMessage>
<Token>NTlEMTdFNjk3Qjg4NUJBNDA3MkJFOTI3NzJEMTdDNDU7bG9jYWxob3N0LmVnbGJwLmNvcnAueWFob28uY29tO0pVNWpzRGRhN3VhSS4yQVRqRi4wWE5jTWl0RHVVYzQyX3luYWd1TjIxaGx6U0lhTXN3LS07NjY2MzM1OzIzNDY3NTsxMjA5MDE2OTE5OzZCM1RBMVNudHdLbl9VdFFKMFEydWctLQ==</Token>
</Response>
Or, it can look like:
<?xml version="1.0" encoding="utf-8"?>
<yahoo:error xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" xml:lang="en-US">
<yahoo:description>description</yahoo:description>
<yahoo:detail>
<ErrorCode>errorCode</ErrorCode>
</yahoo:detail>
</yahoo:error>
Questions
Is there a way to auto-generate POJOs which can be marshalled/unmarshalled without a formal schema?
Should I attempt to generate those POJOs by hand, with JAXB annotations?
Is there some tool I should be leveraging so I don't have to do all this manually?
It's interesting that they provide an HTTP URL as the namespace URI for the schema, but don't actually save their schema there. That could be an oversight on their part, which an email or discussion-list posting could correct.
One approach is to create your own schema, but this seems like a lot of work for little return. Given how simple the messages are, I wonder if you even need a POJO to wrap them? Why not just have a handler that extracts the data you need using XPath?
Edit: blast from the past, but I saw the comment, reread the question, and realized that the first sentence was hard to understand. So, clarification:
One very good habit, if you're going to write a publicly accessible web service, is to make your schema document available at the same URL that you use for the schema's namespace URI -- or better, have that URL be a link to complete documentation (the W3C XSD namespace is itself a good example: http://www.w3.org/2001/XMLSchema).
I would suggest writing beans by hand, and only annotating with JAXB annotations if you have to. For most accessors/mutators (getters/setters) you do not have to; by default all public bean accessors and fields are considered, name is derived using bean convention, and default is to use elements instead of attributes (so attributes need to be annotated).
Alternatively you can of course write schema by hand, generate beans using JAXB, if you like W3C Schema a lot. And just use resulting code, not schema, for data binding.
As to POJO: that can be very simple. Something like:
#XmlRootElement("Response")
class Response {
public int responseCode;
public String responseMessage;
public String token; // or perhaps byte[] works for automated base64?
}
and similarly for other ones. Or, use getters/setters if you like them and don't mind bit more verbosity. These are just data containers, no need to get too fancy.
And if you must auto-detect type from content, consider using Stax parser to see what the root element, and then bind using JAXB Unmarshaller, handing XMLStreamReader that points to that root element. That way you can pass different object type to bind to.
And finally: sending/receiving requests: plain old HttpURLConnection works ok for GET and POST requests (construct using, say, URL.openConnection()). Jakarta HttpClient has more features if need be. So oftentimes you don't really need a separate REST client -- they may come in handy, but generally build on simple http client pieces.
I find HTTP4E very useful for making REST calls. It is an awesome Eclipse plugin, it has tabs, syntax coloring, auto suggest, code generation, REST HTTP call replay, etc.. It does a great job of HTTP debugging, HTTP tampering, hacking. I am having so much fun with it.
http://www.ywebb.com/
Try JdkRequest from jcabi-http (I'm a developer). This is how it works:
String body = new JdkRequest("http://www.google.com")
.header("User-Agent", "it's me")
.fetch()
.body()
Check this blog post for more details: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

Axis2 Web Service Client Generation - Types without modifying the client

Is it possible with Axis2 and Eclipse to generate a Web Service client and have it use java types that you already have in packages instead of creating it's own types. Reason being of course if I have type A already created and it creates it's own Type A I can't just assign variable of type A to variable of type B.
The wsdl is being generated from a Web Service deployed to an application server.
If it's not possible to generate it from that would it be possible to generate a client from the already existing java files.
If you really want to reuse existing classes, you can call the Axis2 API directly without generating a client using wsdl2java. Below is some relatively simple code to call a web service. You just need to fill in the web service endpoint, method QName, expected return Class(es), and arguments to the service. You could reuse your existing classes as the return values or arguments.
If your web service is pretty complicated then you may find that you have to go deeper into the API to get this approach to work.
serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://myservice");
options.setTo(targetEPR);
QName methodName = new QName("ns","methodName");
Class<?>[] returnTypes = new Class[] { String.class };
Object[] args = new Object[] { "parameter" };
Object[] response = serviceClient.invokeBlocking(methodName, args,
returnTypes);
You are generating the web service client from wsdl, correct?
The only thing that the wsdl2java tool knows about is the information in the wsdl, so it won't know about any types that you have already created.
If you can get the type information into the wsdl you may get it to work, although I have never tried.
If you want an easy way to copy from Type A to Type B then you could try BeanUtils.copyProperties, as long as the setters and getters of Type A and Type B match.
pretty much most java webservices projects go through this. I don't know if the .NET/C# world have a more elegant solution.
It makes sense, as Mike mentioned, to use BeanUtils.copyProperties.
BR,
~A
If you use eclipse as your ide, that is waht you need: http://www.eclipse.org/webtools/. It does beyond other things exactly what you want.
You can directly use ServiceClient class to call web service, which provides call using XML only and returns XML response. For different methods of web service, you have to convert the XML response to some java POJO to use it. Only Response handling needs to be done at your end. that you can do like from XML to Map etc...
So you won't need any other stub classes to call any web service, only needs to handle response XML. You can convert XML to POJO using Castor or JAXB libs.
This is the way you don't need to modify your client every time for diff. web services. You can develop like providing a response handler to client externally. So that for every different web service you will have diff. response handler class which is implementation of you interface.
//common interface for response handlers...
//implement this for diff. web service/methods
public interface WSRespHandler{
public Object getMeResp(Object respData);
}
//pass particular handler to client when you call some WS
public class WebServiceClient {
public Object getResp(WSRespHandler respHandler) {
..
return repHandler.getMeResp(xmlData);
}
}
reference:
http://www.developer.com/java/web/article.php/3863416/Using-Axis2-and-Java-for-Asynchronous-Web-Service-Invocation-on-the-Client-Side.htm
http://www.devdaily.com/blog/post/java/java-web-service-client-read-array-list/
thanks.
www.techlads.com
In case this post is still of any use to someone I read the axis2 generating clients guide: http://axis.apache.org/axis2/java/core/docs/userguide-creatingclients.html.
It seems that the Axis2 Eclipse plugin is configured to call ADB code generation in integrated mode (see http://axis.apache.org/axis2/java/core/docs/adb/adb-howto.html), thus creating inner classes in the Web service stub. I don't know if changing the generation mode to expanded mode (generate data classes out of the stub class) is possible, but you can do it command line using Wsdl2Java:
%AXIS2_HOME%\bin\WSDL2Java -uri <wsdl file path> -p <package name> -u
The -u option tells the ADB code generator to create data classes as separate classes and not inner classes in the stub.

Categories

Resources