Angewandte Netzwerktechnik kompakt

Material zum Buch

zu Kapitel 9.3 (SOAP Service)


Zu diesem Kapitel gibt es folgende Projekte:

zu Kapitel 9.5.1 (RESTful Service Server)


Auch in diesem Kapitel gibt es mehrere Projekte:

Zur Verwendung der Server Klassen wird eine Bibliothek Jersey benötigt, welche unter https://jersey.github.io/ abrufbar ist. Alle benötigten Verweise sind bereits in der Klasse vorhanden. Abbildung 9.5 im Buch zeigt, wie die Bibliothek zu einem Eclipse-Projekt hinzugefügt werden kann.

zu Kapitel 9.5.2.1 (REST Aufruf über HTML)


In den Formularen wird gezeigt wie ein REST Webservice über HTML Formular aus dem Browser aufgerufen werden kann.




zu Kapitel 9.5.2.2 und 9.5.3 (RESTful Service Clients)


Auch in diesem Kapitel gibt es mehrere Projekte:

Die passenden Server Klassen stehen in Kapitel 9.5.1.

zu Kapitel 9.6 (Eigenbau)


Für Kapitel 9.5 stehen uns die Klassen TCPClient, Leistung, Befehl für den Client und TCPServer, Befehl, ClientHandler, Leistung, Speicher, Student für den Server zur Verfügung.

Client und Server kommunizieren über ein selbst definiertes TCP/IP-Protokoll. Dieses verwendet keinen DataOutputStream sondern eine textuelle Codierung als UTF-8 String, um plattformunabhängig zu sein.

zu Kapitel 9.7 (Gegenüberstellung)


Im diesem ZIP-Archiv befinden sich die Wireshark-Aufzeichnungen zu Kapitel 9.6 mit der Kommunikation zwischen Client und Server für SOAP, REST und Eigenbau Webservice.

SOAP, RESTful, Eigenbau Webservices


Die folgende Seite dient zur Beobachtung und Verfolgung der Webservices.

Vorschau der Java-Klassen zu Kapitel 9.3


SoapClient.java

package soapClient;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

// Eigener Server
import soapServer.Leistung;
import soapServer.VerwaltungInterface;

// Server von Webseite
//import soap.Leistung;
//import soap.VerwaltungInterface;

public class SoapClient 
{
	public static void main(String[] args) throws Throwable 
	{
		// URL des Servers
		// Eigener Server
		String url ="http://localhost:4434/verwaltung";
		// Server von Webseite
		// String url = "http://angewnwt-neu.hof-university.de:4437/verwaltung";
		// Name des Studenten, fuer den wir anfragen
		String name = "Hannah Becker";

		// Verbindung zum Server aufbauen
		Service service = Service.create(
				new URL(url + "?wsdl"), 
				new QName("http://soapServer/", "VerwaltungImplService"));

		// Stub-Methoden bereitstellen
		VerwaltungInterface verwaltung = service.getPort(VerwaltungInterface.class);

		// Server abfragen: 1) Matrikelnummer zu Name
		int matrikelNummer = verwaltung.martikelnummerZuName(name);
		System.out.println("\nMartikelNummer: " + matrikelNummer);

		if (matrikelNummer != -1) 
		{
			// Server abfragen: 2) leistungen zur Matrikelnummer
			Leistung[] leistungen = verwaltung.studienleistungZuMartikelnummer(matrikelNummer);

			if (leistungen != null) 
			{
				System.out.println(leistungen); 
				
				for (Leistung leistung : leistungen) 
				{
					System.out.println("\nLeistung: " + leistung.getModul() + " - " + leistung.getNote());
				}
			}
		}
	}
}

soapClientExceptionReturnValue.java

package soapClient;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;

import soapServer.Leistung;
import soapServer.VerwaltungInterface;

public class soapClientExceptionReturnValue
{
	public static void main(String[] args) throws MalformedURLException, InterruptedException 
	{
		// URL des Servers
		String url ="http://localhost:4434/verwaltung";
		// Name des Studenten, fuer den wir anfragen
		String name = "Mia Bauer";

		VerwaltungInterface verwaltung = null;

		//FALL 1: Fehler beim Verbindungsaufbau
		boolean serviceErzeugt = false;
		while(!serviceErzeugt) {
			try {
				// Verbindung zum Server aufbauen
				Service service = Service.create(
						new URL(url + "?wsdl"),
						new QName("http://soapServer/", "VerwaltungImplService"));

				// Stub-Methoden bereitstellen
				verwaltung = service.getPort(VerwaltungInterface.class);
				serviceErzeugt=true;
			} catch (WebServiceException e) {
				System.err.println("Server nicht erreichbar! Aufbau der Verbindung wird erneut versucht");
				System.err.println(e);
				Thread.sleep(10000); // vor dem naechsten Versuch kurz warten 
			}
		}

		//FALL 2: Fehler waehrend Anfrage
		if (verwaltung != null) {
			int matrikelNummer = -1;
			boolean anfrageOK;

			anfrageOK = false;
			while(!anfrageOK) {
				try {
					// Server abfragen: 1) Matrikelnummer zu Name
					matrikelNummer = verwaltung.martikelnummerZuName(name);
					System.out.println("\nMartikelNummer: " + matrikelNummer);
					anfrageOK=true;

					if(matrikelNummer != -1) {
						Leistung[] leistungen = null;
						anfrageOK = false;
						// Server abfragen: 2) leistungen zur Matrikelnummer
						leistungen = verwaltung.studienleistungZuMartikelnummer(matrikelNummer);
						anfrageOK=true;

						if (leistungen != null) {
							for (Leistung leistung : leistungen) {
								System.out.println("\nLeistung: " + leistung.getModul() + " - " + leistung.getNote());
							}
						}
					}
				} 
				catch (WebServiceException e) {
					System.err.println("Server nicht erreichbar! Aufbau der Verbindung wird erneut versucht");
					System.err.println(e);
					Thread.sleep(10000); // vor dem naechsten Versuch kurz warten 
				}
			}
		}
	}
}

soapClientException.java

package soapClientException;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.http.HTTPException;
import javax.xml.ws.soap.SOAPFaultException;

import soapServer.Leistung;
import soapServerException.VerwaltungInterfaceException;

public class soapClientException 
{
	public static void main(String[] args) throws Exception
	{
		// URL des Servers
		String url ="http://localhost:4434/verwaltung";
		// Name des Studenten, fuer den wir anfragen
		String name = "Hannah BeckerA";

		VerwaltungInterfaceException verwaltung = null;

		//FALL 1: Fehler beim Verbindungsaufbau
		boolean serviceErzeugt = false;
		while(!serviceErzeugt) {
			try {
				// Verbindung zum Server aufbauen
				Service service = Service.create(
						new URL(url + "?wsdl"),
						new QName("http://soapServerException/", "VerwaltungImplExceptionService"));

				// Stub-Methoden bereitstellen
				verwaltung = service.getPort(VerwaltungInterfaceException.class);
				serviceErzeugt=true;
			} catch (WebServiceException e) {
				System.err.println("Server nicht erreichbar! Aufbau der Verbindung wird erneut versucht");
				System.err.println(e);
				Thread.sleep(10000); // vor dem naechsten Versuch kurz warten 
			}
		}

		//FALL 2: Fehler waehrend Anfrage
		if (verwaltung != null) {
			int matrikelNummer = -1;
			Leistung[] leistungen = null;
			boolean anfrageOK;

			// Server abfragen: 1) Matrikelnummer zu Name
			anfrageOK = false;
			while(!anfrageOK) {
				try {
					matrikelNummer = verwaltung.martikelnummerZuName(name);
					anfrageOK=true;
					System.out.println("\nMartikelNummer: " + matrikelNummer);

					// Server abfragen: 2) Leistungen zur Matrikelnummer
					anfrageOK = false;
					leistungen = verwaltung.studienleistungZuMartikelnummer(matrikelNummer);
					anfrageOK=true;
					for (Leistung leistung : leistungen) {
						System.out.println("\nLeistung: " + leistung.getModul() + " - " + leistung.getNote());
					} 
				}
				catch (SOAPFaultException e) 
				{
					System.err.println("Anfrage gescheitert!");
					System.err.println(e);
					// Methode mit applikationsspezifischer, eigener Exception beenden
					throw new Exception("Anfrage gescheitert");
				}
				catch (HTTPException e) {
					System.err.println("Server nicht erreichbar! Anfrage wird erneut versendet");
					System.err.println(e);
					Thread.sleep(10000); // vor dem naechsten Versuch kurz warten 
				}
			}
		}
	}
}


