Standalone RESTful Server und Client mit dem Restlet Framework

Manchmal braucht man in Java einen REST Server oder Client oder beides. Das ist mit dem Restlet Framework schnell implementiert.

Standalone RESTful Server und Client mit dem Restlet Framework

Es kann entweder das ganze Beispielprojekt von Github geladen werden oder diese Schritte ausgeführt werden:

Zuerst richten wir in Eclipse ein neues Maven Projekt ein und fügen der pom.xml diese Einträge hinzu:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>de.wenzlaff.umgebung</groupId>
	<artifactId>de.wenzlaff.umgebung</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>RestUmgebung</name>
	<url>http://www.wenzlaff.info</url>

	<repositories>
		<repository>
			<id>maven-restlet</id>
			<name>Public online Restlet repository</name>
			<url>http://maven.restlet.org</url>
		</repository>
	</repositories>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<restlet-version>2.3.10</restlet-version>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.6.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<!-- Java Standalone -->
		<dependency>		
			<groupId>org.restlet.jse</groupId>
			<artifactId>org.restlet</artifactId>
			<version>${restlet-version}</version>
		</dependency>
		<dependency>
			<groupId>org.restlet.jse</groupId>
			<artifactId>org.restlet.ext.simple</artifactId>
			<version>${restlet-version}</version>
		</dependency>
		<!-- Java Jackson unterstüzung um Objekte zu serialisieren -->
		<dependency>
			<groupId>org.restlet.jee</groupId>
			<artifactId>org.restlet.ext.jackson</artifactId>
			<version>${restlet-version}</version>
		</dependency>
		<!-- Testframework JUnit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

Den Standalone Server machen wir mit zwei Klassen:

package de.wenzlaff.umgebung;

import org.restlet.Component;
import org.restlet.data.Protocol;

/**
 * Ein Beispiel Standalone Server.
 * 
 * @author Thomas Wenzlaff
 *
 */
public class StandaloneServer {

	public static final Integer PORT = 6969;

	public static final String HOST = "http://localhost:" + PORT;

	public static void main(String[] args) throws Exception {

		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					StandaloneServer.start();
				} catch (Exception e) {
					System.err.println(e.getMessage());
				}
			}
		});
		t.start();
	}

	/**
	 * Der Server mit der Hauptanwendung.
	 * 
	 * Aufruf über
	 * 
	 * http://localhost:9696/umgebung/
	 * 
	 * http://localhost:9696/umgebung/service
	 * 
	 * http://localhost:9696/umgebung/version
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void start() throws Exception {
		Component component = new Component();
		component.getServers().add(Protocol.HTTP, PORT);

		component.getDefaultHost().attach("/umgebung", new UmgebungsZiele());

		component.start();
	}
}

Und noch eine Klasse von Application erben und die Routen bzw. die URLs angeben:

package de.wenzlaff.umgebung;

import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;

import de.wenzlaff.umgebung.resource.InfoResource;
import de.wenzlaff.umgebung.resource.MindmapResource;
import de.wenzlaff.umgebung.resource.UmgebungResource;
import de.wenzlaff.umgebung.resource.VersionResource;

/**
 * Bearbeitet alle Aufrufe für den Server.
 * 
 * @author Thomas Wenzlaff
 *
 */
public class UmgebungsZiele extends Application {

	/**
	 * Erzeugt den root Restlet der alle eingehende Aufrufe bearbeitet.
	 * 
	 * http://localhost:9696/umgebung/
	 * 
	 * http://localhost:9696/umgebung/service
	 * 
	 * http://localhost:9696/umgebung/version
	 * 
	 */
	@Override
	public synchronized Restlet createInboundRoot() {

		Router router = new Router(getContext());

		router.attach("/", InfoResource.class);
		router.attach("/service", UmgebungResource.class);
		router.attach("/version", VersionResource.class);
		router.attach("/mindmap", MindmapResource.class);

		return router;
	}

}

Dann noch eine UmgebungResource anlegen, die von ServerResource erbt.

package de.wenzlaff.umgebung.resource;

