Mit der Version 1.1 (aktuell RC2) bekommt das Restlet Framework eine Integration für Spring. Die Konfiguration erfolgt über Web- und Spring-Context der Anwendung. Hierfür stehen dem Entwickler die Klassen RestletFrameworkServlet und SpringRouter zur Verfügung.
Im Gegensatz zu Restlet 1.0 braucht der “Restlet Router” und die “Restlet Application” nicht mehr von dem Entwickler implementiert werden. Nach der Konfiguration in der web.xml und applicationContext.xml müssen nur noch die Anwendungsspezifischen Resources selbst umgesetzt werden. Das Mapping der Resource-URL auf die Restlets erfolgt dabei über die applicationContext.xml.
RestletFrameworkServlet
Das RestletFrameworkServlet stellt die Verbindung zwischen Web Context und Spring Konfiguration für Restlet da. Es nimmt die HTTP Anfragen entgegen und leitet sie an den konfigurierten Router um.
web.xml
<!-- Restlet --> <servlet> <servlet-name>restlet</servlet-name> <servlet-class>com.noelios.restlet.ext.spring.RestletFrameworkServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <init-param> <param-name>targetRestletBeanName</param-name> <param-value>springRouter</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>restlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> |
SpringRouter
Der Spring Router verteilt die eingehenden Anfragen an die konfigurierten Rest Resources. Im Spring Context wird dabei ein Mapping von URLs auf Restlet Beans vorgenommen. Also Beispiel wird hier eine Klasse Note verwendet die eine Id und einen Text beinhaltet.
applicationContext.xml
<!-- restlet --> <bean id="springRouter" class="org.restlet.ext.spring.SpringRouter"> <property name="attachments"> <map> <entry key="/notes/{id}"> <bean class="org.restlet.ext.spring.SpringFinder"> <lookup-method name="createResource" bean="noteResource" /> </bean> </entry> <entry key="/notes"> <bean class="org.restlet.ext.spring.SpringFinder"> <lookup-method name="createResource" bean="notesResource" /> </bean> </entry> </map> </property> </bean> <!-- restlet resources --> <bean id="notesResource" name="notesResource" class="org.example.NotesResource" scope="prototype"> <property name="noteService" ref="noteService" /> </bean> <bean id="noteResource" name="noteResource" class="org.example.NoteResource" scope="prototype"> <property name="noteService" ref="noteService" /> </bean> |
Jetzt fehlen nur noch die Implementierung der Resource Beans. Hier muss lediglich beachtet werden, dass die Resources einen parameterlosen Konstruktor haben und die Context spezifischen Parameter über die init() Methode übergeben werden.
NoteResource.java
public class NoteResource extends Resource { private Note note; private NoteDAO noteDAO; public NoteResource() { } public void setNoteDAO(final NoteDAO noteDAO) { this.noteDAO = noteDAO; } @Override public void init(final Context context, final Request request, final Response response) { super.init(context, request, response); final Integer noteId = Integer.parseInt((String) getRequest().getAttributes().get("id")); note = noteDAO.findById(noteId); if (note != null) { getVariants().add(new Variant(MediaType.TEXT_XML)); } } @Override public Representation getRepresentation(final Variant variant) { if (MediaType.TEXT_XML.equals(variant.getMediaType())) { try { final DomRepresentation representation = new DomRepresentation(MediaType.TEXT_XML); final Document document = representation.getDocument(); final Element eltItem = document.createElement("note"); document.appendChild(eltItem); final Element idElement = document.createElement("id"); idElement.appendChild(document.createTextNode(Integer.toString(note.getId()))); eltItem.appendChild(idElement); final Element textElement = document.createElement("text"); textElement.appendChild(document.createTextNode(note.getText())); eltItem.appendChild(textElement); document.normalizeDocument(); return representation; } catch (final IOException e) { e.printStackTrace(); } } return null; } } |
NotesResource.java
public class NotesResource extends Resource { private List<Note> notes; private NoteDAO noteDAO; public NotesResource() { } public void setNoteDAO(final NoteDAO noteDAO) { this.noteDAO = noteDAO; } @Override public void init(final Context context, final Request request, final Response response) { super.init(context, request, response); notes = noteDAO.getAllNotes(); getVariants().add(new Variant(MediaType.TEXT_XML)); } @Override public Representation getRepresentation(final Variant variant) { if (MediaType.TEXT_XML.equals(variant.getMediaType())) { try { final DomRepresentation representation = new DomRepresentation(MediaType.TEXT_XML); final Document document = representation.getDocument(); final Element root = document.createElement("notes"); d.appendChild(root); for (final Note note : notes) { final Element eltItem = document.createElement("note"); final Element idElement = document.createElement("id"); idElement.appendChild(document.createTextNode(Integer.toString(note.getId()))); eltItem.appendChild(idElement); final Element textElement = document.createElement("text"); textElement.appendChild(document.createTextNode(note.getText())); eltItem.appendChild(textElement); root.appendChild(eltItem); } document.normalizeDocument(); return representation; } catch (final IOException e) { e.printStackTrace(); } } return null; } } |
Wird nun die URL /notes (innerhalb der Webanwendung) aufgerufen wird eine Liste aller Einträge angezeigt; mit /notes/0 kann dann direkt auf einen Eintrag zugegriffen werden.
Für schreibende Zugriffe auf die Resources lohnt sich ein Blick in Dokumentation der Resource Klasse und in das Restlet Tutorial auf restlet.org.