I am developing a client-side Java application that has a bit of functionality that requires getting data from some web services that transmit in JSON (some RESTful, some not). No JavaScript, no web browser, just a plain JAR file that will run locally with Swing for the GUI.
This is not a new or unique problem; surely there must be some open source libraries out there that will handle the JSON data transmission over HTTP. I've already found some that will parse JSON, but I'm having trouble finding any that will handle the HTTP communication to consume the JSON web service.
So far I've found Apache Axis2 apparently which might have at least part of the solution, but I don't see enough documentation for it to know if it will do what I need, or how to use it. Maybe part of the problem is that I don't have experience with web services so I'm not able to know a solution when I see it. I hope some of you can point me in the right direction. Examples would be helpful.
Apache HttpClient 4.0
is the best in the business and is moderately easy to learn.
If you want easier you could use HtmlUnit which imitates the behaviour of browsers so you could easily get the content (and parse it into Html, javascript and css, you could also execute javascript code on content so you could probably parse JSON files to using JSON.parse or any other equivalent functions) of any page on the web.
so for HtmlUnit here is a sample code:
WebClient wc = new WebClient(BrowserVersion.FIREFOX_3_6);
HtmlPage page = wc.getPage("http://urlhere");
page.executeJavaScript("JS code here");
but it maybe rather heavy for your requirements so a highly recommend the use of HttpClient library.
I'm sure you could find many JSON libraries for java but here is one for you json-lib
I did it using a simple Java JSON libary. Use the Google library..
URL url = new URL("http://www.siteconsortium.com/services/hello.php");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
JSONParser parser=new JSONParser();
Object object = parser.parse(in);
JSONArray array = (JSONArray) object;
JSONObject object2 = (JSONObject)array.get(0);
System.out.println(object2.get("hello"));
If the webservice uses OAuth and an access token you can't use the above example though.
Its great to see that your web services are RESTful. RESTful web services are pretty easy to develop and to consume.Well... you do not need to take any extra care to tranmit JSON data over the network... Data whether is in JSON on in XML format are embedded into the HTTP header..Following code snippet will help you understand the idea :
httpConnection = new HTTPConnectionManager(request);
HttpURLConnection httpURLConnection = httpConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
in = httpURLConnection.getInputStream();
int x;
StringBuilder stringBuilder = new StringBuilder();
while ((x = in.read()) != -1) {
stringBuilder.append((char) x);
}
XMLParser xmParser = new XMLParser();
....
....
}
In this code i am receiving data in XML format from web services.After receiving the data into a StringBuilder object,i am parsing the XML. In the same way you can call your web services using this code and can receive your JSON data. you can use javaJSON APIs,available Here, to extract the data from JSON notation.
Hope code will help you...
PS: HTTPConnectionManager,XMLParser and Request(request object) classes are not any standard APIs. they are written by my own account to handle multiple web service calls. This code snippet is just to give you my idea.
Related
I have a rest application that can export some report data from Elasticsearch. It is easy to do with the Java API:
SearchResponse response = getClient()
.prepareSearch("my_index_name")
.setQuery(QueryBuilders.someQuery())
.addAggregation(AggregationBuilders.someAggregation())
.get();
The problem starts with the big responses. Using this code snippet, the response is read to build the SearchResponse object in memory. In my case, the response does not fits in memory.
Paging cannot help because we often need to return the full data and Aggregations do not support paging yet.
I know that I can use the Elasticsearch REST API to read the response as stream, but manually build the request it is cumbersome. I really want something like this:
// my dream API
InputStream response = getClient()
.prepareSearch("my_index_name")
.setQuery(QueryBuilders.someQuery())
.addAggregation(AggregationBuilders.someAggregation())
.getStream();
So, can the Elasticsearch Java API stream the SearchResponse?
A proposal for streaming results does exist but it doesn't seem to have picked up steam so far and was closed (for now).
There's a way to do it with XContentBuilder but that still requires the whole response to be in memory before being sent.
It might not be what you want, but that's the closest thing that I know which could fulfill your need. Worth giving it a try.
I believe there is no way to obtain an InputStream from the Java API (but I might be wrong). I also think there is no way to directly obtain an InputStream in Jest (a REST-based Elasticsearch Java API).
You mention that it is cumbersome to create the search request to the _search endpoint yourself: if you're referring to building the actual json query, I just would like to point out that once you have a SearchSourceBuilder, you can call toString() on it to get a fully working json representation of your query.
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(this.getQuery())
.from(this.getFrom())
.size(this.getSize())
.fetchSource(this.getSource(), null);
this.getSort().forEach(sourceBuilder::sort);
sourceBuilder.toString() // the json representation
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 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.
I am trying to get the raw XML response from a web service, instead of the usual set of POJOs.
I am using a webservice client that I generated (so I have access to the client's code) from a WSDL and some schemas. The client is generated in RAD 7.5, I think using JAX-WS. I've been looking at the client code itself, but I'm not even sure if the client code ever handles raw XML or if it passes it off to other libraries.
You can do it using
javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>
you can simply get message using SOAPMessageContext#getMessage() and convert message to String using method
public static String getXmlMessage(SOAPMessage message) throws Exception
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
final String encoding = (String) message.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (encoding == null)
{
return new String(os.toByteArray());
}
else
{
return new String(os.toByteArray(), encoding);
}
}
Also you can read here about SOAP handler on client side
Article
It's not widely documented, but you can use the Dispatch interface to implement JAXWS clients which work directly w/ the XML. Here and here are some articles for getting started.
.NET has the HttpWebRequest and WebClient classes for simulating a browser's requests.
I'd google it, but I'm not sure what keyword to use.
I want to write code that does does HTTP GETs and POSTs, along with cookies, in an applet or local .jar and gives me back the response in a text string or some other parseable structure.
HttpURLConnection is Java's equivalent of HttpWebRequest.
URL iurl = new URL(url);
HttpURLConnection uc = (HttpURLConnection)iurl.openConnection();
uc.connect();
if (uc.getContentType().equalsIgnoreCase("image/jpeg"))
{
result = true;
}
Apache HTTPClient has equivalent functionality, though the APIs are not exactly the same. Oakland Software has a table comparing their commercial product with various alternatives, including the Apache product. Apache's own opinion of the built-in HttpUrlConnection (quoted from the above linked-to page) is:
The jdk has the HttpUrlConnection
which is limited and in many ways
flawed.
Here's a link to the HTTPClient tutorial.
html unit for me.
i can simulate javascript (to a certain extent)
Verify Webclient in Apache Cx JaxRs Library.
Checkout this:
https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxrs/client/WebClient.html
Sample code looks below:
WebClient client = WebClient.create(url);
client.path(ADD_PATH).path("/books/2").accept("text/plain");
s = client.get(String.class);
System.out.println(s);