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;
}
}