I've got a working Dropwizard project, which has several ways of getting data it needs. One of those ways is the JAX-RS client that Dropwizard provides, the JerseyClient. This client is configured so that it suits my needs (uses the proper proxy, timeouts etc...)
Now my project has a new requirement for which I need to do a SOAP call. I've got that functionally working using the following code:
// not the actual structure, edited to make a minimal example
// SERVICE_QNAME and PORT_QNAME are hardcoded strings, config.url comes
// from the configuration
import javax.xml.ws.*;
import javax.xml.ws.soap.*;
import javax.xml.namespace.QName;
Service service = Service.create(SERVICE_QNAME);
service.addPort(PORT_QNAME, SOAPBinding.SOAP11HTTP_BINDING, config.url);
Dispatch dispatch = service.createDispatch(PORT_QNAME, SOAPMessage.class, Service.Mode.MESSAGE);
dispatch.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, config.url);
Message message = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
// do stuff to fill the message
response = dispatch.invoke(message);
This is all out-of-the-box behaviour, anything happening here is provided either by java (8) or Dropwizard.
This code however uses it's own http connectors, bypassing anything I've set up in my JAX-RS client. I would like to re-use the JerseyClient's http capabilities in the JAX-WS client in a non-copy-paste kinda way.
Is there a way I can set up the Dispatch so that it will use the existing http connectors? Or some other SOAP client to achieve the same?
Thank you #zloster for the research and suggestions. I decided to take another route however.
I found the SAAJ standard and am using that now. I created a subclass for javax.xml.soap.SOAPConnection and based that on com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection. That part wasn't all that hard and leaves me with a relatively small class.
Now in my code I replaced the code above with something along these lines:
SOAPConnection soapConnection = new JerseySOAPConnection(httpClient, soapProtocol);
Message message = MessageFactory.newInstance(soapProtocol).createMessage();
// do stuff to fill the message
response = soapConnection.call(message, config.url);
Due to my implementation not all that portable, but I don't really need it to be. Again, thanks for those who helped me get to this!
Related
I have a few questions about a specific REST call I'm making in JAVA. I'm quite the novice, so I've cobbled this together from several sources. The call itself looks like this:
String src = AaRestCall.subTrackingNum(trackingNum);
The Rest call class looks like this:
public class AaRestCall {
public static String subTrackingNum (Sting trackingNum) throws IOException {
URL url = new URL("https://.../rest/" + trackingNum);
String query = "{'TRACKINGNUM': trackingNum}";
//make connection
URLConnection urlc = url.openConnection();
//use post mode
urlc.setDoOutput(true);
urlc.setAllowUserInteraction(false);
//send query
PrintStream ps = new PrintStream(urlc.getOutputStream());
ps.print(query);
ps.close();
//get result
BufferedReader br = new BufferedReader(new InputStreamReader(urlc
.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line=br.readLine())!=null) {
sb.append(line);
}
br.close();
return sb.toString();
}
}
Now, I have a few questions on top of the what is wrong with this in general.
1) If this rest call is returning a JSON object, is that going to get screwed up by going to a String?
2) What's the best way to parse out the JSON that is returning?
3) I'm not really certain how to format the query field. I assume that's supposed to be documented in the REST API?
Thanks in advance.
REST is a pattern applied on top of HTTP. From your questions, it seems to me that you first need to understand how HTTP (and chatty socket protocols in general) works and what the Java API offers for deal with it.
You can use whatever Json library out there to parse the HTTP response body (provided it's a 200 OK, that you need to check for, and also watch out for HTTP redirects!), but it's not how things are usually built.
If the service exposes a real RESTful interface (opposed to a simpler HTTP+JSON) you'll need to use four HTTP verbs, and URLConnection doesn't let you do so. Plus, you'll likely want to add headers for authentication, or maybe cookies (which in fact are just HTTP headers, but are still worth to be considered separately). So my suggestion is building the client-side part of the service with the HttpClient from Apache commons, or maybe some JAX-RS library with client support (for example Apache CXF). In that way you'll have full control of the communication while also getting nicer abstractions to work with, instead of consuming the InputStream provided by your URLConnection and manually serializing/deserializing parameters/responses.
Regarding the bit about how to format the query field, again you first need to grasp the basics of HTTP. Anyway, the definite answer depends on the remote service implementation, but you'll face four options:
The query string in the service URL
A form-encoded body of your HTTP request
A multipart body of your HTTP request (similar to the former, but the different MIME type is enough to give some headache) - this is often used in HTTP+JSON services that also have a website, and the same URL can be used for uploading a form that contains a file input
A service-defined (for example application/json, or application/xml) encoding for your HTTP body (again, it's really the same as the previous two points, but the different MIME encoding means that you'll have to use a different API)
Oh my. There are a couple of areas where you can improve on this code. I'm not even going to point out the errors since I'd like you to replace the HTTP calls with a HTTP client library. I'm also unaware of the spec required by your API so getting you to use the POST or GET methods properly at this level of abstraction will take more work.
1) If this rest call is returning a JSON object, is that going to get
screwed up by going to a String?
No, but marshalling that json into an obect is your job. A library like google gson can help.
2) What's the best way to parse out the JSON that is returning?
I like to use gson like I mentioned above, but you can use another marshal/unmarhal library.
3) I'm not really certain how to format the query field. I assume
that's supposed to be documented in the REST API?
Yes. Take a look at the documentation and come up with java objects that mirror the json structure. You can then parse them with the following code.
gson.fromJson(json, MyStructure.class);
Http client
Please take a look at writing your HTTP client using a library like apache HTTP client which will make your job much easier.
Testing
Since you seem to be new to this, I'd also suggest you take a look at a tool like Postman which can help you test your API calls if you suspect that the code you've written is faulty.
I think that you should use a REST client library instead of writing your own, unless it is for educational purposes - then by all means go nuts!
The REST service will respond to your call with a HTTP response, the payload may and may not be formatted as a JSON string. If it is, I suggest that you use a JSON parsing library to convert that String into a Java representation.
And yes, you will have to resort to the particular REST API:s documentation for details.
P.S. The java URL class is broken, use URI instead.
I am implementing a TV listing service and I have decided to use ROVI as my data provider.
They provide me with an API that allows me to exchange data between my application and their servers by means of SOAP requests.
Since I am programming in Java, I used wsimport to generate the classes that would enable me to interact with their server.
//Connection
service = new ListingsService();
port = service.getListingsServiceSoap();
I have come across a problem which Google doesn't seem to have the answer for.
According to their API, whenever I want to make a call to a SOAP service I have to add my API Key to the end of url.
The problem is, I don't know how to do that. Using the stubs generated by wsimport, I can create a request object as it should be; however the URL is not displayed as per their specification. The url I currently get is: http://api.rovicorp.com/v9/listingsservice.asmx and what is required is: http://api.rovicorp.com/v9/listingsservice.asmx?apikey=myAPIkey. I obtained that by printing the following code:
System.out.println(port.toString());
Trying to run the following code:
GetServicesRS servicesRS = port.getServices(getServicesRQ, auth)
Yields the following error:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 403: Forbidden
What java method can I use to append this parameter into the SOAP request URL.
Thanks for your help.
Edit.
I am still struggling with this and haven't been lucky with responses, if anyone could point me in the direction of a framework or something that could facilitate this would be great!
Cheers
I manage to work around my problem using something called BindingProvider.
I added the following to my code:
//Connection
service = new ListingsService();
port = service.getListingsServiceSoap();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://api.rovicorp.com/v9/listingsservice.asmx?apikey=" + APIKey);
With the aforementioned code the call to the API is successful:
GetServicesRS servicesRS = port.getServices(getServicesRQ, auth)
Hope it helps someone in the future.
I am having a Java applet developed on my behalf. The applet makes AJAX requests to a server. I have not written the server code yet.
Is there a design pattern I can use to mock the server responses, whilst the server is not yet ready, so that the applet can be developed and tested against this "mock server"?
Some sample code on how to implement the mockup server would be very useful
Although I'm not entirely sure if this suits your needs, but you can checkout a simple class I made for this purposes here. Here is some sample code:
//let's say that when you GET to /users?id=2 the server should return the user with id 2
//first start the server on your favourite port
MockHttpServer server = new MockHttpServer(portNum);
server.start();
//We will add a mock response for every request we will do, so in this case, just one mock response
server.enqueueResponse(Status.OK, "application/json,"{\"user_id\":15,\"name\":\"paul\"}");
//now we will use curl or whatever to make the GET
curl http://0.0.0.0:3000/users?id=2
// we get the request object
Request req = server.getRequest();
assertEquals(req.getMethod(),"GET");
assertEquals(req.getParams().get("id"),"2")
Its still a work in progress but you can get an idea by reading the code on github. Hope it helps :)
I am trying to create a java application to read the information from ARIN using an IP Address. I see ARIN is using RESTful Web Services to get the IP information but I am not sure what I need to do to start. Some people are talking about RESTLET, other people about JAX-RS,etc. Can you please help me to take me in the right direction? Thanks!
Restlet also has a client API to interact with a remote RESTful application. See the classes Client, ClientResource for more details. For this, you need to have following jar files from Restlet distribution:
org.restlet: main Restlet jar
org.restlet.ext.xml: Restlet support of XML
org.restlet.ext.json: Restlet support of JSON. In this case, the JSON jar present in libraries folder is also required.
If I use the documentation located at this address https://www.arin.net/resources/whoisrws/whois_api.html#whoisrws. Here is a simple Restlet code you can use:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get();
// Display the XML content
System.out.println(repr.getText());
or
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN.txt");
Representation repr = cr.get();
// Display the text content
System.out.println(repr.getText());
Restlet also provides some support at XML level. So you can have access to hints contained in the XML in a simple way, as described below:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get();
DomRepresentation dRepr = new DomRepresentation(repr);
Node firstNameNode = dRepr.getNode("//firstName");
Node lastNameNode = dRepr.getNode("//lastName");
System.out.println(firstNameNode.getTextContent()+" "+lastNameNode.getTextContent());
Note that you can finally handle content negotiation (conneg) since it seems supported by your REST service:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get(MediaType.APPLICATION_JSON);
In this case, your representation object contains JSON formatted data. In the same way than the DomRepresentation, there is a JsonRepresentation to inspect this representation content.
Hope it helps you.
Thierry
The problem is that you don't seem to understand very well what REST is (sorry if I'm mistaken!). Restlet and JAX-RS are both server-side related.
You probably need something like jersey-client. This is a library which helps to interact with RESTful webservices.
You could also usa plain Java libraries to make HTTP calls to the webservice. REST is tightly bound to its implementation protocol. This means that if the webservice is implemented in HTTP (most likely is) you don't need anything fancy to interact with it. Just HTTP.
I strongly encourage you to learn more about REST and HTTP itself.
This is probably an easy question for anyone with any moderate expertise with web services using Apache Axis.
I have a web service client that was generated by wsdl2java in Axis 1.4. I am writing unit tests that need to access the actual SOAP message itself, and do a comparison to the client side java classes which are generated by Axis. (don't ask)
How can I retrieve the actual SOAP message from a response from the service?
From what I can gather from searching around is that I have to get the MessageContext.
I have tried something along these lines...
MessageContext mc = MessageContext.getCurrentContext();
String message = mc.getCurrentMessage().getSOAPPartAsString();
But mc is null in this case....
Any help is appreciated!
This is how it's done.
http://users.skynet.be/pascalbotte/rcx-ws-doc/jaxrpchandler.htm
When _call object is filled calling the line below gives it.
String request=_call.getMessageContext().getRequestMessage()
.getSOAPPart().getEnvelope().toString();
For response use the below one
_call.getMessageContext().getResponseMessage()
.getSOAPPart().getEnvelope().toString()
Call is a org.apache.axis.client.Call as you know.