Leistung.java

package soapServer;

public class Leistung {
	String modul;
	public String getModul() {
		return modul;
	}

	public void setModul(String modul) {
		this.modul = modul;
	}

	public double getNote() {
		return note;
	}

	public void setNote(double note) {
		this.note = note;
	}

	double note;
	
	Leistung()
	{		
		modul = "nicht initialisiert";
		note  = 6.0;
	}
}

SoapServer.java

package soapServer;

import javax.xml.ws.Endpoint;

public class SoapServer 
{
	public static void main(String[] args) 
	{
		// SOAP Service erstellen
		String url = "http://localhost:4434/verwaltung";
	    Endpoint.publish( url, new VerwaltungImpl() );
	    System.out.println("SOAP-Server gestartet: "+url);
	}
}

Speicher.java

package soapServer;

public class Speicher {
	// Array, das die Studenten speichert
	// Kniff: Der Inhalt des Speichers existiert nur einmal, da static
	private static final Student[] studenten;

	// Kniff: Der Inhalt des Speichers wird durch diese Methode beim ersten Zugriff erzeugt
	static
	{
		// Datensaetze erzeugen
		studenten = Speicher.fuelleMitUnsinn(100);
	}

	// Methoden fuer den Zugriff auf die gespeicherten Daten
	public static Student[] getStudenten()
	{
		return studenten;
	}

	public static Student getSucheMatrikelNummerZuName(String name)
	{
		for(Student s : studenten)
		{
			if(s.name.equals(name))
			{
				return s;
			}
		}
		return null;
	}

	public static Student getStudentenInfoZuMatrikelNummer(int matrikelNummer)
	{
		for(Student s : studenten)
		{
			if(s.matrikelNummer == matrikelNummer)
			{
				return s;
			}
		}	
		return null;
	}	

	// Utility-Methoden
	public static Student[] fuelleMitUnsinn(int Zahl)
	{
		// Hilfsvariablen zum Erzeugen von Datensaetzen
		  final String [] vornamen = { "Mia","Ben","Emma","Jonas","Hannah","Leon","Sofia","Finn","Anna","Elias"};
		  final String [] nachnamen = {"Bauer","Becker","Fischer","Fuchs","Hartmann","Lang", "Jung","Hofmann","Huber"};
		  final String [] module = {"Analysis A","Lineare Algebra A","Analysis B","Lineare Algebra B","Numerik A",
				"Stochastik A","Stochastik B","Numerik partieller Differentialgleichungen 1","Numerik partieller Differentialgleichungen 2",
				"Baumechanik I (Statik starrer Koerper)","Baumechanik II (Elastomechanik)","Baumechanik III (Kinematik und Kinetik)",
				"Kontinuumsmechanik I","Modellbildung im Ingenieurwesen","Numerische Mechanik","Festkoerpermechanik","Finite Elemente II",
				"Grundlagen der Elektrotechnik","Umweltbiologie und -chemie","Stroemungsmechanik","Thermodynamik im Ueberblick",
				"Datenstrukturen, Algorithmen und Programmierung","Datenbanksysteme im Ingenieurwesen","Graphen und Netze","Baustoffkunde I",
				"Baustoffkunde II","Ausgleichungsrechnung und Statistik I","Ausgleichungsrechnung und Statistik II",
		"Projekte des Ingenieurwesens" };

		Student[] unsinn = new Student[Zahl];

		for(int i=0; i < Zahl; i++) {
			unsinn[i]=new Student();
			int vn_indx = (int)(Math.random()*vornamen.length);
			int nn_indx = (int)(Math.random()*nachnamen.length);
			unsinn[i].name = vornamen[vn_indx] + " " + nachnamen[nn_indx];
			unsinn[i].matrikelNummer = vn_indx * 100 + nn_indx;
			int notenZahl = (int)(Math.random()*8);
			if(notenZahl >= 1) {
				unsinn[i].leistungen = new Leistung[notenZahl];
				for(int j=0; j < notenZahl; j++) {
					int mod_indx = (int)(Math.random()*module.length);
					unsinn[i].leistungen[j] = new Leistung();
					unsinn[i].leistungen[j].modul = module[mod_indx];
					unsinn[i].leistungen[j].note = (int)(Math.random()*5) + 1;
				}
			}
			else
				unsinn[i].leistungen = null;
		}
		return unsinn;
	}

	public static boolean sindArraysGleich(Student[] a, Student[] b) {
		boolean istUnGleich = false;
		if(a.length == b.length)
		{
			for(int i=0; i < a.length; i++) {
				istUnGleich |= a[i].matrikelNummer != b[i].matrikelNummer;
				istUnGleich |= !(a[i].name.equals(b[i].name));
				if(a[i].leistungen != null) {
					for(int j=0; j < a[i].leistungen.length; j++) {
						istUnGleich |= !(a[i].leistungen[j].modul.equals(b[i].leistungen[j].modul)) ;
						istUnGleich |= a[i].leistungen[j].note != b[i].leistungen[j].note ;
					}
				}
				if(istUnGleich)
					System.out.println("Ungleich "+ a[i].name);
			}
		}
		else
			istUnGleich = true;

		return !istUnGleich;
	}
}

Student.java

package soapServer;

public class Student {
	public int matrikelNummer;
	public String name;
	public Leistung[] leistungen;

	public int getMatrikelNummer() {
		return matrikelNummer;
	}
	public void setMatrikelNummer(int matrikelNummer) {
		this.matrikelNummer = matrikelNummer;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public Leistung[] getLeistungen() {
		return leistungen;
	}
	public void setLeistungen(Leistung[] leistungen) {
		this.leistungen = leistungen;
	}
}

VerwaltungImpl.java

package soapServer;

import javax.jws.WebService;

@WebService( endpointInterface="soapServer.VerwaltungInterface" )
public class VerwaltungImpl implements VerwaltungInterface 
{
	@Override
	public int martikelnummerZuName(String name) 
	{
		System.out.print("matrikelNummerZuName: "+ name);
		Student s = Speicher.getSucheMatrikelNummerZuName(name);
		
		if(s != null)
		{
			System.out.println(" "+ s.matrikelNummer);
			return s.matrikelNummer;
		}
		
		System.out.println(" nicht gefunden");
		return -1;
	}

	@Override
	public Leistung[] studienleistungZuMartikelnummer(int matrikelNummer) 
	{
		System.out.print("StudienleistungZuMartikelnummer: "+ matrikelNummer);
		
		Student s = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		
		if(s != null)
		{
			System.out.println(" "+ s.name + " mit " + s.leistungen.length + " Leistungen");
			return s.leistungen;
		}
		
		System.out.println(" nicht gefunden");
		return null;
	}
}

VerwaltungInterface.java

package soapServer;

import javax.jws.*;

@WebService
public interface VerwaltungInterface 
{
	public int martikelnummerZuName( @WebParam( name = "name" ) String name );
	
	public Leistung[] studienleistungZuMartikelnummer( @WebParam( name = "matrikelNummer" ) int matrikelNummer );
}

NichtGefundenException.java

package soapServerException;

import javax.xml.ws.WebServiceException;

public class NichtGefundenException extends WebServiceException {
	private static final long serialVersionUID = 1L;
	String fehlerMeldung;
	int fehlerCode;
	
	NichtGefundenException(String fehlerMeldung, int fehlerCode) {
		this.fehlerMeldung = fehlerMeldung;
		this.fehlerCode = fehlerCode;
	}
	
