RSS

Archiv für den Monat Februar 2012

Erkenntnisse: Wortbedeutungen

Erkenntnisse: Wortbedeutungen

Ich weiß nicht wie es Euch geht, aber manchmal tauchen in Gesprächen, Wörter auf, die ich vielleicht schon einmal gehört habe, aber deren Bedeutung mir nicht wirklich klar ist. Oft kann man sich deren Bedeutung annäherungsweise ableiten, aber die exakte Definition bleibt verborgen. Natürlich ist es heute, durch das Internet und dank Google, einfacher zu recherchieren, aber oft siegt dann doch die Faulheit den Aufwand zu betreiben.

Ich spreche hier von Wörtern wie „meucheln“, „Minne“ etc., aber auch von Wörtern, die neuerdings immer wieder Verwendung finden, wie z.B. „vermeintlich“ oder „am Ende des Tages“. Zumindest bei der Redewendung „am Ende des Tages“, bin ich mir sicher, dass sie direkt aus dem Englischen „at the end of the day“ übersetzt wurde. Meine Erfahrung mit dieser Redewendung ist, dass man sie anwendet, um auszudrücken, worauf Etwas letztendlich hinausläuft. Der Begriff vermeintlich deutet darauf hin, dass Etwas nur so scheint bzw. irrtümlich ist (siehe auch: The Free Dicitionary).

Eine Erläuterung zum Begriff „Meuchelmord“ findet man direkt bei Wikipedia, das entsprechende Verb „meucheln“ (etwas heimlich und hinterhältig tun) wiederrum wird bei gut  Deutsches Rechtswörterbuch: Wörterbuch der älteren deutschen Rechtssprache erklärt. „Minne“ ist ebenfalls auf Wikipedia gut erklärt und bedeutet „Liebe“, d.h. ein „Minnesänger“ singt Liebeslieder – ganz so einfach ist es allerdings nicht, denn wenn man weiterliest, ist der Kontext wichtig: „…(Verehrung einer meist hochgestellten Dame oder Frau, ungleich spontaner Gefühlsäußerung) nennt man die schriftlich überlieferte, hoch ritualisierte Form der gesungenen Liebeslyrik, die der westeuropäische Adel im hohen Mittelalter pflegte, den Kaiser selbst eingeschlossen…“.

Ich finde es teilweise erstaunlich, aber auch spannend, auf solche Wörter zu treffen. Sei es, weil ich mir dann (automatisch) eine Meinung über einen Menschen bilde, oder, weil ich ganz gerne Rätsel löse. Auf jeden Fall wäre es, aus meiner Sicht schade, wenn all diese Wörter in Vergessenheit geraten würden, denn im richtigen Zusammenhang machen sie einen Satz harmonischer, wie ich finde – gelesen oder gesprochen.

 
Hinterlasse einen Kommentar

Verfasst von - Februar 23, 2012 in Allgemein, Erkenntnisse

 

Schlagwörter:

Weblog Betreiber: Impressum Generator


Als Weblog Betreiber bewegt man sich ja bewusst oder unbewusst immer mal wieder an der Grenze der Legalität. So ist es teilweise notwendig ein Impressum zu erstellen. Mit dem Impressum Generator von eRecht 24 wird einem ein Großteil der Arbeit abgenommen. Da ich nur rudimentäre Kenntnisse im Bereich Recht habe, weiss ich nicht in wiefern dieses Tool sinnvolle und rechtskonforme Ergebnisse liefert. Für Kommentare und Hinweise bin ich dankbar 🙂

 
Hinterlasse einen Kommentar

Verfasst von - Februar 23, 2012 in Allgemein

 

Schlagwörter:

JSON Provider erstellen. Part 7: Konvertierung JSONXML


Im folgenden wird die Umwandlung von JSON in XML mit Java beschrieben. Die JSON-lib bietet mit dem JSONSerializer die Möglichkeit nahezu jedes Java-Objekt in die JSON-Notation zu konvertieren. Mit dem XMLSerializer kann man JSON Objekte in die XML-Notation und zurück umwandeln.

Um die JSON-lib benutzen zu können, sind mindestens folgende Libraries zusätzlich notwendig:

Vorbereitung

Erstellen Sie z.B. in Eclipse ein neues Java Projekt und binden Se die o.g. Libraries (inklusive der JSON-lib) in Ihr Projekt ein.
 

 

JSON>XML

Im folgenden Beispiel wird ein JSON String erstellt und aus diesem der korrespondierende XML String erstellt. Die Klasse „XMLSerializer“ bietet über die write-Methode alle Voraussetzungen, um diese Aufgabe zu erledigen:

package org.jkhofmann.dyndns;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;

public class JSON2XMLConverter {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String jsonStr = "{'foo':'bar'," +
						 "'coolness':2.0," +
				         "'altitude':39000," +
				         "'pilot':{'firstName':'Buzz'," +
				         "'lastName':'Aldrin'}," +
				         "'mission':'apollo 11'}";

        XMLSerializer serializer = new XMLSerializer();
        JSON json = JSONSerializer.toJSON( jsonStr );
        String xml = serializer.write( json );
        System.out.println(xml);
	}
}

Die (formatierte) Ausgabe:

<?xml version="1.0" encoding="UTF-8"?>
<o>
  <altitude type="number">39000</altitude>
  <coolness type="number">2.0</coolness>
  <foo type="string">bar</foo>
  <mission type="string">apollo 11</mission>
  <pilot class="object">
    <firstName type="string">Buzz</firstName>
    <lastName type="string">Aldrin</lastName>
  </pilot>
</o>

Will man den Typen-Hinweis ausschalten, gibt man folgenden Befehl „serializer.setTypeHintsEnabled(false);“ vor der Serialisierung ein:

...

        JSON json = JSONSerializer.toJSON( jsonStr );
        serializer.setTypeHintsEnabled(false);
        String xml = serializer.write( json );
...

Die entsprechende Ausgabe sieht dann so aus:

<?xml version="1.0" encoding="UTF-8"?>
<o>
  <altitude>39000</altitude>
  <coolness>2.0</coolness>
  <foo>bar</foo>
  <mission>apollo 11</mission>
  <pilot>
    <firstName>Buzz</firstName>
    <lastName>Aldrin</lastName>
  </pilot>
</o>

