JAX-RS

Czym jest JAX-RS

JAX-RS, czyli Java API for RESTful Web Services jest specyfikacją zdefiniowaną w platformie Java EE od wersji 6. Obecna wersja 2.0 została wydana w roku 2013 i stanowi element Javy EE 7.

Założeniem JAX-RS było stworzenie API, które wymaga minimalnej konfiguracji, a sama konfiguracja odbywa się przy pomocy prostych adnotacji zastosowanych na poziomie odpowiednich klas i metod będących zwykłymi klasami POJO. W praktyce pozwala to w bardzo prosty sposób udostępnić w swojej aplikacji REST API.

Dostępne implementacje

jaxrs impl

JAXRS jest jedynie specyfikacją, zbiorem reguł, adnotacji oraz interfejsów, które powinny być zaimplementowane. Istnieje kilka bibliotek, które są implementację tego standardu. Referencyjna to biblioteka Jersey jeszcze z czasów firmy Sun. Korzystając z serwerów JBoss/Wildfly napotkamy na RestEASY, a oprócz tego istnieje jeszcze Apache CXF będąca jednocześnie implementacją specyfikacji JAX-WS (Java API for XML Web Services).

Dostępne adnotacje

JAXRS definiuje bogaty zestaw wygodnych w użyciu adnotacji, z których najważniejsze to:

  • @ApplicationPath - definiuje główną ścieżkę aplikacji / api
  • @Path - określa ścieżkę do zasobu
  • @PathParam - pozwala wykorzystać zmienne w ścieżkach zasobów
  • @GET, @POST, @PUT, @DELETE - służą do określenia typu żądania obsługiwanego przez metodę. Poszczególne żądania odpowiadają operacjom CRUD, które chcemy wykonać na zasobie.
  • @Consumes / @Produces - określa typ danych (odbieranych i produkowanych) przez dany punkt krańcowy. Na ich podstawie wykonywany jest marshalling lub unmarshalling z/do odpowiedniego typu.
  • @QueryParam - mapowanie parametru żądania
  • @FormParam - mapowanie parametru z formularza

JAXB i JSON

JAX-RS posiada bezpośrednią integrację ze specyfikacją JAXB. Jeśli więc oznaczymy klasę jako @XmlRootElement, to będzie ona mogła stanowić wynik metody obsługującej dany endpoint. Adnotacje JAXB pozwolą nam sterować obiektem produkowanym w wyniku marshallingu zarówno dla formatów XML jak i JSON.

Przykład

W projekcie dodajemy zależność do specyfikacji JAXRS:

<dependency>
     <groupId>javax.ws.rs</groupId>
     <artifactId>javax.ws.rs-api</artifactId>
     <version>2.0</version>
 </dependency>

korzystając z serwerów JBoss/Wildfly lepiej skorzystać z sekcji dependencyManagement i zależności dostarczanej przez serwer:

<dependencyManagement>
 	<dependencies>
 		<dependency>
 			<groupId>org.jboss.spec</groupId>
 			<artifactId>jboss-javaee-7.0</artifactId>
 			<version>1.0.3.Final</version>
 			<scope>import</scope>
 			<type>pom</type>
 		</dependency>
 	</dependencies>
 </dependencyManagement>
 
 <dependencies>
 	<dependency>
 		<groupId>org.jboss.spec.javax.ws.rs</groupId>
 		<artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
 		<scope>provided</scope>
 	</dependency>
 </dependencies>

Definiujemy klasę reprezentującą zasób:

package pl.javastart.jaxrs.model;
 
 public class User {
 
     private String username;
     private String email;
     
     public User(String username, String email) {
         this.username = username;
         this.email = email;
     }
 
     public String getUsername() {
         return username;
     }
 
     public void setUsername(String username) {
         this.username = username;
     }
 
     public String getEmail() {
         return email;
     }
 
     public void setEmail(String email) {
         this.email = email;
     }
         
 }

Klasę konfiguracji:

package pl.javastart.jaxrs;
 
 import javax.ws.rs.ApplicationPath;
 import javax.ws.rs.core.Application;
 
 @ApplicationPath("/api")
 public class RestConfig extends Application {
 }

Oraz klasę obsługującą endpoint /users:

package pl.javastart.jaxrs.endpoint;
 
 import java.util.Arrays;
 import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import pl.javastart.jaxrs.model.User;
 
 @Path("/users")
 public class UserEndpoint {
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     public List<User> getAll() {
         List<User> users = Arrays.asList(
                 new User("jankowal1", "jankowal1@gmail.com"),
                 new User("alamak", "jankowal1@tlen.pl"),
                 new User("karolak", "karolak@uu1.com")
                 );
         return users;
     }
     
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     public Response save(User user) {
         System.out.println(user);
         return Response.ok().build();
     }
 }

Po wdrożeniu aplikacji na serwerze pod adresem localhost:8080/adres-aplikacji/api/users otrzymamy w wyniku listę użytkowników w formacie JSON. Możemy także wysłać żądanie POST z użytkownikiem, odpowiednia informacja zostanie zalogowana w konsoli.

json response

Projekt na Github.

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.