	@Override
	public String toString() {
		return "NichtGefunden: " + fehlerMeldung + " (" + fehlerCode + ")";
	}
}

SoapServerException.java

package soapServerException;

import javax.xml.ws.Endpoint;

public class SoapServerException 
{
	public static void main(String[] args) 
	{
		// SOAP Service erstellen
		String url = "http://localhost:4434/verwaltung";
	    Endpoint.publish( url, new VerwaltungImplException() );
	    System.out.println("SOAP-Server gestartet: "+url);
	}
}

VerwaltungImplException.java

package soapServerException;

import javax.jws.WebService;

import soapServer.Leistung;
import soapServer.Speicher;
import soapServer.Student;

@WebService( endpointInterface="soapServerException.VerwaltungInterfaceException" )
public class VerwaltungImplException implements VerwaltungInterfaceException
{
	@Override
	public int martikelnummerZuName(String name) throws NichtGefundenException 
	{
		System.out.print("matrikelNummerZuName: "+ name);
		Student s = Speicher.getSucheMatrikelNummerZuName(name);
		
		if(s != null)
		{
			System.out.println(" "+ s.matrikelNummer);
			return s.matrikelNummer;
		}
		System.out.println(" nicht gefunden");
		throw new NichtGefundenException("unbekannter Name", 1);
	}

	@Override
	public Leistung[] studienleistungZuMartikelnummer(int matrikelNummer) throws NichtGefundenException 
	{
		System.out.print("StudienleistungZuMartikelnummer: "+ matrikelNummer);
		
		Student s = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		
		if(s != null)
		{
			System.out.println(" "+ s.name + " mit " + s.leistungen.length + " Leistungen");
			return s.leistungen;
		}
			System.out.println(" nicht gefunden");
		throw new NichtGefundenException("ungueltige Matrikelnummer",2);
	}
}

VerwaltungInterfaceException.java

package soapServerException;

import javax.jws.*;

import soapServer.Leistung;

@WebService
public interface VerwaltungInterfaceException 
{
	public int martikelnummerZuName( @WebParam( name = "name" ) String name ) throws NichtGefundenException ;
	
	public Leistung[] studienleistungZuMartikelnummer( @WebParam( name = "matrikelNummer" ) int matrikelNummer ) throws NichtGefundenException ;
}

Vorschau der Java-Klassen zu Kapitel 9.5.1


Leistung.java

package restServer;


public class Leistung {
	String modul;
	double note;
}

RestServer.java

package restServer;

import java.io.IOException;
import java.net.URI;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

public class RestServer
{
	/*
	 * JAX-RS ist in Java SE (Standard  Edition) NICHT enthalten, sondern nur in Java EE (Enterprise Edition).
	 * Als Referenzimplementierung wird hier Jersey eingesetzt.
	 * 
	 * Zusaetzlich wird ein einfacher Webserver benoetigt (in diesen Beispiel: Grizzly)
	 * 
	 * URLs zu den Biblioteken:
	 * - https://jersey.github.io/
	 * - https://javaee.github.io/grizzly/
	 */

	public static void main(String[] args) throws IOException, InterruptedException 
	{
		String baseUrl = "http://localhost:4434";

		// Webserver erzeugen und mit unserem Service verbinden
		final HttpServer webServer = GrizzlyHttpServerFactory.createHttpServer(URI.create(baseUrl),
				new ResourceConfig(VerwaltungService.class), false);

		// Methode zum Beenden des Webservers beim Beenden des Java-Programms bei der Java-Runtime registrieren 
		Runtime.getRuntime().addShutdownHook(
				new Thread(new Runnable() {
					@Override
					public void run() {
						webServer.shutdownNow();
					}
				}));

		// Webserver starten
		webServer.start();

		System.out.println(String.format(
				"\nGrizzly-HTTP-Server gestartet mit der URL: %s\n"
						+ "Stoppen des Grizzly-HTTP-Servers mit:      Strg+C\n",
						baseUrl + VerwaltungService.webContextPath));

		// Warten bis das Java-Programm beendet wird (durch Ctrl-C)
		Thread.currentThread().join();
	}
}

Speicher.java

package restServer;

public class Speicher {
	// Array, das die Studenten speichert
	// Kniff: Der Inhalt des Speichers existiert nur einmal, da static
	private static final Student[] studenten;

	// Kniff: Der Inhalt des Speichers wird durch diese Methode beim ersten Zugriff erzeugt
	static
	{
		// Datensaetze erzeugen
		studenten = Speicher.fuelleMitUnsinn(100);
	}

	// Methoden fuer den Zugriff auf die gespeicherten Daten
	public static Student[] getStudenten()
	{
		return studenten;
	}

	public static Student getSucheMatrikelNummerZuName(String name)
	{
		for(Student s : studenten)
		{
			if(s.name.equals(name))
			{
				return s;
			}
		}
		return null;
	}

	public static Student getStudentenInfoZuMatrikelNummer(int matrikelNummer)
	{
		for(Student s : studenten)
		{
			if(s.matrikelNummer == matrikelNummer)
			{
				return s;
			}
		}	
		return null;
	}	

	// Utility-Methoden
	public static Student[] fuelleMitUnsinn(int Zahl)
	{
		// Hilfsvariablen zum Erzeugen von Datensaetzen
		  final String [] vornamen = { "Mia","Ben","Emma","Jonas","Hannah","Leon","Sofia","Finn","Anna","Elias"};
		  final String [] nachnamen = {"Bauer","Becker","Fischer","Fuchs","Hartmann","Lang", "Jung","Hofmann","Huber"};
		  final String [] module = {"Analysis A","Lineare Algebra A","Analysis B","Lineare Algebra B","Numerik A",
				"Stochastik A","Stochastik B","Numerik partieller Differentialgleichungen 1","Numerik partieller Differentialgleichungen 2",
				"Baumechanik I (Statik starrer Koerper)","Baumechanik II (Elastomechanik)","Baumechanik III (Kinematik und Kinetik)",
				"Kontinuumsmechanik I","Modellbildung im Ingenieurwesen","Numerische Mechanik","Festkoerpermechanik","Finite Elemente II",
				"Grundlagen der Elektrotechnik","Umweltbiologie und -chemie","Stroemungsmechanik","Thermodynamik im Ueberblick",
				"Datenstrukturen, Algorithmen und Programmierung","Datenbanksysteme im Ingenieurwesen","Graphen und Netze","Baustoffkunde I",
				"Baustoffkunde II","Ausgleichungsrechnung und Statistik I","Ausgleichungsrechnung und Statistik II",
		"Projekte des Ingenieurwesens" };

		Student[] unsinn = new Student[Zahl];

		for(int i=0; i < Zahl; i++) {
			unsinn[i]=new Student();
			int vn_indx = (int)(Math.random()*vornamen.length);
			int nn_indx = (int)(Math.random()*nachnamen.length);
			unsinn[i].name = vornamen[vn_indx] + " " + nachnamen[nn_indx];
			unsinn[i].matrikelNummer = vn_indx * 100 + nn_indx + i * 10000;
			int notenZahl = (int)(Math.random()*8);
			if(notenZahl >= 1) {
				unsinn[i].leistungen = new Leistung[notenZahl];
				for(int j=0; j < notenZahl; j++) {
					int mod_indx = (int)(Math.random()*module.length);
					unsinn[i].leistungen[j] = new Leistung();
					unsinn[i].leistungen[j].modul = module[mod_indx];
					unsinn[i].leistungen[j].note = (int)(Math.random()*5) + 1;
				}
			}
			else
				unsinn[i].leistungen = null;
		}
		return unsinn;
	}

	public static boolean sindArraysGleich(Student[] a, Student[] b) {
		boolean istUnGleich = false;
		if(a.length == b.length)
		{
			for(int i=0; i < a.length; i++) {
				istUnGleich |= a[i].matrikelNummer != b[i].matrikelNummer;
				istUnGleich |= !(a[i].name.equals(b[i].name));
				if(a[i].leistungen != null) {
					for(int j=0; j < a[i].leistungen.length; j++) {
						istUnGleich |= !(a[i].leistungen[j].modul.equals(b[i].leistungen[j].modul)) ;
						istUnGleich |= a[i].leistungen[j].note != b[i].leistungen[j].note ;
					}
				}
				if(istUnGleich)
					System.out.println("Ungleich a="+ a + "| b=" + b);
			}
		}
		else
			istUnGleich = true;

		return !istUnGleich;
	}
}

Student.java

package restServer;


public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

VerwaltungService.java

package restServer;
import javax.ws.rs.*;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

@Path(VerwaltungService.webContextPath)
public class VerwaltungService 
{
	static final String webContextPath = "/student";
		