Soll der Name des Wurzel-Knotens von „<o>“ z.B. nach „<SampleJSON>“ umbenannt werden, dann gibt man den Befehl „serializer.setRootName(„SampleJSON“)“ ein. Die Ausgabe sieht dann so aus:

<?xml version="1.0" encoding="UTF-8"?>
<SampleJSON>
  <altitude>39000</altitude>
  <coolness>2.0</coolness>
  <foo>bar</foo>
  <mission>apollo 11</mission>
  <pilot>
    <firstName>Buzz</firstName>
    <lastName>Aldrin</lastName>
  </pilot>
</SampleJSON>

 

Hinweis: Will man anstelle eines String einen InputStream umwandeln, leistet die Apache Commons IOUtils Library hilfreiche Dienste.

// is comes as a InputStream object and will be
// converted to a String:
String jsonData = IOUtils.toString(is);

 

XML > JSON

Um einen XML String in einen JSON String umzuwandeln, kann man wieder die Klasse „XMLSerializer“ verwenden, diesmal aber über die read-Methode:

JSON jsonout = serializer.read( xml );

Beispiel: Die Klasse wandelt einen JSON String in einen XML String um und anschließend wieder in einen JSON String:

package org.jkhofmann.dyndns;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;

public class JSON2XMLConverter {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		// JSON Eingabestring:
		String jsonStr = "{'foo':'bar'," +
						 "'coolness':2.0," +
				         "'altitude':39000," +
				         "'pilot':{'firstName':'Buzz'," +
				         "'lastName':'Aldrin'}," +
				         "'mission':'apollo 11'}";

		// Konvertierung nach XML:
        XMLSerializer serializer = new XMLSerializer();
        JSON json = JSONSerializer.toJSON( jsonStr );
        serializer.setTypeHintsEnabled(false);
        serializer.setRootName("SampleJSON");
        String xml = serializer.write( json );
        System.out.println(xml);
        // Konvertierung zurück nach JSON:
        JSON jsonout = serializer.read( xml );
        System.out.println( jsonout );
	}
}

Ausgabe des JSON Strings:

{"altitude":"39000",
 "coolness":"2.0",
 "foo":"bar",
 "mission":"apollo 11",
 "pilot":{
    "firstName":"Buzz",
    "lastName":"Aldrin"
 }
}

 

Links

Wie immer ist ein Großteil der Kenntnisse und Beispiele, de ich hier wiedergebe, nicht auf meinem „eigenen Mist“ gewachsen. Deshalb möchte ich hier die verwendeten Links und weitere Fundstellen nennen:

 
Hinterlasse einen Kommentar

Verfasst von - Februar 23, 2012 in IT, WebServices

 

Schlagwörter: , , ,

Tomcat auf Ubuntu für Eclipse verwenden

Tomcat auf Ubuntu für Eclipse verwenden

Wenn man versucht einen installierten Tomcat-Server z.B. für Debugging in Eclipse zu verwenden und bekommt die Fehlermeldung, dass die Runtime nicht verwendet werden kann, dann kann das an den unterschiedlichen Installationsverzeichnissen der Tomcat Installation liegen.

Nachdem man Tomcat installiert hat, wird die Installation auf /usr/share, /var/lib, /var/log etc. verteilt. Damit scheint zumindest die „Indigo“ Version von Eclipse, Probleme zu haben. Fasst man die verteilten Verzeichnisse über Softlinks wieder in ein Verzeichnis zusammen, dann funktioniert die Einbindung von Tomcat in Eclipse.

sudo apt-get install tomcat6
cd /usr/share/tomcat6
sudo ln -s /var/lib/tomcat6/conf conf
sudo ln -s /etc/tomcat6/policy.d/03catalina.policy conf/catalina.policy
sudo ln -s /var/log/tomcat6 log
sudo chmod -R 777 /usr/share/tomcat6/conf

Anschließend muss man noch die Runtime über Window/Preferences/Sever/Runtime Environments hinzufügen, das entsprechende Verzeichnis (zum obigen Beispiel) wäre dann  /usr/share/tomcat6.

Falls der Tomcat Server nicht gestartet werden kann, liegt das oft daran, dass er bereits beim Booten des OS über ein Skript gestartet wurde. Das Stoppen geht einfach über:

sudo service tomcat6 stop

Anschließend sollte sich der Tomcat Server in Eclipse starten lassen.

Hinweis: Die Informationen wurden aus stackoverflow entnommen und aufbereitet!

 
Hinterlasse einen Kommentar

Verfasst von - Februar 22, 2012 in IT

 

Schlagwörter: ,

JSON Provider erstellen. Part 6: Ressourcen, Sub-Ressourcen


Im letzten Teil ging es um „Ressourcen, Parameter, CRUD, JSON etc.„, in diesem Artikel soll das Thema „Ressourcen“ vertieft werden.

Mit Root- und Sub-Ressourcen, sowie mit Sub-Ressource-Locators ist es möglich einen Rest-Service und dessen Ressourcen in einer Klassen-Hierarchie zu strukturieren.

Root-Ressourcen

Eine Root-Ressource zeichnet sich dadurch aus, dass sie zum einen als POJO (Plain Old Java Object) definiert ist. Die Klasse selbst ist mit @Path annotiert und enthält mindestens eine Methode, die mit @Path, @GET, @PUT, @POST oder @DELETE annotiert ist.

Beispiel:

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

import com.sun.jersey.spi.resource.Singleton;

@Singleton
@Path("/printers")
public class ResourcesSubResources {

    // Root -Resource:
    @GET
	@Produces(MediaType.TEXT_PLAIN)
    public String getMyResources() {
    	return "Root-Resource: Method: getMyResources, URI: /printers";
    }
}

Ausgabe:

 

Sub-Ressourcen

Eine Sub-Ressource zeichnet sich dadurch aus, dass es sich entweder um eine Methode handelt, die mit @GET, @POST, @PUT, @DELETE, zusammen mit @Path annotiert ist, oder über Sub-Ressource-Locators delegiert wird.

Beispiel:

package org.jkhofmann.dyndns;

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

import com.sun.jersey.spi.resource.Singleton;

@Singleton
@Path("/printers")
public class ResourcesSubResources {

    // Root -Resource:
    @GET
	@Produces(MediaType.TEXT_PLAIN)
    public String getMyResources() {
    	return "Root-Resource: Method: getMyResources, URI: /printers";
    }

    // Sub-Resource:
    @GET @Path("/list")
	@Produces(MediaType.TEXT_PLAIN)
    public String getListOfPrinters() {
    	return "Sub-Resource: Method: getListOfPrinters, URI: /printers/list";
    }

