[Android] RESTEasy und Android
Wurde eine REST-Schnittstelle auf Server-Seite mit RESTEasy implementiert, gab es bisher keine wirkliche Möglichkeit, mit RESTEasy den vorhandenen Code auch auf Android-Seite zu nutzen. RESTEasy funktionierte bisher nicht unter Android. Thomas Diesler hat glücklicherweise ein Projekt auf github (https://github.com/tdiesler/resteasy-mobile) gestartet, welches diesen Teil nachimplementiert. Er hat hierzu auch einen Blogpost verfasst.
Nachfolgende die Kurzform der notwendigen Schritte. Ich habe den Code in drei Projekte aufgeteilt:
- REST-Interface und Transferobjekte
In diesem Projekt werden die Transferobjekte und das REST-Interface implementiert. Transferobjekte sind die Klassen, die die Daten zwischen Server und Client kapseln. Wie der Name REST-Interface schon vermuten lässt, wird damit die Schnittstelle zwischen Client und Server definiert (aber noch nicht implementiert). Nutzt Maven. - REST-Server-Implementierung
Die Implementierung der Backend-Logik. Benutzt das REST-Interface und die Transferobjekte. Nutzt Maven. - REST für Android
Die Implementierung der Android-Client-Seite. Benutzt das REST-Interface und die Transferobjekte.
Für das REST-Interface und Transferobjekte wird folgende Dependency in der pom.xml eingetragen:
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>1.2.1.GA</version> </dependency>
Für die REST-Server-Implementierung werden folgende Dependencies in der pom.xml eingetragen:
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>1.2.1.GA</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>1.2.1.GA</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>jaxrs-api</artifactId> <version>1.2.1.GA</version> </dependency> <dependency> <groupId>net.sf.scannotation</groupId> <artifactId>scannotation</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson-provider</artifactId> <version>2.3.1.GA</version> </dependency> <!-- Reference to REST-Interface-Project --> <dependency> <groupId>de.yellowshoes.rest</groupId> <artifactId>restinterface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
Auf Android-Seite ist kein Maven im Einsatz. Folgende Libraries werden im Buildpath mit aufgenommen:
- Jackson Core ASL 1.6.3
- Jackson JAXRS 1.6.3
- Jackson Mapper ASL 1.6.3
- Jackson XC 1.6.3
- JAXRS API 2.2.1 GA von RESTEasy
- RESTEasy Mobile 1.0.0
Nachfolgend ein einfaches Beispiel, wie eine konkrete Implementierungen aussehen kann:
REST-Interface
Zuerst die Transferklasse. Hier ein Objekt Book. Ein simples POJO, mehr nicht.
public class Book { private String titel; private String author; public String getTitel() { return titel; } public void setTitel( String titel ) { this.titel = titel; } public String getAuthor() { return author; } public void setAuthor( String author ) { this.author = author; } }
Nun das REST-Interface. Die @Path-Annotation definiert jeweils, an welche Url die Klasse/die Methode gebunden wird. Hier wird das komplette Interface an /api gebunden, die Methode (durch die Vererbung) an /api/book. Mit den Annotations @Consumes und @Produces wird festgelegt, was für MediaTypes verarbeitet werden können und was zurückgeschickt werden kann. Hier wird jeweils JSON definiert.
@Path( "/api" ) @Consumes( MediaType.APPLICATION_JSON ) @Produces( MediaType.APPLICATION_JSON ) public interface RestResourceInterface { @GET @Path( "/book" ) public Book getBook(); }
REST-Implementierung
Auf Server-Seite wird nur eine Klasse benötigt.
public class RestResource implements RestResourceInterface { public Book getBook() { Book book = new Book(); book.setAuthor( "Hans Müller" ); book.setTitel( "REST gut" ); return book; } }
REST-Android
Auch auf Android-Seite muss nicht mehr viel gemacht werden. Hier eine einfache Client-Implementierung. Das wichtigste ist die Methode getClient(), die über die ProxyFactory die Schnittstellen-Implementierung initialisiert. Der Code sollte ansonsten selbsterklärend sein.
public class ResteasyClient implements RestResourceInterface { RestResourceInterface client = null; @Override public Book getBook() { RestResourceInterface client = getClient(); Book book = client.getBook(); return book; } private RestResourceInterface getClient() { String requestURI = "http://192.168.11.86:8080/restest/"; if( client == null ) { BasicHttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1 ); HttpProtocolParams.setContentCharset( params, HTTP.DEFAULT_CONTENT_CHARSET ); HttpProtocolParams.setUseExpectContinue( params, false ); client = ProxyFactory.create( RestResourceInterface.class, requestURI, new ApacheHttpClient4Executor( params ) ); } return client; } }