	// Funktion fuer Pfad 1 der Server-Sitemap: Namen und Matrikelnummern aller Studenten
	public String getListeVonStudenten() 
	{
		String ergebnisAlsJSON;
		
		System.out.println("getListeVonStudenten");

		// GSON fuer Umwandlung in JSON
		Gson gson = new GsonBuilder().create();
		
		// Wir wollen nur einen Teil transportieren, deswegen muss Liste ueberarbeitet werden
		JsonArray nurMatrikelnummerUndName = new JsonArray();
	
		for(Student s : Speicher.getStudenten())
		{
			JsonObject dataset = new JsonObject();
			dataset.addProperty("matrikelNummer", s.matrikelNummer);
			dataset.addProperty("name", s.name);
	 		nurMatrikelnummerUndName.add(dataset);
		}
		ergebnisAlsJSON = gson.toJson(nurMatrikelnummerUndName);
		return ergebnisAlsJSON;
	}
	
	// Funktion fuer Pfad 2 der Server-Sitemap: Matrikelnummer zum Namen
	public String getSucheMatrikelNummerZuName(String name) 
	{
		Student myStudent = null;
		JsonObject matrikelnummer = null;
		String ergebnisAlsJSON;

		Gson gson = new GsonBuilder().create();
				
		System.out.print("getSucheMatrikelNummerZuName: "+ name);
	
		myStudent = Speicher.getSucheMatrikelNummerZuName(name);
		if(myStudent != null)
		{
			 matrikelnummer = new JsonObject();
			 matrikelnummer.addProperty("matrikelNummer", myStudent.matrikelNummer);
		}
		System.out.println(" "+ matrikelnummer);
		ergebnisAlsJSON = gson.toJson(matrikelnummer);
		return ergebnisAlsJSON;
	}
	
	// Pfad 1 und Pfad 2 der Server-Sitemap fuehren auf diese Methode
	// diese verzweigt je nach Aufruf mit oder ohne Query-Parameter 
	@GET
	@Path("/")
	@Produces(MediaType.APPLICATION_JSON) 
	public String getListeOderSuche(@QueryParam("name") String name) {
		System.out.print("getListeOderSuche: "+ name + " ");
		
		if(name == null)
			// Pfad 1: kein Parameter: gesamte Liste
			return getListeVonStudenten();
		else
			// Pfad 2: mit Parameter: nur ein Eintrag
			return getSucheMatrikelNummerZuName(name);
	}

	// Funktion fuer Pfad 3 der Server-Sitemap: Name zu einer Matrikelnummer
	@GET
	@Path("/{matrikelNummer}")
	@Produces(MediaType.APPLICATION_JSON)
	public String getStudentenInfoZuMatrikelNummer(@PathParam("matrikelNummer") int matrikelNummer) 
	{
		Student myStudent = null;
		String ergebnisAlsJSON = "null";

		Gson gson = new GsonBuilder().create();
	
		System.out.print("getStudentenInfoZuMatrikelNummer: "+ matrikelNummer);

		myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		if(myStudent != null)
		{
			System.out.println(" "+ myStudent.name + " mit " + myStudent.leistungen.length + " Leistungen");
			
			// Wir wollen nur einen Teil transportieren, deswegen muss Liste ueberarbeitet werden
			JsonObject nurMatrikelnummerUndName = new JsonObject();
			nurMatrikelnummerUndName.addProperty("matrikelNummer", myStudent.matrikelNummer);
			nurMatrikelnummerUndName.addProperty("name", myStudent.name);
			ergebnisAlsJSON = gson.toJson(nurMatrikelnummerUndName);
		}
		else
			System.out.println(" nicht gefunden.");

		return ergebnisAlsJSON;
	}
		
	// Funktion fuer Pfad 4 der Server-Sitemap: Leistungen zu einer Matrikelnummer
	@GET
	@Path("/{matrikelNummer}/leistung")
	@Produces(MediaType.APPLICATION_JSON)
	public String getLeistungVonStudenten(@PathParam("matrikelNummer") int matrikelNummer) 
	{
		Student myStudent = null;
		String ergebnisAlsJSON = "null";

		Gson gson = new GsonBuilder().create();

		System.out.print("getLeistungVonStudenten: "+ matrikelNummer);

		myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		if(myStudent != null)
		{
			System.out.println(" "+ myStudent.name + " mit " + myStudent.leistungen.length + " Leistungen");
			ergebnisAlsJSON = gson.toJson(myStudent.leistungen);
		}
		else
			System.out.println(" nicht gefunden.");
	
		return ergebnisAlsJSON;
	}
}

Leistung.java

package restServerHTTPErrors;

public class Leistung {
	String modul;
	double note;
}

RestServer.java

package restServerHTTPErrors;

import java.io.IOException;
import java.net.URI;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

public class RestServer
{
	/*
	 * JAX-RS ist in Java SE (Standard  Edition) NICHT enthalten, sondern nur in Java EE (Enterprise Edition).
	 * Als Referenzimplementierung wird hier Jersey eingesetzt.
	 * 
	 * Zusaetzlich wird ein einfacher Webserver benoetigt (in diesen Beispiel: Grizzly)
	 * 
	 * URLs zu den Biblioteken:
	 * - https://jersey.github.io/
	 * - https://javaee.github.io/grizzly/
	 */

	public static void main(String[] args) throws IOException, InterruptedException 
	{
		String baseUrl = "http://localhost:4434";

		// Webserver erzeugen und mit unserem Service verbinden
		final HttpServer webServer = GrizzlyHttpServerFactory.createHttpServer(URI.create(baseUrl),
				new ResourceConfig(VerwaltungService.class), false);

		// Methode zum Beenden des Webservers beim Beenden des Java-Programms bei der Java-Runtime registrieren 
		Runtime.getRuntime().addShutdownHook(
				new Thread(new Runnable() {
					@Override
					public void run() {
						webServer.shutdownNow();
					}
				}));

		// Webserver starten
		webServer.start();

		System.out.println(String.format(
				"\nGrizzly-HTTP-Server gestartet mit der URL: %s\n"
						+ "Stoppen des Grizzly-HTTP-Servers mit:      Strg+C\n",
						baseUrl + VerwaltungService.webContextPath));

		// Warten bis das Java-Programm beendet wird (durch Ctrl-C)
		Thread.currentThread().join();
	}
}

Speicher.java

package restServerHTTPErrors;

public class Speicher {
	// Array, das die Studenten speichert
	// Kniff: Der Inhalt des Speichers existiert nur einmal, da static
	private static final Student[] studenten;

	// Kniff: Der Inhalt des Speichers wird durch diese Methode beim ersten Zugriff erzeugt
	static
	{
		// Datensaetze erzeugen
		studenten = Speicher.fuelleMitUnsinn(100);
	}

	// Methoden fuer den Zugriff auf die gespeicherten Daten
	public static Student[] getStudenten()
	{
		return studenten;
	}

	public static Student getSucheMatrikelNummerZuName(String name)
	{
		for(Student s : studenten)
		{
			if(s.name.equals(name))
			{
				return s;
			}
		}
		return null;
	}

	public static Student getStudentenInfoZuMatrikelNummer(int matrikelNummer)
	{
		for(Student s : studenten)
		{
			if(s.matrikelNummer == matrikelNummer)
			{
				return s;
			}
		}	
		return null;
	}	