    // Sub-Resource:
    @GET @Path("/ids/{printerid}")
	@Produces(MediaType.TEXT_PLAIN)
    public String getPrinter(@PathParam("printerid") String printerId) {
    	return "sub-Resource: Method: getPrinter, URI: /printers/ids/" + printerId;
    }
}

Dazu die entsprechenden Aufrufe in einem Browser:

 

Sub-Ressource-Locators

Man muss nicht alle Root- und Sub-Ressourcen in einer Klasse zusammenfassen. Mit sog. Sub Ressource Locators ist es möglich aus einer Ressource Klasse heraus weitere Ressource Klassen aufzurufen.

Beispiel:

package org.jkhofmann.dyndns;

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

import com.sun.jersey.spi.resource.Singleton;

@Singleton
@Path("/printers")
public class ResourcesSubResources {

    // Root -Resource:
    @GET
	@Produces(MediaType.TEXT_PLAIN)
    public String getMyResources() {
    	return "Root-Resource: Method: getMyResources, URI: /printers";
    }
...

    // Sub-Resource-Locator:
    @Path("subresource")
    public SubResource getSubResource() {
        return new SubResource();
    }
}

 

Sub Ressource Klasse:

package org.jkhofmann.dyndns;

import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

public class SubResource {
	@GET
	@Produces(MediaType.TEXT_PLAIN)
    public String getMyResources() {
    	return "Sub-Resource: Method: getMyResources, URI: /printers/subresource with subresource locator";
    }

    @GET
    @Path("{version}")
	@Produces(MediaType.TEXT_PLAIN)
    public String getPrinter(@PathParam("version") String version) {
    	return "sub-Resource: Method: getPrinter, URI: /printers/subresource/{version}" + version;
    }
}

 

Aufruf im Browser:

 

Links

Chapter 2. Overview of JAX-RS 1.1.1

 
Hinterlasse einen Kommentar

Verfasst von - Februar 21, 2012 in IT, WebServices

 

JSON Provider erstellen. Part 5: Ressourcen, Parameter, CRUD, JSON- und XML-Response


Nachdem ich im vorigen Teil die grundsätzliche Vorgehensweise zum Erstellen eines REST-Services auf Tomcat mit der Jersey-Bibliothek erläutert habe, will ich diesem Teil noch zeigen, wie man Klassen für Ressourcen definiert, CRUD anwendet und einen REST-Service JSON sprechen läßt. Dazu verwende ich die generierte „Kontakte“-Klasse aus dem Artikel „JAXB mit Eclipse nutzen“ im REST-Jargon als Ressource. Die Server-Klasse kann sowohl XML, als auch JSON zurückgeben.

Wer mehr zu Rest und dessen Vokabular erfahren will, dem seien u. a. folgendeArtikel empfohlen: „OData: die Daten API des Webs„, „JSON Provider erstellen. Part 4: Mit Tomcat und Jersey REST Services erstellen“ und „Representational state transfer (REST)„.

 

Die Server Klasse um JSON und JAXB erweitern

Im letzten Teil habe ich mehr oder weniger sinnlosen Text über REST ausgegeben. Das soll sich nun ändern, die Texte sind nicht unbedingt sinnvoller ;-), aber immerhin erfolgt die Ausgabe nicht mehr direkt, sondern über das Einlesen und Schreiben einer XML Datei („Kontakte.xml“), die als Datenbank dient. Alle Kontakte werden auf dem Server von ihr gelesen bzw. in sie geschrieben – mit JAXB sollte das kein Problem darstellen. Bei der Anwendung von CRUD bietet es sich an diese Datei entsprechend zu synchronisieren, also neue Kontakte hinzuzufügen (C = Create), alle oder einzelne Kontakte zu lesen (R = Read), Kontakte zu verändern (U = Update) und schließlich auch Kontakte zu löschen (D = Delete).

Die Schnittstelle zwischen der Server-Klasse und der XML-Datei, stellt die Klasse „KontakteHandler“ dar. Mit ihr kann man die CRUD Operationen durchführen.

Man kann das vorhandene Projekt weiterverwenden, oder ein Neues erstellen.

1. Erstellen Sie ein “Dynamic Web Project” mit Eclipse

2. Kopieren der Jersey-Jars und die JAXB-Jars in das Verzeichnis WebContent/WEB-INF/lib des Projektes. Kopieren der generierten JAXB-Klassen (aus dem Artikel „JAXB mit Eclipse nutzen„) in das „src/generated“ Unterverzeichnis des Projektes. Kopieren der Datei „Kontakte.xml“ in das „WebContent“ Verzeichnis.

 

4. Source-Code für die Klasse „KontakteHandler“ erstellen:

package org.jkhofmann.dyndns;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.Writer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import generated.*;

// Klasse (Singleton) zur Verwaltung der "Kontakte" Ressource
public class KontakteHandler {
	private String xmlFileName = "Kontakte.xml";
	private static KontakteHandler instance = null;
	private Kontakte kontakte = null;
	private boolean isSyncedWithFile = false;

	private KontakteHandler() {

	}

	public static KontakteHandler getInstance() {
		if (instance == null) {
			instance = new KontakteHandler();
		}
		return instance;
	}

