Java API for RESTful Webservices (JAX-RS) ist ein Standard, mit dem man REST-APIs in Java implementieren kann. Dabei werden Klassen und Methoden mit Annotationen markiert, damit diese dann auf HTTP-Requests reagieren und passende Responses zu schicken.
JAX-RS bedarf einer Library, die es implementiert (Annotationen auswerten, Serverinstanz starten, Anfragen an Methoden weiterleiten…), z.B. Jersey.
Beispiel
@Path("students")
public class StudentService {
@GET
@Path("{id}")
public Student read(@PathParam("id") int mnr) {
Student s;
// s aus Datenbank lesen
return s;
}
}Annotationen
Für Klassen
@XMLRootElement- Markiert die Klasse als Wurzelelement für XML-Serialisierung. Wurzelelemente sollten eigenständige Entitäten sein.@XmlAccessorType(type)- Legt fest, wie auf Methoden/Felder zugegriffen wirdXmlAccessorType.Field- Direkter Zugriff auf Felder (auch private)XmlAccessorType.PROPERTY- Zugriff über Getter und SetterXmlAccessorType.PUBLIC_MEMBER- Öffentliche FelderXmlAccessorType.NONE- Nur explizit annotierte Felder und Methoden
Für Attribute
@XmlAttribute- Markiert ein Feld als XML-Attribut statt als Element
Beispiel:<student studentNumber="123">/*...*/</student>
statt<student><studentNumber>123</studentNumber>/*...*/</student>@XmlTransiet- Schließt ein Feld/Methode von der XML-Serialisierung aus
Für Methoden
@Path(path)- Definiert den Pfad der URL zur Funktion (kann man auch an Klassen schreiben)@POST,@GET,@PUT,@DELETE- Definiert mit welchen Methoden die URL aufzurufen ist@Produces(type)- Definiert welcher Content-Type als Response gesendet werden darfMediaType.APPLICATION_XML- XML
JSON
@Consumes(MediaType.APPLICATION_JSON)@Produces(MediaType.APPLICATION_JSON)@Singleton
Beispiel
@Singleton // Ohne diese Annotation würde für jede Request ein neuer Service erstellt werden -> Datenverlust
@Path("/todos")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ToDoService {
private final Map<Integer, Todo> todos = new ConcurrentHashMap<>();
private final AtomicInteger id = new AtomicInteger(1);
@GET
public Collection<Todo> getToDos() {
return todos.values();
}
@POST
public Todo createToDo(Todo todo) {
int newId = id.getAndIncrement();
todo.setId(newId);
todos.put(newId, todo);
return todo;
}
@GET
@Path("/{id}")
public Todo readToDo(@PathParam("id") int id) {
Todo todo = todos.get(id);
if(todo == null) {
throw new NotFoundException();
}
return todo;
}
}XML
Für XML bräuchte der Service die Annotationen
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)und das Model bräuchte zusätzlich
@XmlRootElement(name = "todo")
@XmlAccessorType(XmlAccessType.FIELD)Woran liegt das?
Das hängt mit den unterschiedlichen Mappern zusammen, die für XML bzw. JSON verwendet werden. Der JSON-Mapper, meist Jackson, nutzt Reflection und erkennt die Objekte automatisch. Der XML-Mapper JAXB erwartet dass der Programmierer die Elemente selbst definiert.