import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;

/**
 * Liefert die Systemumgebung.
 * 
 * @author Thomas Wenzlaff
 *
 */
public class UmgebungResource extends ServerResource implements Umgebung {

	@Override
	@Get
	public String getUmgebung() {
		return "Umgebung:\n" + System.getProperties().toString().replaceAll(",", "\n");
	}

}

Dafür auch gleich noch ein Interface mit Klassennamen Umgebung und der Annotation @get anlegen:

package de.wenzlaff.umgebung.resource;

import org.restlet.resource.Get;

/**
 * Interface für die Umgebung.
 * 
 * @author Thomas Wenzlaff
 *
 */
public interface Umgebung {

	@Get
	String getUmgebung();

}

Das ist schon alles für den Server. Wir wollen das aber ja nicht nur über den Browser testen. Deshalb einen Client in einer JUnit Testklasse verpackt:

package de.wenzlaff.umgebung;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.BeforeClass;
import org.junit.Test;
import org.restlet.resource.ClientResource;

import de.wenzlaff.umgebung.resource.Mindmap;
import de.wenzlaff.umgebung.resource.MindmapModell;
import de.wenzlaff.umgebung.resource.Umgebung;
import de.wenzlaff.umgebung.resource.Version;

/**
 * Testklasse für den Server.
 * 
 * @author Thomas Wenzlaff
 *
 */
public class ServerAppTest {

	@BeforeClass
	public static void startServer() throws Exception {
		StandaloneServer.start();
	}

	@Test
	public void testGetUmgebungVersion() throws Exception {

		String hostUrl = StandaloneServer.HOST + "/umgebung/version";
		System.out.println("Anfrage von: " + hostUrl);

		ClientResource clientResource = new ClientResource(hostUrl);

		Version resource = clientResource.wrap(Version.class);

		String vers = resource.getVersion();

		System.out.println(vers);

		assertEquals("0.0.1", vers);
	}

	@Test
	public void testGetUmgebungService() throws Exception {

		String hostUrl = StandaloneServer.HOST + "/umgebung/service";
		System.out.println("Anfrage von: " + hostUrl);

		ClientResource clientResource = new ClientResource(hostUrl);

		Umgebung resource = clientResource.wrap(Umgebung.class);

		String vers = resource.getUmgebung();

		System.out.println(vers);
		assertTrue(vers.length() > 10);
	}

	/**
	 * Benötigt org.restlet.ext.jackson in der pom.xml
	 * 
	 * @throws Exception
	 */
	@Test
	public void testGetUmgebungMindmap() throws Exception {

		String hostUrl = StandaloneServer.HOST + "/umgebung/mindmap";
		System.out.println("Anfrage von: " + hostUrl);

		ClientResource clientResource = new ClientResource(hostUrl);

		Mindmap resource = clientResource.wrap(Mindmap.class);

		MindmapModell m = resource.getMindmap();

		if (m == null) {
			System.err.println("Es fehlt evl. die org.restlet.ext.jackson unterstüzung in der pom.xml");
			return;
		}

		assertEquals("0.0.1", m.getVersion());

		System.out.println("Mindmap Version: " + m.getVersion());
		System.out.println("Mindmap Name: " + m.getName());
		System.out.println("Erstellungs Datum: " + m.getErstellungsDatum());
		System.out.println(m);

	}

}

Ist die Beschreibung ausführlich genug? Weitere Details siehe auch im Beispielprojekt auf Github.

Ähnliche Artikel:

  1. Java Rätsel des Monats
  2. Besser als Fussball: MQTT Java Client mit Paho
  3. Generische Methoden

wallpaper-1019588
5 Dinge, die du als Trailrunning-Anfänger wissen solltest
wallpaper-1019588
Kalorienarme Lebensmittel: Top-Auswahl für Ihre Diät
wallpaper-1019588
Kalorienarme Lebensmittel: Top-Auswahl für Ihre Diät
wallpaper-1019588
#1492 [Review] Manga ~ Dein Verlangen gehört mir