	private void readKontakte() {
		Kontakte kontakteRet = null;
		try {
			// create JAXB context and instantiate unmarshaller
			JAXBContext context = JAXBContext.newInstance(Kontakte.class);
			Unmarshaller um = context.createUnmarshaller();
			this.kontakte = (Kontakte) um.unmarshal(new FileReader(xmlFileName));
			isSyncedWithFile = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void writeKontakte() {
		try {
			// create JAXB context and instantiate marshaller
			JAXBContext context = JAXBContext.newInstance(Kontakte.class);
			Marshaller m = context.createMarshaller();

			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

			Writer w = null;
			try {
				w = new FileWriter(xmlFileName);
				m.marshal(this.kontakte, w);
			} finally {
				try {
					w.close();
				} catch (Exception e) {
				}
			}
			isSyncedWithFile = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Kontakte getKontakte() {
		if (!isSyncedWithFile) {
			this.readKontakte();
		}

		return this.kontakte;
	}

	public Kontakte searchKontakte(String nameArg) {
		Kontakte kontakteRet = null;
		boolean isContactFound = false;

		if (!isSyncedWithFile) {
			this.readKontakte();
		}

		for (int i = 0; i < this.kontakte.getKontakt().toArray().length; i++) {
			Kontakte.Kontakt k = kontakte.getKontakt().get(i);
			if (k.getName().equals(nameArg)) {
				if (!isContactFound) {
					kontakteRet = new Kontakte();
					isContactFound = true;
				}

				kontakteRet.getKontakt().add(k);
			}
		}

		return kontakteRet;
	}

	public void setKontakte(Kontakte kontakte) {
		this.kontakte = kontakte;
		this.writeKontakte();
	}

	public void setXmlFileName(String xmlFileName) {
		this.xmlFileName = xmlFileName;
	}
}

5. Erweitern der Server Klasse um die Repräsentation JSON und die Verwendung der Klasse „KontakteHandler“:

package org.jkhofmann.dyndns;

import java.io.File;

import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import generated.*;

@Path("/kontakte")
public class HelloRestService {
	@Context UriInfo uriInfo;
	@Context Request request;
	@Context ServletContext context;

	// This method is called if JSON is requested. If QueryParam is empty, all contacs will be
	// returned. Otherwise the contact will be searched in the contact list and if it exists it
	// will be returned.
	@GET
	@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public Kontakte getJSON(@QueryParam("name") String name) {
		Kontakte kontakteRet = null;

		// Set path to the contacts xml source file (it is the real path on the tomcat server):
	    String strBas = context.getRealPath("/") + "Kontakte.xml";
	    KontakteHandler.getInstance().setXmlFileName(strBas);

	    // Depending on if QueryParam is set, select the right handler method
		if ((name != null) && name.trim().length() > 0) {
			// if QueryParam is set, it will be searched for it:
			kontakteRet = KontakteHandler.getInstance().searchKontakte(name);
		} else {
			// if QueryParam is NOT set, return all contacts:
			kontakteRet = KontakteHandler.getInstance().getKontakte();
		}

		return kontakteRet;
	}

	// This can be used to test the integration with the browser
	@GET
	@Produces( { MediaType.TEXT_XML })
	public Kontakte getXML(@QueryParam("name") String name) {
		Kontakte kontakteRet = null;

		// Set path to the contacts xml source file (it is the real path on the tomcat server):
	    String strBas = context.getRealPath("/") + "Kontakte.xml";
	    KontakteHandler.getInstance().setXmlFileName(strBas);

	    // Depending on if QueryParam is set, select the right handler method
		if ((name != null) && name.trim().length() > 0) {
			// if QueryParam is set, it will be searched for it:
			kontakteRet = KontakteHandler.getInstance().searchKontakte(name);
		} else {
			// if QueryParam is NOT set, return all contacts:
			kontakteRet = KontakteHandler.getInstance().getKontakte();
		}

		return kontakteRet;
	}
}

 

6. Erstellen und Anpassen der „web.xml“ Datei

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>HelloRestService</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<servlet>
		<servlet-name>HelloRestService</servlet-name>
		<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>com.sun.jersey.config.property.packages</param-name>
			<param-value>org.jkhofmann.dyndns</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloRestService</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

 

7. Erstellen und Deployen des WAR-Archives, z.B. „JerseyJAXBRestTest1.war“

 

Parameter: PathParam, QueryParam, FormParam etc.

Will man auf eine bestimmte Ressource zugreifen, kann dies u.a. über eine Parametrisierung des URI-Pfades geschehen (PathParam), z.B. „GET /artikel/123„, oder durch einen oder mehrere Aufrufparameter (QueryParam), z.B. „GET /artikel?id=123“ geschehen. QueryParam lässt sich relativ einfach anwenden, wie das Beispiel der Server Klasse zeigt, hier wird er Parameter „name“ ausgewertet, ist er angegeben, wird nach einem Kontakt mit diesem Namen gesucht. Ist das nicht der Fall, werden alle Kontakte ausgegeben. Mit FormParam lassen sich Formular-Parameter abfragen, wie sie in HTML-Formularen übergeben werden.

Weitere Informationen und Parameter sind u.a. in http://jsr311.java.net/nonav/releases/1.0/index.html zu finden.

Die Anwendung von QueryParam wurde bereits im vorigen Beispiel veranschaulicht. FormParam kommt in einem späteren Beispiel zur Anwendung. Im folgenden Beispiel wird die Verwendung von PathParam gezeigt:

@Path("/users/{username}")
public class UserResource {

    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String userName) {
        ...
    }
}

 

Testen

Direkt im Browser

Man kann sich die Ergebnisse direkt in einem Browser anschauen, der Link (ohne QueryParam) lautet: http://localhost:8080/JerseyJAXBRestTest1/kontakte

Sollen nur die Kontakte mit einem bestimmten Namen angezeigt werden, lautet die URL beispielsweise: http://localhost:8080/JerseyJAXBRestTest1/kontakte?name=Name1

Advanced Rest Client

Google Chrome Nutzer können auch die Erweiterung „Advanced Rest Client“ verwenden, sie bietet u.a. den Vorteil, dass man sich den JSON-Response direkt anschauen kann. Dazu erweitert man den Header um „Accept“ mit dem Inhalt „application/json“ und drückt anschliessend den „Send request“ Knopf.

Ohne QueryParam: http://localhost:8080/JerseyJAXBRestTest1/kontakte

Ergebnis:

Mit QueryParam: http://localhost:8080/JerseyJAXBRestTest1/kontakte?name=Name1

Ergebnis:

Java Client

Zum Testen des Services kann man beispielsweise folgenden Java-Client implementieren:

package org.jkhofmann.dyndns;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.representation.Form;

public class JerseyJAXBRestTest1Client {
	public static void main(String[] args) {
		ClientConfig config = new DefaultClientConfig();
		Client client = com.sun.jersey.api.client.Client.create(config);
		WebResource service = client.resource(getBaseURI());
		// Get XML
		System.out.println(service.path("kontakte").accept(
				MediaType.TEXT_XML).get(String.class));
		// Get XML for application
		System.out.println(service.path("kontakte").accept(
				MediaType.APPLICATION_JSON).get(String.class));
		// Get JSON for application
		System.out.println(service.path("kontakte").accept(
				MediaType.APPLICATION_XML).get(String.class));
		// Testen von @QueryParam, Methode queryParam baut URL entsprechend zusammen,
		// z.B. GET http://localhost:8080/JerseyJAXBRestTest1/kontakte?name=Name1:
		System.out.println(service.queryParam("name", "Name1").path("kontakte").accept(
				MediaType.APPLICATION_XML).get(String.class));

	}

	   private static URI getBaseURI() {
		return UriBuilder.fromUri(
				"http://localhost:8080/JerseyJAXBRestTest1").build();
	}

}

Das Ergebnis:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Kontakte><Kontakt><Name>Name1</Name><Vorname>Vorname1</Vorname><eMail>eMail1</eMail></Kontakt><Kontakt><Name>Name2Neu</Name><Vorname>Vorname2Neu</Vorname><eMail>eMail2Neu</eMail></Kontakt><Kontakt><Name>Name3Neu</Name><Vorname>Vorname3Neu</Vorname><eMail>eMail3Neu</eMail></Kontakt></Kontakte>
{"Kontakt":[{"Name":"Name1","Vorname":"Vorname1","eMail":"eMail1"},{"Name":"Name2Neu","Vorname":"Vorname2Neu","eMail":"eMail2Neu"},{"Name":"Name3Neu","Vorname":"Vorname3Neu","eMail":"eMail3Neu"}]}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Kontakte><Kontakt><Name>Name1</Name><Vorname>Vorname1</Vorname><eMail>eMail1</eMail></Kontakt><Kontakt><Name>Name2Neu</Name><Vorname>Vorname2Neu</Vorname><eMail>eMail2Neu</eMail></Kontakt><Kontakt><Name>Name3Neu</Name><Vorname>Vorname3Neu</Vorname><eMail>eMail3Neu</eMail></Kontakt></Kontakte>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Kontakte><Kontakt><Name>Name1</Name><Vorname>Vorname1</Vorname><eMail>eMail1</eMail></Kontakt></Kontakte>

In der zweiten Zeile ist der JSON Response und in der vierten Zeile die Rückgabe mit @QueryParam.

 

Jetzt aber: CRUD

Das R(Read) in CRUD haben wir jetzt ausreichend getestet, bleiben noch C (Create), U(Update) und D(Delete). Im folgenden Beispiel wird die Server Klasse entsprechend erweitert und mit unserer Datenbank „Kontakte.xml“ synchronisiert.

Folgende HTTP Operationen werden in diesem Zusammenhang verwendet:

HTTP Operation CRUD
POST Create
GET Read
PUT Update
DELETE Delete

 

PUT – Update

Die folgende Methode dient der Server Klasse dazu, einen Kontakt zu verändern. Hier wird der @FormParam benutzt, wie er beispielsweise in einem HTML Formular verwendet wird.

Die KontakteHandler Klasse wird wie folgt erweitert:

	public void updateKontakte() {
		this.writeKontakte();
	}

Die Server Klasse muss dazu wie folgt erweitert werden:

...
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
...
	// PUT operation to update data. Accepts parameters as form parameters like they usually used
	// in HTML pages. Shows the usage of @FormParam.
	@PUT
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response putContact(@FormParam("name") String nameArg,
							   @FormParam("nameNeu") String neunameArg,
							   @FormParam("vnameNeu") String neuvnameArg,
							   @FormParam("emailNeu") String neuemailArg,
							   @Context HttpServletResponse servletResponse) {
		Response resRet = Response.noContent().build();;

		// Set path to the contacts xml source file (it is the real path on the tomcat server):
	    String strBas = context.getRealPath("/") + "Kontakte.xml";
	    KontakteHandler.getInstance().setXmlFileName(strBas);

	    // Depending on if QueryParam is set, select the right handler method
		if ((nameArg != null) && nameArg.trim().length() > 0) {
			// if QueryParam is set, it will be searched for it:
			Kontakte kontakte = KontakteHandler.getInstance().searchKontakte(nameArg);
			// Check if kontakt was found:
			if (kontakte != null) {
				Kontakte.Kontakt kontakt = kontakte.getKontakt().get(0);
				if ((neunameArg != null) && nameArg.trim().length() > 0)
					kontakt.setName(neunameArg);
				if ((neuvnameArg != null) && nameArg.trim().length() > 0)
					kontakt.setVorname(neuvnameArg);
				if ((neuemailArg != null) && nameArg.trim().length() > 0)
					kontakt.setEMail(neuemailArg);

				KontakteHandler.getInstance().updateKontakte();
				resRet = Response.created(uriInfo.getAbsolutePath()).build();
			}
		} 

		return resRet;
	}

Zum Testen kann die Java Client Klasse wie folgt erweitert werden:

package org.jkhofmann.dyndns;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.representation.Form;

public class JerseyJAXBRestTest1Client {
	public static void main(String[] args) {
		ClientConfig config = new DefaultClientConfig();
		Client client = com.sun.jersey.api.client.Client.create(config);
		WebResource service = client.resource(getBaseURI());
		// Get XML
		System.out.println(service.path("kontakte").accept(
				MediaType.TEXT_XML).get(String.class));
		// Get XML for application
		System.out.println(service.path("kontakte").accept(
				MediaType.APPLICATION_JSON).get(String.class));
		// Get JSON for application
		System.out.println(service.path("kontakte").accept(
				MediaType.APPLICATION_XML).get(String.class));
		// Testen von @QueryParam, Methode queryParam baut URL entsprechend zusammen,
		// z.B. GET http://localhost:8080/JerseyJAXBRestTest1/kontakte?name=Name1:
		System.out.println(service.queryParam("name", "Name1").path("kontakte").accept(
				MediaType.APPLICATION_XML).get(String.class));

		// Check PUT operation:
		// Simulate a HTML form and send PUT request to server to update existing resource:
		Form form = new Form();
		form.add("name", "Name2");
		form.add("nameNeu", "Name2Neu");
		form.add("vnameNeu", "Vorname2Neu");
		form.add("emailNeu", "eMail2Neu");
		ClientResponse response = service.path("kontakte").type(MediaType.APPLICATION_FORM_URLENCODED)
								   .put(ClientResponse.class, form);
	    System.out.println( response.getStatus() + " " + response.getClientResponseStatus() );
	    System.out.println( response.getEntity( String.class ) );
	}

	   private static URI getBaseURI() {
		return UriBuilder.fromUri(
				"http://localhost:8080/JerseyJAXBRestTest1").build();
	}

}

Schaut man sich anschließend die „Kontakte.xml“ Datei im Root Verzeichnis der Web-Applikation an, sieht sie so aus:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Kontakte>
    <Kontakt>
        <Name>Name1</Name>
        <Vorname>Vorname1</Vorname>
        <eMail>eMail1</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name2Neu</Name>
        <Vorname>Vorname2Neu</Vorname>
        <eMail>email2Neu</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name3</Name>
        <Vorname>Vorname3</Vorname>
        <eMail>eMail3</eMail>
    </Kontakt>
</Kontakte>

 

Man erkennt, dass der zweite Eintrag verändert wurde.

Mit dem Advanced Rest Client von Google, kann man beispielsweise folgende Werte testen:

Das Ergebnis:

 

Schaut man sich anschließend die „Kontakte.xml“ Datei im Root Verzeichnis der Web-Applikation an, sieht sie so aus:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Kontakte>
    <Kontakt>
        <Name>Name1</Name>
        <Vorname>Vorname1</Vorname>
        <eMail>eMail1</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name2Neu</Name>
        <Vorname>Vorname2Neu</Vorname>
        <eMail>eMail2Neu</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name3Neu</Name>
        <Vorname>Vorname3Neu</Vorname>
        <eMail>eMail3Neu</eMail>
    </Kontakt>
</Kontakte>

Jetzt wurde der dritte Eintrag verändert.

Anstelle des @FormParam Parameters kann man auch direkt JAXB Klassen übergeben. Zu diesem Zweck muss die Server Klasse um folgende Methode erweitert werden:

...
import javax.xml.bind.JAXBElement;
...
	@PUT
	@Consumes(MediaType.APPLICATION_XML)
	public Response putContact(JAXBElement<Kontakte> kontakteArg) {
		Response resRet = Response.noContent().build();

		// Set path to the contacts xml source file (it is the real path on the
		// tomcat server):
		String strBas = context.getRealPath("/") + "Kontakte.xml";
		KontakteHandler.getInstance().setXmlFileName(strBas);

		// extract the name to search for:
		String searchName = kontakteArg.getValue().getKontakt().get(0).getName();
		// extract the remaining attributes:
		String newVName = kontakteArg.getValue().getKontakt().get(0).getVorname();
		String newEMail = kontakteArg.getValue().getKontakt().get(0).getEMail();

		Kontakte kontakte = KontakteHandler.getInstance().searchKontakte(
				searchName);

		// Check if kontakt was found:
		if (kontakte != null) {
			Kontakte.Kontakt kontakt = kontakte.getKontakt().get(0);
			// if ((neunameArg != null) && nameArg.trim().length() > 0)
			// kontakt.setName(neunameArg);
			if ((newVName != null) && newVName.trim().length() > 0)
				kontakt.setVorname(newVName);
			if ((newEMail != null) && newEMail.trim().length() > 0)
				kontakt.setEMail(newEMail);

			KontakteHandler.getInstance().updateKontakte();
			resRet = Response.created(uriInfo.getAbsolutePath()).build();
		}

		return resRet;
	}

Der Client kann folgenden Aufruf verwenden:

		// Check PUT Operation with JAXB class:
		Kontakte kontakteUpdate = new Kontakte();
		Kontakte.Kontakt kontaktUpdate = new Kontakte.Kontakt();
		kontaktUpdate.setName("Name1");
		kontaktUpdate.setVorname("NeuVorname1");
		kontaktUpdate.setEMail("NeuEMail1");
		kontakteUpdate.getKontakt().add(kontaktUpdate);
		ClientResponse response2 = service.path("kontakte")
				.type(MediaType.APPLICATION_XML)
				.put(ClientResponse.class, kontakteUpdate);
		System.out.println(response2.getStatus() + " "
				+ response2.getClientResponseStatus());
		System.out.println(response2.getEntity(String.class));

Man beachte, dass sich der Name nicht ändern läßt, weil er gleichzeitig als Suchargument verwendet wird. Würde man für jeden Kontakt noch ein weiteres, eindeutiges Attribut definieren, beispielsweise eine ID, dann könnte man das als Suchargument verwenden und auch den Namen ändern.

 

POST – Create

Um die POST Operation zu implementieren, also um einen neuen Kontakt zu erstellen, kann man im Prinzip ähnlich wie bei der PUT Operation vorgehen. Im Beispiel wird wieder der @FormParam verwendet, um die Attribute des neuen Kontaktes festzulegen. Beim PUT habe ich „Response“ als Rückgabetyp gewählt, hier werde ich einmal „text/plain“, also String und einmal „MediaType.APPLICATION_XML“, also XML als Rückgabetyp wählen. Man kann natürlich auch andere Möglichkeiten der Parameterübergabe wählen (z.B. @QueryParam, etc.), das Gleiche gilt für den Response.

Die Server Klasse (mit „text/plain“ als Rückgabetyp):

	@POST
	@Produces("text/plain")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String postContact(@FormParam("nameNeu") String neunameArg,
			@FormParam("vnameNeu") String neuvnameArg,
			@FormParam("emailNeu") String neuemailArg,
			@Context HttpServletResponse servletResponse) {

		// Set path to the contacts xml source file (it is the real path on the
		// tomcat server):
		String strBas = context.getRealPath("/") + "Kontakte.xml";
		KontakteHandler.getInstance().setXmlFileName(strBas);

		Kontakte kontakte = KontakteHandler.getInstance().getKontakte();
		Kontakte.Kontakt kontakt = new Kontakte.Kontakt();

		// Check if there is something to create:
		if ((neunameArg != null) && neunameArg.trim().length() > 0) {
			if ((neunameArg != null) && neunameArg.trim().length() > 0)
				kontakt.setName(neunameArg);
			if ((neuvnameArg != null) && neuvnameArg.trim().length() > 0)
				kontakt.setVorname(neuvnameArg);
			if ((neuemailArg != null) && neuemailArg.trim().length() > 0)
				kontakt.setEMail(neuemailArg);
			kontakte.getKontakt().add(kontakt);
			KontakteHandler.getInstance().updateKontakte();
		}
		return "Customer " + kontakt.getName() + " added !";
	}

Die Server Klasse (mit „MediaType.APPLICATION_XML“ als Rückgabetyp):

	@POST
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Kontakte postContact(@FormParam("nameNeu") String neunameArg,
			@FormParam("vnameNeu") String neuvnameArg,
			@FormParam("emailNeu") String neuemailArg,
			@Context HttpServletResponse servletResponse) {

		// Set path to the contacts xml source file (it is the real path on the
		// tomcat server):
		String strBas = context.getRealPath("/") + "Kontakte.xml";
		KontakteHandler.getInstance().setXmlFileName(strBas);

		Kontakte kontakte = KontakteHandler.getInstance().getKontakte();
		Kontakte.Kontakt kontakt = new Kontakte.Kontakt();

		// Check if there is something to create:
		if ((neunameArg != null) && neunameArg.trim().length() > 0) {
			if ((neunameArg != null) && neunameArg.trim().length() > 0)
				kontakt.setName(neunameArg);
			if ((neuvnameArg != null) && neuvnameArg.trim().length() > 0)
				kontakt.setVorname(neuvnameArg);
			if ((neuemailArg != null) && neuemailArg.trim().length() > 0)
				kontakt.setEMail(neuemailArg);
			kontakte.getKontakt().add(kontakt);
			KontakteHandler.getInstance().updateKontakte();
		}

		// create a "Kontakte" class with one "Kontakt" (the created one),
		// and use it for the response (in XML format):
		Kontakte kontakteRet = new Kontakte();
		kontakteRet.getKontakt().add(kontakt);

		return kontakteRet;
	}

 

Als Client verwende ich wieder den Advanced Rest Client:

Der Response (in der XML Version der Server Methode):

 

DELETE – Delete

Für die Operation Löschen werde ich wieder mit @QueryParam arbeiten und JSON zurückgeben. Auch hier gilt wieder, dass man andere Möglichkeiten der Parameterübergabe wählen könnte (Klasse direkt übergeben, @FormParam etc.), das Gleiche gilt für den Response.

Die Server Klasse wie folgt erweitern:

	@DELETE
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public Kontakte deleteContact(@QueryParam("name") String nameArg) {
		// Set path to the contacts xml source file (it is the real path on the
		// tomcat server):
		String strBas = context.getRealPath("/") + "Kontakte.xml";
		KontakteHandler.getInstance().setXmlFileName(strBas);

		Kontakte.Kontakt kontaktRet = new Kontakte.Kontakt();

		if ((nameArg != null) && nameArg.trim().length() > 0) {
			// if QueryParam is set, it will be searched for it:
			Kontakte kontakte = KontakteHandler.getInstance().searchKontakte(
					nameArg);
			// Check if kontakt was found:
			if (kontakte != null) {
				// save attributes for return value:
				kontaktRet.setName(new String(kontakte.getKontakt().get(0)
						.getName()));
				kontaktRet.setVorname(new String(kontakte.getKontakt().get(0)
						.getVorname()));
				kontaktRet.setEMail(new String(kontakte.getKontakt().get(0)
						.getEMail()));

				// delete contact:
				Kontakte.Kontakt kontakt = kontakte.getKontakt().remove(0);
				KontakteHandler.getInstance().updateKontakte();
			}
		}
		// create a "Kontakte" class with one "Kontakt" (the created one),
		// and use it for the response (in XML format):
		Kontakte kontakteRet = new Kontakte();
		kontakteRet.getKontakt().add(kontaktRet);

		return kontakteRet;
	}

 

Test mit dem Advanced Rest Client:

Das Ergebnis:

 

Links:

vogella: REST with Java (JAX-RS) using Jersey – Tutorial

IBM developerWorks: Build a RESTful Web service using Jersey and Apache Tomcat

Thorsten Horn: RESTful Web Services mit JAX-RS und Jersey

devx.com: JAX-RS: Developing RESTful Web Services in Java

 
Hinterlasse einen Kommentar

Verfasst von - Februar 11, 2012 in Formate, WebServices

 

Schlagwörter: , , , ,

JAXB mit Eclipse nutzen

JAXB mit Eclipse nutzen

Java Architecture for XML Binding (JAXB) ermöglicht den einfachen Umgang mit XML Dateien und Java. Man kann damit Java-Klassen erstellen, die auf Schema-Definitionen (z.B. XSD) von XML Dateien beruhen und diese dann einlesen und weiterverarbeiten. Die umgekehrte Richtung, also das Generieren von XML Dateien aus Java-Klassen ist damit ebenfalls möglich. Beides wird in diesem Artikel behandelt.

 

Voraussetzungen:

Java 1.6

Eclipse IDE for Java EE Developers, ich verwende hier das Indigo Release

Download einer aktuellen JAXB Version, z.B. 2.2.41.

Download JAXB-Eclipse-Plugin, z.B. JAXB-Builder

 

Installation/Konfiguration:

Java und die Eclipse IDE kann man einfach herunterladen und installieren. JAXB kann man an einem zentralen Ort speichern, um später die Libraries und evtl. Tools verwenden zu können (z.B. in den Classpath des Eclipse-Projektes einzubinden) – ich verwende hierfür meist das Verzeichnis „C:Program Files (x86)Java“

Das JAXB Eclipse Plugin muss man entpacken und im Plugin-Verzeichnis der Eclipse-Installation kopieren. Danach Eclipse neu starten. Falls der Wizard über „File > New > Project > JAXB“ nicht sichtbar ist, sollte man Eclipse beenden und mit dem Parameter „-clean“ neu starten, um den Plugin-Cache zu leeren.

 

Erst mal ohne Plugin…:

Um einen ersten Einblick in JAXB zu gewinnen, will ich veranschaulichen, wie man Klassen erstellt, ohne das Eclipse-Plugin zu nutzen. Der erste Schritt besteht darin, sich im Klaren zu sein, welche Daten man verarbeiten will und wie man diese in einer XML-Datei darstellen würde.

Im folgenden Beispiel will ich eine Anwendung erstellen, die in der Lage ist XML-Dateien zu verarbeiten, die Kontakte beinhaltet. Der Aufbau dieser XML-Datei könnte wie folgt aussehen:

<Kontakte>
	<Kontakt>
		<Name>Name1</Name>
		<Vorname>Vorname1</Vorname>
		<eMail>eMail1</eMail>
	</Kontakt>
	<Kontakt>
		<Name>Name2</Name>
		<Vorname>Vorname2</Vorname>
		<eMail>eMail2</eMail>
	</Kontakt>
	<Kontakt>
		<Name>Name3</Name>
		<Vorname>Vorname3</Vorname>
		<eMail>eMail3</eMail>
	</Kontakt>
</Kontakte>

Es gibt eine Vielzahl von Online-Tools, die eine Umwandlung der XML-Datei in eine XSD-Datei (XML-Schema) ermöglichen, z.B. http://www.xmlforasp.net. Das Ergebnis sieht dann wie folgt aus:

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Kontakte">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element maxOccurs="unbounded" name="Kontakt">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="Name" type="xsd:string" />
              <xsd:element name="Vorname" type="xsd:string" />
              <xsd:element name="eMail" type="xsd:string" />
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Jetzt ist es an der Zeit mit Eclipse ein Java Projekt zu erstellen. Die XSD- und die XML-Datei können der Vollständigkeit halber in das Projektverzeichnis kopiert oder dort angelegt werden.

Mit dem Download der JAXB Version werden zwei Skriptdateien mit ausgeliefert, die im „bin“ Unterverzeichnis zu finden sind:

  • „xjc“, um eine XML-Schemadatei in vollständig annotierte Java-Klassen zu kompilieren
  • „schemagen“, um eine XML-Schemadatei aus Java-Klassen zu generieren

Mit dem „xjc“ Tool ist es also möglich, aus der Schema-Datei „Kontakte.xsd“ die entsprechenden JAXB-Java-Klassen zu generieren:

Die generierten Klassen werden im Unterverzeichnis „generated“ gespeichert. Ich kopieren das Verzeichnis in den src Unterordner des Eclipse Projektes und aktualisiere das Projektverzeichnis:

Es werden folgende Klassen und Methoden generiert:

Um die JAXB-Klassen nutzen zu können, müssen die im „lib“-Unterverzeichnis vorhandenen jar Dateien in den Build-Path des Projektes eingebunden werden:

Eine Anwendung, die die XML-Datei parst und weiterverarbeitet könnte etwa so aussehen:

package org.jkhofmann.dyndns;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import generated.*;

public class ParseKontakte {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			// create JAXB context and instantiate marshaller
			JAXBContext context = JAXBContext.newInstance(Kontakte.class);
			Marshaller m = context.createMarshaller();

			// get variables from our xml file, created before
			System.out.println();
			System.out.println("Kontakte XML File: ");
			Unmarshaller um = context.createUnmarshaller();
			Kontakte kontakte = (Kontakte) um.unmarshal(new FileReader(
					"Kontakte.xml"));

			for (int i = 0; i < kontakte.getKontakt().toArray().length; i++) {
				System.out.println("Kontakt " + (i + 1) + ": "
						+ "Name: " + kontakte.getKontakt().get(i).getName() + ", "
						+ "Vorame: " + kontakte.getKontakt().get(i).getVorname() + ", "
						+ "eMail: " + kontakte.getKontakt().get(i).getEMail() + ", "
						);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Die entsprechende Ausgabe:

Kontakte XML File:
Kontakt 1: Name: Name1, Vorame: Vorname1, eMail: eMail1,
Kontakt 2: Name: Name2, Vorame: Vorname2, eMail: eMail2,
Kontakt 3: Name: Name3, Vorame: Vorname3, eMail: eMail3,

In einem weiteren Schritt will ich den Inhalt bearbeiten und erweitern:

package org.jkhofmann.dyndns;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import generated.*;

public class ParseKontakte {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			// create JAXB context and instantiate marshaller
			JAXBContext context = JAXBContext.newInstance(Kontakte.class);
			Marshaller m = context.createMarshaller();

			// get variables from our xml file, created before
			System.out.println();
			System.out.println("Kontakte XML File: ");
			Unmarshaller um = context.createUnmarshaller();
			Kontakte kontakte = (Kontakte) um.unmarshal(new FileReader(
					"Kontakte.xml"));

			for (int i = 0; i < kontakte.getKontakt().toArray().length; i++) {
				System.out.println("Kontakt " + (i + 1) + ": "
						+ "Name: " + kontakte.getKontakt().get(i).getName() + ", "
						+ "Vorame: " + kontakte.getKontakt().get(i).getVorname() + ", "
						+ "eMail: " + kontakte.getKontakt().get(i).getEMail() + ", "
						);
			}

			// Add a new contact:
			Kontakte.Kontakt k = new Kontakte.Kontakt();
			k.setName("Name4");
			k.setVorname("Vorname4");
			k.setEMail("eMail4");

			kontakte.getKontakt().add(k);

			// write the enhanced contact list in a new XML file:
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			m.marshal(kontakte, System.out);

			Writer w = null;
			try {
				w = new FileWriter("Kontakte2.xml");
				m.marshal(kontakte, w);
			} finally {
				try {
					w.close();
				} catch (Exception e) {
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Die Ausgabe („Kontakte2.xml“):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Kontakte>
    <Kontakt>
        <Name>Name1</Name>
        <Vorname>Vorname1</Vorname>
        <eMail>eMail1</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name2</Name>
        <Vorname>Vorname2</Vorname>
        <eMail>eMail2</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name3</Name>
        <Vorname>Vorname3</Vorname>
        <eMail>eMail3</eMail>
    </Kontakt>
    <Kontakt>
        <Name>Name4</Name>
        <Vorname>Vorname4</Vorname>
        <eMail>EMail4</eMail>
    </Kontakt>
</Kontakte>

Ich finde, die Anwendung von JAXB ist im Vergleich zur Anwendung von SAX- oder DOM-Parsern (z.B. Xerces oder allgemeiner  Java API for XML Processing – JAXP), wesentlich einfacher und zeitsparender. Anwender der Eclipse IDE können sich zusätzlich das Plugin „JAXB-Builder“ installieren. Die Anwendung wird im folgenden erläutert.

Jetzt mit dem Plugin…

Dazu erstellt man sich ein neues Projekt über „File > New > Project > JAXB“ und kopiert die XSD-Datei hinein:

Damit das Plugin funktioniert, muss man (wie gehabt) den Build-Path des Projektes um die JAXB-Libraries erweitern:

Durch einen Rechtsklick auf die XSD-Datei > Generate > JAXB Classes… kann man sich die JAXB-Klassen generieren lassen. Das Ergebnis ist das Gleiche wie oben, d.h. das Ausprogrammieren ist noch notwendig.

Man erspart sich allerdings den Umweg über die Kommandozeile, zum Generieren der JAXB-Java-Klassen.

 
Ein Kommentar

Verfasst von - Februar 3, 2012 in Formate, IT

 

Schlagwörter: , , , ,

 
Erstelle eine Website wie diese mit WordPress.com
Jetzt starten