	// Utility-Methoden
	public static Student[] fuelleMitUnsinn(int Zahl)
	{
		// Hilfsvariablen zum Erzeugen von Datensaetzen
		  final String [] vornamen = { "Mia","Ben","Emma","Jonas","Hannah","Leon","Sofia","Finn","Anna","Elias"};
		  final String [] nachnamen = {"Bauer","Becker","Fischer","Fuchs","Hartmann","Lang", "Jung","Hofmann","Huber"};
		  final String [] module = {"Analysis A","Lineare Algebra A","Analysis B","Lineare Algebra B","Numerik A",
				"Stochastik A","Stochastik B","Numerik partieller Differentialgleichungen 1","Numerik partieller Differentialgleichungen 2",
				"Baumechanik I (Statik starrer Koerper)","Baumechanik II (Elastomechanik)","Baumechanik III (Kinematik und Kinetik)",
				"Kontinuumsmechanik I","Modellbildung im Ingenieurwesen","Numerische Mechanik","Festkoerpermechanik","Finite Elemente II",
				"Grundlagen der Elektrotechnik","Umweltbiologie und -chemie","Stroemungsmechanik","Thermodynamik im Ueberblick",
				"Datenstrukturen, Algorithmen und Programmierung","Datenbanksysteme im Ingenieurwesen","Graphen und Netze","Baustoffkunde I",
				"Baustoffkunde II","Ausgleichungsrechnung und Statistik I","Ausgleichungsrechnung und Statistik II",
		"Projekte des Ingenieurwesens" };

		Student[] unsinn = new Student[Zahl];

		for(int i=0; i < Zahl; i++) {
			unsinn[i]=new Student();
			int vn_indx = (int)(Math.random()*vornamen.length);
			int nn_indx = (int)(Math.random()*nachnamen.length);
			unsinn[i].name = vornamen[vn_indx] + " " + nachnamen[nn_indx];
			unsinn[i].matrikelNummer = vn_indx * 100 + nn_indx + i * 10000;
			int notenZahl = (int)(Math.random()*8);
			if(notenZahl >= 1) {
				unsinn[i].leistungen = new Leistung[notenZahl];
				for(int j=0; j < notenZahl; j++) {
					int mod_indx = (int)(Math.random()*module.length);
					unsinn[i].leistungen[j] = new Leistung();
					unsinn[i].leistungen[j].modul = module[mod_indx];
					unsinn[i].leistungen[j].note = (int)(Math.random()*5) + 1;
				}
			}
			else
				unsinn[i].leistungen = null;
		}
		return unsinn;
	}

	public static boolean sindArraysGleich(Student[] a, Student[] b) {
		boolean istUnGleich = false;
		if(a.length == b.length)
		{
			for(int i=0; i < a.length; i++) {
				istUnGleich |= a[i].matrikelNummer != b[i].matrikelNummer;
				istUnGleich |= !(a[i].name.equals(b[i].name));
				if(a[i].leistungen != null) {
					for(int j=0; j < a[i].leistungen.length; j++) {
						istUnGleich |= !(a[i].leistungen[j].modul.equals(b[i].leistungen[j].modul)) ;
						istUnGleich |= a[i].leistungen[j].note != b[i].leistungen[j].note ;
					}
				}
				if(istUnGleich)
					System.out.println("Ungleich a="+ a + "| b=" + b);
			}
		}
		else
			istUnGleich = true;

		return !istUnGleich;
	}
}

Student.java

package restServerHTTPErrors;

public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

VerwaltungService.java

package restServerHTTPErrors;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

@Path(VerwaltungService.webContextPath)
public class VerwaltungService 
{
	static final String webContextPath = "/student";
		
	// Funktion fuer Pfad 1 der Server-Sitemap: Namen und Matrikelnummern aller Studenten
	public Response getListeVonStudenten() 
	{
		String ergebnisAlsJSON;
		ResponseBuilder responseBuilder;
		Response response;
		
		System.out.println("getListeVonStudenten");

		// GSON fuer Umwandlung in JSON
		Gson gson = new GsonBuilder().create();
		
		// Wir wollen nur einen Teil des Studentenarrays transportieren, deswegen muss Liste ueberarbeitet werden
		JsonArray nurMatrikelnummerUndName = new JsonArray();
		for(Student s : Speicher.getStudenten())
		{
			JsonObject dataset = new JsonObject();
			dataset.addProperty("matrikelNummer", s.matrikelNummer);
			dataset.addProperty("name", s.name);
	 		nurMatrikelnummerUndName.add(dataset);
		}
		ergebnisAlsJSON = gson.toJson(nurMatrikelnummerUndName);
		if (ergebnisAlsJSON==null) {
			// keine Daten gefunden ==> Fehlermeldung als HTTP-Status zurueckgeben
			// ResponseBuilder mit HTML Status 5xx instanziieren, Klartextnachricht anhaengen
			responseBuilder = Response.serverError();
			responseBuilder = responseBuilder.entity("500 Internal Server Error");
			// Response erzeugen
			response = responseBuilder.build();
			return response;
		} else {
			// Daten gefunden ==> HTTP-Status Erfolg und Daten in die Response
			responseBuilder = Response.ok(ergebnisAlsJSON, MediaType.APPLICATION_JSON);
			// Response erzeugen
			response = responseBuilder.build();
			return response;
		}
	}
	
