Restful services in Java – simple client example

I suppose that a restful server isn’t all that useful unless there is a way to query this information back and use it in some useful way.

It is easy enough to test this out the server from the command line using the curl command.  Simply select the return type and select the URI.

curl -H “Accept: text/plain” http://192.168.178.70:8080/FirstRestful/Communicate/hello

 

curl -H “Accept: application/xml” http://192.168.178.70:8080/FirstRestful/Communicate/hello

This is the best starting point as we can pretty much guarantee that the server is working. Should any problems occur during the development of the client we can pretty much point to the client as the culprit.

Java client

My first web services client will be essentially just a plain old java program.  Although I am using java for my client I can easily imagine that there are some systems that were programmed in some older languages that use also use restful services in this same manner.  Not only communicate with a web server but to provide an easy way to enhance those systems with abilities that were didn’t exist when they were created (I am looking at you COBOL ).

Jersey makes the process of making restful calls easy from Java.  The restConnect method groups together the necessary logic for accessing a URI that is passed in.

Once these steps are done the object is a WebTarget is initialized and it is possible to call the restful service.

In this example client example I use use three slightly different methods for setting up the URI.  The two more flexible calls (lines 68 – 78) setup a base URI and then adds to the path.  This might be the best way if quite a few similar calls were necessary.

When doing the restful calls you also pass in the datatype that you wish to be returned back.  This then does the proper call to the server to get the correct return type.

/**
 * 
 */
package com.acmesoft;

import java.io.StringReader;
import java.net.URI;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.glassfish.jersey.client.ClientConfig;

public class TestClient 
{
	String uribase = "http://192.168.178.70:8080/FirstRestful";
	String urifull = uribase + "/Communicate/hello";

	public void showMagazine(String desc, magazine value)
	{
		System.out.println("\n" + desc );
		System.out.println("year "  + value.getYear());
		System.out.println("month " + value.getMonth());
		System.out.println("price " + value.getPrice());
		System.out.println("title " + value.getTitle());
	}
	
	public magazine convertXmlToMag(String xmlstring)
	{
		magazine converted = null;
		JAXBContext jc = null;
		try {
			jc = JAXBContext.newInstance(magazine.class);
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			StringReader reader = new StringReader(xmlstring);
			converted = (magazine) unmarshaller.unmarshal(reader);	
		}
		catch (JAXBException ex)
		{
			ex.printStackTrace();
		}
		return converted;
	}
	
	public WebTarget restConnect(String targetUrl)
	{
		URI uri = UriBuilder.fromUri(targetUrl).build();
		ClientConfig config = new ClientConfig();
		Client client = ClientBuilder.newClient(config);
		WebTarget target = client.target(uri);
		return target;
	}
	
	public TestClient()
	{
		// example 1
		WebTarget target = restConnect(urifull);
		String plainAnswer = target.request().accept(MediaType.TEXT_PLAIN).get(String.class);
		System.out.println("raw (text)data");
		System.out.println(plainAnswer);
		System.out.println("");
		
		// example 2/3 setup
		ClientConfig config1 = new ClientConfig();
		Client client1       = ClientBuilder.newClient(config1);
		WebTarget target1    = client1.target(uribase);

		// example 2
		String xmlAnswer = target1.path("/").path("Communicate").path("/hello").request().accept(MediaType.APPLICATION_XML).get(String.class);
		magazine converted = convertXmlToMag(xmlAnswer);
		System.out.println(xmlAnswer);
		showMagazine("xml text data", converted);
		
		// example 3
		magazine xmlobj = target1.path("/Communicate/hello").request().accept(MediaType.APPLICATION_XML).get(magazine.class);
		showMagazine("pure xml object", xmlobj);
	}
	
	public static void main(String[] args) 
	{
		new TestClient();
	}
}

Below is the magazine class with the appropriate markups to easily do the JAXB conversion between plain old java objects and XML.

package com.acmesoft;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessType;

@XmlRootElement(name="Magazine")
@XmlAccessorType(XmlAccessType.FIELD)
public class magazine {

	// Microsoft Exchange values 
	@XmlElement(name="Year")
	private  int year; 

	@XmlElement(name="Month")
	private  int month; 

	@XmlElement(name="Title")
	private   String title; 

	@XmlElement(name="Price")
	private   double price;

	public magazine()
	{
	}
	public magazine(int year, int month, String title, double price)
	{
		this.year = year;
		this.month = month;
		this.title = title;
		this.price = price;
	}

	public int getYear()
	{
		return year;
	}
	public void setYear(int value)
	{
		this.year= value;
	}

	public int getMonth()
	{
		return month;
	}
	public void setMonth(int value)
	{
		this.month= value;
	}

	public String getTitle()
	{
		return title;
	}
	public void setTitle(String value)
	{
		this.title = value;
	}

	public double getPrice()
	{
		return price;
	}
	public void setPrice(double value)
	{
		this.price = value;
	}
}

The flexibility of the restful API calls  is pretty amazing. The first example (lines 62-67) shows how easy it can be to call a restful service.  Nothing is all that surprising as the server is passing back text and that text is assigned to a string.

The second example is slightly more useful as the return data is XML formatted and it is possible to convert that into a java object using JAXB.  XML data is still text data and it shouldn’t be amazing that text data is returned and assigned to a string.  Manually parsing out the data from an XML structure is really painful so I created the method convertXmlToMag to parse the XML into a java object.

The third example is by far the most useful example.  The restful server returns XML data but when making the restful call instead of passing in a string class I pass in a magazine class.  Thus the restful call returns the magazine object directly.  This also isn’t magic as the class does need to be defined when compiling the client but that is pretty much to be expected.  If the server does have certain types of data you wish to query then the client would already have similar or identical structured objects.

raw (text)data
Hello World
Having a great time!

200
<Magazine><Year>2016</Year><Month>6</Month><Title>Economist</Title><Price>9.99</Price></Magazine>

xml text data
year 2016
month 6
price 9.99
title Economist

pure xml object
year 2016
month 6
price 9.99
title Economist
This entry was posted in programming, Setup From Scratch and tagged , , . Bookmark the permalink.