Apache CXF con JAX-RS

Antes de continuar con este capítulo, asumimos que sabe cómo escribir un servicio web RESTful en Java. Le mostraré cómo usar CXF en la parte superior de este JAX-RS (API de Java para servicios web RESTful). Crearemos un servicio web que mantiene una lista de las últimas películas. Cuando el usuario solicita una película, especifica el ID de la película en su solicitud, el servidor localizará la película y se la devolverá al cliente. En nuestro caso trivial, simplemente devolveremos el nombre de la película al cliente y no el archivo MP4 binario real. Así que comencemos a crear una aplicación JAX-RS.

Declaración de elemento de película

Declararemos un elemento raíz XML llamado Movie para almacenar la identificación y el nombre de una película determinada. El elemento se declara en un archivo llamado Movie.java. El contenido del archivo se muestra aquí:

//Movie.java
package com.tutorialspoint.cxf.jaxrs.movie;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Movie")
public class Movie {
   private long id;
   private String name;
   public long getId() {
      return id;
   }
   public void setId(long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

Tenga en cuenta el uso de XmlRootElement etiqueta para declarar el elemento XML para el Movieetiqueta. A continuación, crearemos un servicio que contiene la lista de películas en su base de datos.

Creación de una base de datos de servicios de películas

Para almacenar la lista de películas utilizamos Java suministrado Mapque almacena los pares clave-valor. Si la lista es grande, utilizará un almacenamiento de base de datos externo que también será más fácil de administrar. En nuestro caso trivial, almacenaremos solo cinco películas en nuestra base de datos. El código para la clase MovieService se proporciona a continuación:

//MovieService.java
package com.tutorialspoint.cxf.jaxrs.movie;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@Path("/movieservice/")
@Produces("text/xml")
public class MovieService {
   long currentId = 123;
   Map<Long, Movie> movies = new HashMap<>();
   public MovieService() {
      init();
   }
   @GET
   @Path("/movie/{id}/")
   public Movie getMovie(@PathParam("id") String id) {
      long idNumber = Long.parseLong(id);
      return movies.get(idNumber);
   }
   final void init() {
      Movie c1 = new Movie();
      c1.setName("Aquaman");
      c1.setId(1001);
      movies.put(c1.getId(), c1);
      
      Movie c2 = new Movie();
      c2.setName("Mission Imposssible");
      c2.setId(1002);
      movies.put(c2.getId(), c2);
      
      Movie c3 = new Movie();
      c3.setName("Black Panther");
      c3.setId(1003);
      movies.put(c3.getId(), c3);
      
      Movie c4 = new Movie();
      c4.setName("A Star is Born");
      c4.setId(1004);
      movies.put(c4.getId(), c4);
      
      Movie c5 = new Movie();
      c5.setName("The Meg");
      c5.setId(1005);
      movies.put(c5.getId(), c5);
   }
}

Tenga en cuenta que usamos las siguientes dos anotaciones para especificar la ruta URL para nuestro servicio de películas y su tipo de retorno:

@Path("/movieservice/")
@Produces("text/xml")

Usamos las anotaciones @GET y @Path para especificar la URL para la solicitud GET de la siguiente manera:

@GET
@Path("/movie/{id}/")

La base de datos de películas en sí se inicializa en el método init, donde agregamos cinco elementos de película a la base de datos.

Nuestra próxima tarea es escribir una aplicación de servidor.

Servidor de desarrollo

Para crear un servidor, utilizamos CXF suministrado JAXRSServerFactoryBean clase.

JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();

Establecemos sus clases de recursos llamando al setResourceClasses método.

factory.setResourceClasses(Movie.class);
factory.setResourceClasses(MovieService.class);

Configuramos el proveedor de servicios llamando al setResourceProvider método.

factory.setResourceProvider(MovieService.class,
new SingletonResourceProvider(new MovieService()));

Configuramos el deseado publish dirección llamando al aetAddress método -

factory.setAddress("http://localhost:9000/");

Finalmente, publicamos el servidor llamando al método create en el factory ejemplo.

factory.create();

El código completo para la aplicación del servidor se proporciona a continuación:

//Server.java
package com.tutorialspoint.cxf.jaxrs.movie;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
public class Server {
   public static void main(String[] args) throws Exception {
      JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
      factory.setResourceClasses(Movie.class);
      factory.setResourceClasses(MovieService.class);  
      factory.setResourceProvider(MovieService.class,
         new SingletonResourceProvider(new MovieService()));
      factory.setAddress("http://localhost:9000/");
      factory.create();
      
      System.out.println("Server ready...");
      Thread.sleep(5 * 60 * 1000);
      
      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

El pom.xml final

Aquí hemos incluido la versión final de pom.xml a continuación:

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.tutorialspoint</groupId>
   <artifactId>cxf-jaxrs</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.tutorialspoint.cxf.jaxrs.movie.Server
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
         <dependencies>
            <dependency>
               <groupId>org.apache.cxf</groupId>
               <artifactId>cxf-rt-transports-http-jetty</artifactId>
               <version>3.3.0</version>
            </dependency>
         </dependencies>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.tutorialspoint.cxf.jaxrs.movie.Client
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxrs</artifactId>
         <version>3.3.0</version>
         </dependency>
      <dependency>
         <groupId>jakarta.ws.rs</groupId>
         <artifactId>jakarta.ws.rs-api</artifactId>
         <version>2.1.5</version>
      </dependency>
      <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
         <version>4.5.7</version>
      </dependency>
   </dependencies>
</project>

Cliente en desarrollo

Escribir el cliente RS es trivial. Simplemente creamos un objeto URL y abrimos su flujo. Usamos la clase IOUtils proporcionada por CXF para copiar el contenido del flujo de entrada a un flujo local.

URL url = new URL("http://localhost:9000/movieservice/movie/1002");
try (InputStream instream = url.openStream();
CachedOutputStream outstream = new CachedOutputStream()) {
   IOUtils.copy(instream, outstream);
}

El código completo de la aplicación cliente se proporciona a continuación:

//Client.java
package com.tutorialspoint.cxf.jaxrs.movie;
import java.io.InputStream;
import java.net.URL;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
public class Client {
   public static void main(String[] args) throws Exception {
      URL url = new URL("http://localhost:9000/movieservice/movie/1002");
      try (InputStream instream = url.openStream();
      CachedOutputStream outstream = new CachedOutputStream()) {
         IOUtils.copy(instream, outstream);
         String str = outstream.getOut().toString();
         System.out.println(str);
      }
   }
}

Prueba de la aplicación JAX-RS

Ejecute el servidor usando el siguiente comando en la ventana de la línea de comandos:

mvn -Pserver

Ahora, verá el siguiente mensaje en la consola:

INFO: Setting the server's publish address to be http://localhost:9000

Ahora, abra su navegador y escriba la siguiente URL:

http://localhost:9000/movieservice/movie/1002

Verá lo siguiente en la ventana del navegador.

Puede invocar el servicio utilizando una aplicación cliente Java que hemos desarrollado ejecutando el siguiente comando en una ventana de línea de comandos separada.

mvn -Pclient

Verá la siguiente salida:

<?xml version="1.0" encoding = "UTF-8" standalone="yes"?>
<Movie><id>1002</id><name>Mission Imposssible</name></Movie>

Los ejemplos de CXF proporcionan varios ejemplos sobre cómo utilizar CXF con JAX-RS. Se anima a los lectores interesados ​​a estudiar estas muestras.