REST asleep – how to construct an HTTP server in Java

REST? What? An HTTP server to „communicate“ with via URLs? Yes, why not. In certain use cases a valid solution for various different tasks. Especially for the idea of displaying more or less ’static‘ information on a display.

In my case such a server handles tasks such as

  • fetching the next x entries in a (google) calendar
  • retrieving and preprocessing actual weather data from openweathermap
  • retrieving and preprocessing the weather forecast for the upcoming hours/days from openweathermap

Other examples of useful information could be financial data such as

  • exchange rates of different currencies or
  • stock market information.

Interesting could also be the information which dustbin should be standing outside next for garbage disposal in the morning.
Perhaps flight information for frequent flyers, train times (and delays) for rail travellers, even momentary fuel prices in the region (if only they were not changing so quickly as in Germany) is helpul.

For sure there are more ideas which data could be retrieved and prepared by a server for display! But back to the server itself.

HTTP Server Construction

An HTTP server in Java is basically a runnable jar file that is launched on a machine within a (local) network. The required libraries include http, httpclient, httpcore, … .

Functionality

When a GET request is received from a client the appropriate routine is launched. For each ‚digestible‘ URL a different Java class handles the request.
In case of fetching the next x entries from a Google calendar the specific Java class handles the authentication, the retrieval and the processing of the calendar entries into the JSON format. In Java this is more simple and faster than computing directly on an Arduino.

The entry point of the server may be constructed like this:

import com.sun.net.httpserver.HttpServer;
...
public static void main(String[] args) {
	try {
	    HttpServer server = HttpServer.create(new InetSocketAddress(12345), 0);
	    server.createContext("/calendar", new RequestCalendarHandler());
	    server.createContext("/weather", new RequestOWMWeatherHandler());
	    server.createContext("/forecast", new RequestOWMWeatherForecastHandler());
	    server.setExecutor(null); // creates a default executor
	    server.start();
	    System.out.println("Server running on host " + server.getAddress().getHostString());
	} catch (IOException e) {
	    System.err.println(e.getMessage());
	}
}

Openweathermap

For weather data/weather forecast retrieval from openweathermap it is not necessary to reimplement the wheel. An excellent Java library already exists: owm-japis. It can be used in a different Java class to process appropriate HTTP GET requests.

The handler for fetching weather data by openweathermap may look similar to this:

import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import net.aksingh.owmjapis.CurrentWeather;
import net.aksingh.owmjapis.OpenWeatherMap;
import net.aksingh.owmjapis.OpenWeatherMap.Units;
...
static class RequestOWMWeatherHandler implements HttpHandler {
	@Override
	public void handle(HttpExchange http) throws IOException {
		System.out.println("URI received: " + http.getRequestURI().toString());

	String[] request = http.getRequestURI().toString().split("/");
	if( request.length>1 ) {
		// Handle read requests
		if( request[1].equals("weather") ) {
		try{
			OpenWeatherMap owm = new OpenWeatherMap("APIKEY");
			owm.setUnits(Units.METRIC);

			// getting current weather data for the location
			CurrentWeather cwd = owm.currentWeatherByCityCode(CITYCODE_OWM);

			// checking data retrieval was successful or not
			if (cwd.isValid()) {
				DateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
				Date now = cwd.getDateTime();
				String dateNow = dateFormatter.format(now);
				DateFormat timeFormatter = new SimpleDateFormat("HH:mm");
				String timeNow = timeFormatter.format(now);

				System.out.println(cwd.getRawResponse());
				System.out.println("Post weather result in JSON format (raw)");
				// wrap parcels of byte size 4096
				int BUFFER_SIZE = 4096;
				http.sendResponseHeaders(200, 0);
				try (BufferedOutputStream out = new BufferedOutputStream(http.getResponseBody())) {
					try (ByteArrayInputStream bis = new ByteArrayInputStream(response.getBytes())) {
						byte [] buffer = new byte [BUFFER_SIZE];
						int count ;
						while ((count = bis.read(buffer)) != -1) {
							out.write(buffer, 0, count);
						}
					}
				}
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}
}

Client to Server

A client requests data from the HTTP server by a GET request. An example URL to fetch the weather data looks like this:
http://localhost:12345/weather
Such an URL consisting of hostname:port can be tested in a browser on the machine where the server is running. Otherwise an IP or hostname must replace localhost.

Server to Clients

As soon as the HTTP server received a request it analyses the URL and launches the appropriate handler. In the example above the weather data will be retrieved from openweathermap (API key and location ID required).

How to read from a google calendar in Java is explained on google’s developer pages. Authentication for the desired calendar must be set up in advance following the manual.

The results can be preprocessed into a desired format to be posted for the client.
A common format is the JSON format. Data in this format can be read and processed further by a client.

Example Client: Arduino / ESP8266

The client I use is an Adafruit Huzzah microcontroller with an ESP8266 WiFi chip.
(Just in case: the hardware setup, the pin changes in the epd library and the code to parse weather data are described in previous blog posts) .
The source code in this blog post illustrates how to act as an HTTP client. To decode a reply in JSON format the library ArduinoJson is used.
Any display can be attached to the microcontroller to show the results from the HTTP GET request to the HTTP server. At the moment I strongly prefer an e-Ink display. 😉

calendar_currentweather

Links

https://developers.google.com/google-apps/calendar/quickstart/java

http://openweathermap.org/api

https://bitbucket.org/akapribot/owm-japis/overview

https://github.com/bblanchon/ArduinoJson

http://www.waveshare.com/4.3inch-e-paper.htm

http://www.waveshare.com/wiki/4.3inch_e-Paper

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s