	// Funktion fuer Pfad 2 der Server-Sitemap: Matrikelnummer zum Namen
	public Response getSucheMatrikelNummerZuName(String name) 
	{
		ResponseBuilder responseBuilder;
		Response response;
		Student myStudent = null;
		JsonObject matrikelnummer = null;
		String ergebnisAlsJSON;

		Gson gson = new GsonBuilder().create();
				
		System.out.print("getSucheMatrikelNummerZuName: "+ name);
	
		myStudent = Speicher.getSucheMatrikelNummerZuName(name);
		if(myStudent != null)
		{
			 matrikelnummer = new JsonObject();
			 matrikelnummer.addProperty("matrikelNummer", myStudent.matrikelNummer);
		}
		System.out.println(" "+ matrikelnummer);
		ergebnisAlsJSON = gson.toJson(matrikelnummer);
		if (matrikelnummer==null) {
			//JSON Fehlernachricht wird intanziiert
			ergebnisAlsJSON = gson.toJson("404 Not Found. The requested Name /"+name+" was not found on this server");
			//ResponseBuilder wird mit HTML Status 404 instanziiert
			responseBuilder = Response.status(Response.Status.NOT_FOUND);
			//Den ResponseBuilder wird zusaetzlich eine JSON Nachricht angehaengt
			responseBuilder = responseBuilder.entity(ergebnisAlsJSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		} else {
			//ResponseBuilder wird mit HTML Status 200 und einer Nachricht von Typ JSON instanziiert
			responseBuilder = Response.ok(ergebnisAlsJSON, MediaType.APPLICATION_JSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		}
	}
	
	// Pfad 1 und Pfad 2 der Server-Sitemap fuehren auf diese Methode
	// diese verzweigt je nach Aufruf mit oder ohne Query-Parameter 
	@GET
	@Path("/")
	@Produces(MediaType.APPLICATION_JSON) 
	public Response getListeOderSuche(@QueryParam("name") String name) {
		System.out.print("getListeOderSuche: "+ name + " ");
		
		if(name == null)
			// Pfad 1: kein Parameter: gesamte Liste
			return getListeVonStudenten();
		else
			// Pfad 2: mit Parameter: nur ein Eintrag
			return getSucheMatrikelNummerZuName(name);
	}

	// Funktion fuer Pfad 3 der Server-Sitemap: Name zu einer Matrikelnummer
	@GET
	@Path("/{matrikelNummer}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getStudentenInfoZuMatrikelNummer(@PathParam("matrikelNummer") int matrikelNummer) 
	{
		ResponseBuilder responseBuilder;
		Response response;
		Student myStudent = null;
		String ergebnisAlsJSON = "null";

		Gson gson = new GsonBuilder().create();
	
		System.out.print("getStudentenInfoZuMatrikelNummer: "+ matrikelNummer);

		myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		if(myStudent != null)
		{
			System.out.println(" "+ myStudent.name + " mit " + myStudent.leistungen.length + " Leistungen");
			
			// Wir wollen nur einen Teil transportieren, deswegen muss Liste ueberarbeitet werden
			JsonObject nurMatrikelnummerUndName = new JsonObject();
			nurMatrikelnummerUndName.addProperty("matrikelNummer", myStudent.matrikelNummer);
			nurMatrikelnummerUndName.addProperty("name", myStudent.name);
			ergebnisAlsJSON = gson.toJson(nurMatrikelnummerUndName);
			//ResponseBuilder wird mit HTML Status 200 und einer Nachricht von Typ JSON instanziiert
			responseBuilder = Response.ok(ergebnisAlsJSON, MediaType.APPLICATION_JSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		}
		else {
			System.out.println(" nicht gefunden.");
			ergebnisAlsJSON = gson.toJson("404 Not Found. The requested matrikelNummer /"+matrikelNummer+" was not found on this server");
			//ResponseBuilder wird mit HTML Status 404 instanziiert
			responseBuilder = Response.status(Response.Status.NOT_FOUND);
			//Den ResponseBuilder wird zusaetzlich eine JSON Nachricht angehaengt
			responseBuilder = responseBuilder.entity(ergebnisAlsJSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		
		}
			
	}
		
	// Funktion fuer Pfad 4 der Server-Sitemap: Leistungen zu einer Matrikelnummer
	@GET
	@Path("/{matrikelNummer}/leistung")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getLeistungVonStudenten(@PathParam("matrikelNummer") int matrikelNummer) 
	{
		ResponseBuilder responseBuilder;
		Response response;
		Student myStudent = null;
		String ergebnisAlsJSON = "null";

		Gson gson = new GsonBuilder().create();

		System.out.print("getLeistungVonStudenten: "+ matrikelNummer);

		myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
		if(myStudent != null)
		{
			System.out.println(" "+ myStudent.name + " mit " + myStudent.leistungen.length + " Leistungen");
			ergebnisAlsJSON = gson.toJson(myStudent.leistungen);
			//ResponseBuilder wird mit HTML Status 200 und einer Nachricht von Typ JSON instanziiert
			responseBuilder = Response.ok(ergebnisAlsJSON, MediaType.APPLICATION_JSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		}
		else {
			System.out.println(" nicht gefunden.");
			ergebnisAlsJSON = gson.toJson("404 Not Found. The requested matrikelNummer /"+matrikelNummer+" was not found on this server");
			//ResponseBuilder wird mit HTML Status 404 instanziiert
			responseBuilder = Response.status(Response.Status.NOT_FOUND);
			//Den ResponseBuilder wird zusaetzlich eine JSON Nachricht angehaengt
			responseBuilder = responseBuilder.entity(ergebnisAlsJSON);
			//Response wird aus ResponseBuilder instanziiert. Response enthaelt den Statuscode und eine Nachricht, 
			//die jetzt als akzeptiertes Format zurueckgeliefert werden kann
			response = responseBuilder.build();
			return response;
		}
	}
}

Vorschau der Java-Klassen zu Kapitel 9.5.2.2 und 9.5.3


Leistung.java

package restClient;


public class Leistung {
	String modul;
	double note;
}

//
// 4711 - Hans Muster
// Leistungen - REN 1,0
// 		      - GdaT 5,0
// 4712 - Erika Muster
// Leistungen - keine also Wert == null

RestClient.java

package restClient;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import restClient.Leistung;

public class RestClient {

	public static void main(String[] args) 
	{
		// URL des Servers
		String baseUrl   = "http://localhost:4434";
		// Name des Studenten, fuer den wir anfragen
		String name 		 = "Hannah Jung"; 

		// Relative Pfade auf dem Server
		String webContextPath = "/student";  
		String webContextUnderPath = "/leistung";
		
		Student student = new Student();
		student.matrikelNummer = -1;

		System.out.println( "\nAngefragte URL: " + baseUrl + webContextPath );

		// GSON Instanz fuer das Interpretieren der Antwort vom Server
		Gson gson = new GsonBuilder().create();
		
		// Jersey Client fuer das Abfragen des Servers erzeugen
		Client client = ClientBuilder.newClient();
		
		// Server abfragen: 1) Matrikelnummer zu Name
		// WebTarget erzeugen und richtigen Pfad angeben
		WebTarget target = client.target( baseUrl + webContextPath );
		// Parameter name anhaengen
		target = target.queryParam("name",name);
		// GET-Anfrage erzeugen
		Invocation invocation = target.request( MediaType.APPLICATION_JSON ).buildGet();
		// Anfrage an Server senden und JSON-String empfangen
		String jsonString = invocation.invoke(String.class );
		// JSON-String decodieren
		if(jsonString != null)
			student = gson.fromJson(jsonString, Student.class);
		
		if(student.matrikelNummer != -1)
		{
			System.out.println("\nStudent gefunden: " + student.matrikelNummer );
			
			// Server abfragen: 2) leistungen zur Matrikelnummer
			// WebTarget erzeugen und richtigen Pfad angeben
			target = client.target( baseUrl + webContextPath);
			// gefundene Matrikelnummer an Pfad anhaengen
			target = target.path( String.valueOf(student.matrikelNummer) );
			// Unterpfad /leistung an Pfad anhaengen
			target = target.path( webContextUnderPath );
			// GET-Anfrage erzeugen
			invocation = target.request( MediaType.APPLICATION_JSON ).buildGet();
			// Anfrag an Server senden und JSON-String empfangen
			jsonString = invocation.invoke(String.class );
			// JSON-String decodieren
			Leistung[] leistungen = gson.fromJson(jsonString, Leistung[].class);
			
			System.out.println("\nLeistungen:" );
			for(Leistung l : leistungen)
			{
				System.out.println(l.modul + ": " + l.note);	
			}
		}
		else
		{
			System.out.println("\nKeinen Studenten gefunden!" );
		}
	}
}

Student.java

package restClient;


public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

Leistung.java

package restClientHTTP;

public class Leistung {
	String modul;
	double note;
}

RestClientHTTP.java

package restClientHTTP;


import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class RestClientHTTP {

	public static void main(String[] args) throws ClientProtocolException, IOException, URISyntaxException {

		// GSON Instanz fuer das Interpretieren der Antwort vom Server
		Gson gson = new GsonBuilder().create();

		// HTTP Client fuer das Senden von HTTP Requests
		CloseableHttpClient httpClient = HttpClients.createDefault();

		// URI aufbauen
		URIBuilder uriBuilder = new URIBuilder("http://localhost:4434/student/");
		uriBuilder.addParameter("name", "Mia Fischer");
		// GET Request auf Server
		HttpGet httpGet = new HttpGet(uriBuilder.build());
		CloseableHttpResponse response = httpClient.execute(httpGet);

		// Abholen der Antwort ueber einen StreamReader
		HttpEntity entity = response.getEntity();
		InputStreamReader httpStreamReader = new InputStreamReader(entity.getContent());

		// Parsen der Antwort mit GSON, Umwandeln in den von uns gewuenschten Typ
		Student student = new Student();
		student.matrikelNummer = -1;
		
		student = gson.fromJson(httpStreamReader, Student.class);

		// Aufraeumen 
		EntityUtils.consume(entity);
		response.close();

		if(student.matrikelNummer != -1)
		{
			// Student gefunden
			System.out.println("\nStudent gefunden: " + student.matrikelNummer);

			// URI aufbauen
			uriBuilder = new URIBuilder("http://localhost:4434/student/");
			uriBuilder = uriBuilder.setPath(uriBuilder.getPath() + Integer.toString(student.matrikelNummer));
			uriBuilder = uriBuilder.setPath(uriBuilder.getPath() + "/leistung");
			
			// GET Request auf unseren Server
			httpGet = new HttpGet(uriBuilder.build());
			response = httpClient.execute(httpGet);

			// Abholen der Antwort ueber einen StreamReader
			entity = response.getEntity();
			httpStreamReader = new InputStreamReader(entity.getContent());

			// Parsen der Antwort mit GSON, Umwandeln in den von uns gewuenschten Typ
			// JSON-String decodieren
			Leistung[] leistungen = gson.fromJson(httpStreamReader, Leistung[].class);

			// Aufraeumen 
			EntityUtils.consume(entity);
			response.close();

			System.out.println("\nLeistungen:" );
			for(Leistung l : leistungen)
			{
				System.out.println(l.modul + ": " + l.note);	
			}
		}
		else
		{
			System.out.println("\nKeinen Studenten gefunden!" );
		}
	}
}



Student.java

package restClientHTTP;

public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

Leistung.java

package restClientHTTPErrors;

public class Leistung {
	String modul;
	double note;
}

RestClient.java

package restClientHTTPErrors;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status.Family;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import restClientHTTPErrors.Leistung;

public class RestClient {

	public static void main(String[] args) 
	{
		// URL des Servers
		String baseUrl   = "http://localhost:4434";
		// Name des Studenten, fuer den wir anfragen
		String name 		 = "Hannah Jung"; 

		// Relative Pfade auf dem Server
		String webContextPath = "/student";  
		String webContextUnderPath = "/leistung";
		
		Student student = new Student();

		System.out.println( "\nAngefragte URL: " + baseUrl + webContextPath );

		// GSON Instanz fuer das Interpretieren der Antwort vom Server
		Gson gson = new GsonBuilder().create();
		
		// Jersey Client fuer das Abfragen des Servers erzeugen
		Client client = ClientBuilder.newClient();
		
		// Server abfragen: 1) Matrikelnummer zu Name
		// WebTarget erzeugen und richtigen Pfad angeben
		WebTarget target = client.target( baseUrl + webContextPath );
		// Parameter name anhaengen
		target = target.queryParam("name",name);
		// GET-Anfrage erzeugen
		Builder builder = target.request( MediaType.APPLICATION_JSON );
		Invocation invocation = builder.buildGet();
		// Anfrage an Server senden und JSON-String empfangen
		Response response = invocation.invoke(Response.class );
		// JSON-String decodieren
		String jsonString = response.readEntity(String.class);
		student = gson.fromJson(jsonString, Student.class);
		
		//Status pruefen der GET Anfrage
		if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL)
		{
			System.out.println("\nStudent gefunden: " + student.matrikelNummer );
			
			// Server abfragen: 2) leistungen zur Matrikelnummer
			// WebTarget erzeugen und richtigen Pfad angeben
			target = client.target( baseUrl + webContextPath);
			// gefundene Matrikelnummer an Pfad anhaengen
			target = target.path( String.valueOf(student.matrikelNummer) );
			// Unterpfad /leistung an Pfad anhaengen
			target = target.path( webContextUnderPath );
			// GET-Anfrage erzeugen
			builder = target.request( MediaType.APPLICATION_JSON );
			invocation = builder.buildGet();
			// Anfrag an Server senden und JSON-String empfangen
			response = invocation.invoke(Response.class );
			// JSON-String decodieren
			jsonString = response.readEntity(String.class);
			Leistung[] leistungen = gson.fromJson(jsonString, Leistung[].class);
			
			System.out.println("\nLeistungen:" );
			for(Leistung l : leistungen)
			{
				System.out.println(l.modul + ": " + l.note);	
			}
		}
		else
		{
			System.out.println("\nKeinen Studenten gefunden!" );
		}
	}
}

Student.java

package restClientHTTPErrors;


public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

Vorschau der Java-Klassen zu Kapitel 9.6


Befehl.java

package TcpProtokollClient;

import java.io.UnsupportedEncodingException;

public class Befehl 
{
	String anfrage = "";
	String anhang  = "";
	
	public byte[] baueBefehlString() throws UnsupportedEncodingException
	{
		// Speicher fuer die Teile des Befehls
		// 3 Bytes fuer die Anfrage im 7Bit Ascii-Code
		byte[] anfrageBytes = anfrage.getBytes("ASCII");
		// Bytes fuer den Parameter im 8/16/32Bit UTF-8 Code
		byte[] anhangBytes = anhang.getBytes("UTF-8");
		// 3 Bytes fuer die Zeichenkette der Laenge im 7Bit Ascii-Code
		byte[] lengthBytes =  String.format("%03d", anhangBytes.length).getBytes("ASCII");
		
		// Zielarray in entsprechender Groesse anlegen
		byte[] befehlBytes = new byte[3 + 3 + anhangBytes.length];
		
		// umkopieren in Zielarray
		int index = 0;
		for(int i=0; i < anfrageBytes.length; i++)
			befehlBytes[index++] = anfrageBytes[i];
		for(int i=0; i < lengthBytes.length; i++)
			befehlBytes[index++] = lengthBytes[i];
		for(int i=0; i < anhangBytes.length; i++)
			befehlBytes[index++] = anhangBytes[i];
		
		return befehlBytes;
	}
}

Leistung.java

package TcpProtokollClient;

public class Leistung {
	String modul;
	double note;
}

//
// 4711 - Hans Muster
// Leistungen - REN 1,0
// 		      - GdaT 5,0
// 4712 - Erika Muster
// Leistungen - keine also Wert == null

TCPClient.java

package TcpProtokollClient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;

public class TCPClient 
{
	String ip;
	int port;
	Socket server;
	OutputStream outToServer;
	InputStream inFromServer;

	public TCPClient(String ip, int port)
	{
		this.ip = ip;
		this.port = port;
	}

	public void baueVerbindungAuf() throws UnknownHostException, IOException
	{
		this.server = new Socket(ip, port);

		System.out.println("Client verbunden mit: " + this.server.getInetAddress() + ":" + this.server.getPort());

		this.outToServer = this.server.getOutputStream();
		this.inFromServer = this.server.getInputStream();
	}

	public Befehl sendeBefehl(Befehl befehl) throws IOException
	{
		byte[] bytes = new byte[6];
		Befehl antwort = new Befehl();

		outToServer.write(befehl.baueBefehlString());

		int read = inFromServer.read(bytes, 0, 6);
		if(read == -1)
		{
			schliesseVerbindung();
			return antwort;
		}
		antwort.anfrage = new String(bytes, 0, 3, Charset.forName("ASCII"));
		String antwortAnhangLaenge = new String(bytes, 3, 3, Charset.forName("ASCII"));

		int anhangLaenge = Integer.parseInt(antwortAnhangLaenge);
		if(anhangLaenge > 0)
		{
			bytes = new byte[anhangLaenge];
			inFromServer.read(bytes, 0, anhangLaenge);
			antwort.anhang = new String(bytes, 0, anhangLaenge, Charset.forName("UTF-8"));
		}
		return antwort;
	}

	public void schliesseVerbindung() throws IOException
	{
		outToServer.close();
		inFromServer.close();
		server.close();
	}

	public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException
	{
		String ip =  "localhost";
		int port  =  47331;
		String name = "Mia Fischer";
		
		TCPClient client = new TCPClient(ip, port);

		client.baueVerbindungAuf();

		// Finde Matrikelnummer zu Name 
		Befehl befehl = new Befehl(); 
		befehl.anfrage = "MAT";
		befehl.anhang = name;
		Befehl antwort = client.sendeBefehl(befehl);
		if(antwort.anhang.length() > 0)
		{
			// Martikelnummer zu Name gefunden (Student vorhanden)
			int matrikelNummer = Integer.parseInt(antwort.anhang);
			System.out.println("Matrikelnummer zu " + name + " ist: "+ matrikelNummer);

			// Leistungen des Studenten landen
			befehl.anfrage = "LEI";
			befehl.anhang = String.format("%03d", matrikelNummer);
			antwort = client.sendeBefehl(befehl); 

			String elemente[] = antwort.anhang.split("\\|");
			Leistung leistungen[] = new Leistung[elemente.length];
			for(int i = 0; i < leistungen.length; i++)
			{
				String teile[] = elemente[i].split(";");
				leistungen[i] = new Leistung();
				leistungen[i].modul = teile[0];
				leistungen[i].note = Double.parseDouble(teile[1]);
				System.out.println(leistungen[i].modul + " " + leistungen[i].note);
			}
		}
		else 
			System.out.println("Matrikelnummer zu " + name + " nicht gefunden");

		client.schliesseVerbindung();
	}
}

Befehl.java

package TcpProtokollServer;

import java.io.UnsupportedEncodingException;

public class Befehl 
{
	String anfrage = "";
	String anhang  = "";
	
	public byte[] baueBefehlString() throws UnsupportedEncodingException
	{
		// Speicher fuer die Teile des Befehls
		// 3 Bytes fuer die Anfrage im 7Bit Ascii-Code
		byte[] anfrageBytes = anfrage.getBytes("ASCII");
		// Bytes fuer den Parameter im 8/16/32Bit UTF-8 Code
		byte[] anhangBytes = anhang.getBytes("UTF-8");
		// 3 Bytes fuer die Zeichenkette der Laenge im 7Bit Ascii-Code
		byte[] lengthBytes =  String.format("%03d", anhangBytes.length).getBytes("ASCII");
		
		// Zielarray in entsprechender Groesse anlegen
		byte[] befehlBytes = new byte[3 + 3 + anhangBytes.length];
		
		// umkopieren in Zielarray
		int index = 0;
		for(int i=0; i < anfrageBytes.length; i++)
			befehlBytes[index++] = anfrageBytes[i];
		for(int i=0; i < lengthBytes.length; i++)
			befehlBytes[index++] = lengthBytes[i];
		for(int i=0; i < anhangBytes.length; i++)
			befehlBytes[index++] = anhangBytes[i];
		
		return befehlBytes;
	}
}

ClientHandler.java

package TcpProtokollServer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;

public class ClientHandler extends Thread
{
	Socket clientSocket;
	InputStream inFromClient;
	OutputStream outToClient;

	public ClientHandler(Socket clientSocket) throws IOException
	{
		this.clientSocket = clientSocket;
		this.inFromClient = clientSocket.getInputStream();
		this.outToClient = clientSocket.getOutputStream();
	}

	@Override
	public void run()
	{
		while(true)
		{
			try 
			{
				byte[] bytes = new byte[6];

				int read = inFromClient.read(bytes, 0, 6);
				if(read == -1)
				{
					schliesseVerbindung();
					return;
				}

				Befehl befehl = new Befehl();

				befehl.anfrage = new String(bytes, 0, 3, Charset.forName("ASCII"));
				String anhangLaenge = new String(bytes, 3, 3, Charset.forName("ASCII"));

				int laenge = Integer.parseInt(anhangLaenge);
				if(laenge > 0)
				{
					bytes = new byte[laenge];
					inFromClient.read(bytes, 0, laenge);
					befehl.anhang = new String(bytes, 0, laenge, Charset.forName("UTF-8"));
				}
				System.out.println("Kommando: " + befehl.anfrage + " " + befehl.anhang + 
						" von " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
			
				if(befehl.anfrage.contains("MAT"))
				{
					Befehl antwort = new Befehl();
					antwort.anfrage = "ANT";
					
					Student myStudent= Speicher.getSucheMatrikelNummerZuName(befehl.anhang);
					if(myStudent != null)
					{
						antwort.anhang = String.valueOf(myStudent.matrikelNummer); 
					}
					outToClient.write(antwort.baueBefehlString());
				}
				else if(befehl.anfrage.contains("STU"))
				{
					Befehl antwort = new Befehl();
					antwort.anfrage = "ANT";
					int matrikelNummer = Integer.parseInt(befehl.anhang);
					
					Student myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
					if(myStudent != null)
					{
						antwort.anhang = myStudent.matrikelNummer + ";" + myStudent.name; 
					}
					outToClient.write(antwort.baueBefehlString());
				}
				else if(befehl.anfrage.contains("LEI"))
				{
					Befehl antwort = new Befehl();
					antwort.anfrage = "ANT";
					int matrikelNummer = Integer.parseInt(befehl.anhang);

					Student myStudent = Speicher.getStudentenInfoZuMatrikelNummer(matrikelNummer);
					if(myStudent != null)
					{
						if(myStudent.leistungen != null)
						{
							for(Leistung l: myStudent.leistungen)
							{
								antwort.anhang += l.modul + ";" + l.note + "|";
							}
						}
					}
					outToClient.write(antwort.baueBefehlString());
				}
			}
			catch (Exception e) 
			{
				if(!clientSocket.isConnected())
				{
					try 
					{
						schliesseVerbindung();
					} 
					catch (IOException e1) 
					{
						e1.printStackTrace();
					}
				}
				e.printStackTrace();
				return;
			}
		}
	}

	public void schliesseVerbindung() throws IOException
	{
		System.out.println("Verbindung beendet " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
		outToClient.close();
		inFromClient.close();
		clientSocket.close();
	}
}

Leistung.java

package TcpProtokollServer;


public class Leistung {
	String modul;
	double note;
}

//
// 4711 - Hans Muster
// Leistungen - REN 1,0
// 		      - GdaT 5,0
// 4712 - Erika Muster
// Leistungen - keine also Wert == null

Speicher.java

package TcpProtokollServer;

public class Speicher {
	// Array, das die Studenten speichert
	// Kniff: Der Inhalt des Speichers existiert nur einmal, da static
	private static final Student[] studenten;

	// Kniff: Der Inhalt des Speichers wird durch diese Methode beim ersten Zugriff erzeugt
	static
	{
		// Datensaetze erzeugen
		studenten = Speicher.fuelleMitUnsinn(1000);
	}

	// Methoden fuer den Zugriff auf die gespeicherten Daten
	public static Student[] getStudenten()
	{
		return studenten;
	}

	public static Student getSucheMatrikelNummerZuName(String name)
	{
		for(Student s : studenten)
		{
			if(s.name.equals(name))
			{
				return s;
			}
		}
		return null;
	}

	public static Student getStudentenInfoZuMatrikelNummer(int matrikelNummer)
	{
		for(Student s : studenten)
		{
			if(s.matrikelNummer == matrikelNummer)
			{
				return s;
			}
		}	
		return null;
	}	

	// Utility-Methoden
	public static Student[] fuelleMitUnsinn(int Zahl)
	{
		// Hilfsvariablen zum Erzeugen von Datensaetzen
		  final String [] vornamen = { "Mia","Ben","Emma","Jonas","Hannah","Leon","Sofia","Finn","Anna","Elias"};
		  final String [] nachnamen = {"Bauer","Becker","Fischer","Fuchs","Hartmann","Lang", "Jung","Hofmann","Huber"};
		  final String [] module = {"Analysis A","Lineare Algebra A","Analysis B","Lineare Algebra B","Numerik A",
				"Stochastik A","Stochastik B","Numerik partieller Differentialgleichungen 1","Numerik partieller Differentialgleichungen 2",
				"Baumechanik I (Statik starrer Koerper)","Baumechanik II (Elastomechanik)","Baumechanik III (Kinematik und Kinetik)",
				"Kontinuumsmechanik I","Modellbildung im Ingenieurwesen","Numerische Mechanik","Festkoerpermechanik","Finite Elemente II",
				"Grundlagen der Elektrotechnik","Umweltbiologie und -chemie","Stroemungsmechanik","Thermodynamik im Ueberblick",
				"Datenstrukturen, Algorithmen und Programmierung","Datenbanksysteme im Ingenieurwesen","Graphen und Netze","Baustoffkunde I",
				"Baustoffkunde II","Ausgleichungsrechnung und Statistik I","Ausgleichungsrechnung und Statistik II",
		"Projekte des Ingenieurwesens" };

		Student[] unsinn = new Student[Zahl];

		for(int i=0; i < Zahl; i++) {
			unsinn[i]=new Student();
			int vn_indx = (int)(Math.random()*vornamen.length);
			int nn_indx = (int)(Math.random()*nachnamen.length);
			unsinn[i].name = vornamen[vn_indx] + " " + nachnamen[nn_indx];
			unsinn[i].matrikelNummer = vn_indx * 100 + nn_indx;
			int notenZahl = (int)(Math.random()*8);
			if(notenZahl >= 1) {
				unsinn[i].leistungen = new Leistung[notenZahl];
				for(int j=0; j < notenZahl; j++) {
					int mod_indx = (int)(Math.random()*module.length);
					unsinn[i].leistungen[j] = new Leistung();
					unsinn[i].leistungen[j].modul = module[mod_indx];
					unsinn[i].leistungen[j].note = (int)(Math.random()*5) + 1;
				}
			}
			else
				unsinn[i].leistungen = null;
		}
		return unsinn;
	}

	public static boolean sindArraysGleich(Student[] a, Student[] b) {
		boolean istUnGleich = false;
		if(a.length == b.length)
		{
			for(int i=0; i < a.length; i++) {
				istUnGleich |= a[i].matrikelNummer != b[i].matrikelNummer;
				istUnGleich |= !(a[i].name.equals(b[i].name));
				if(a[i].leistungen != null) {
					for(int j=0; j < a[i].leistungen.length; j++) {
						istUnGleich |= !(a[i].leistungen[j].modul.equals(b[i].leistungen[j].modul)) ;
						istUnGleich |= a[i].leistungen[j].note != b[i].leistungen[j].note ;
					}
				}
				if(istUnGleich)
					System.out.println("Ungleich "+ a[i].name);
			}
		}
		else
			istUnGleich = true;

		return !istUnGleich;
	}
}

Student.java

package TcpProtokollServer;


public class Student {
	int matrikelNummer;
	String name;
	Leistung[] leistungen;
}

TCPServer.java

package TcpProtokollServer;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer 
{
	public static void main(String[] args) throws IOException
	{
		int port = 47331;

		// ServerSocket erzeugen
		ServerSocket serverSocket = new ServerSocket(port);
		System.out.println("Warte auf Verbindung auf "+InetAddress.getLocalHost() +":" + port);

		while(true)
		{
			// Auf Verbindung warten
			Socket clientSocket = serverSocket.accept();
			System.out.println("Client verbunden: " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());

			// Thread zur Berabeitung der Anfragen ueber diese Verbindung starten
			ClientHandler clientHandler = new ClientHandler(clientSocket);
			clientHandler.start();
		}
	}
}