Apache CXF com JAX-RS
Antes de prosseguir neste capítulo, presumimos que você saiba como escrever um serviço da Web RESTful em Java. Vou mostrar a você como usar o CXF em cima deste JAX-RS (API Java para RESTful Web Services). Criaremos um serviço da web que mantém uma lista dos filmes mais recentes. Quando o usuário solicita um filme, ele especifica a ID do filme em sua solicitação, o servidor irá localizar o filme e devolvê-lo ao cliente. Em nosso caso trivial, simplesmente retornaremos o nome do filme ao cliente e não o arquivo MP4 binário real. Portanto, vamos começar a criar um aplicativo JAX-RS.
Declarando elemento de filme
Declararemos um elemento raiz XML denominado Movie para armazenar a id e o nome de um determinado filme. O elemento é declarado em um arquivo chamado Movie.java. O conteúdo do arquivo é mostrado aqui -
//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;
}
}
Observe o uso de XmlRootElement tag para declarar o elemento XML para o Movietag. A seguir, criaremos um serviço que contém a lista de filmes em seu banco de dados.
Criando Banco de Dados do Movie Service
Para armazenar a lista de filmes, usamos o Java fornecido Mapque armazena os pares de valores-chave. Se a lista for grande, você usará um armazenamento de banco de dados externo que também será mais fácil de gerenciar. Em nosso caso trivial, armazenaremos apenas cinco filmes em nosso banco de dados. O código para a classe MovieService é fornecido abaixo -
//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);
}
}
Observe que usamos as duas anotações a seguir para especificar o caminho do URL para nosso serviço de filme e seu tipo de retorno -
@Path("/movieservice/")
@Produces("text/xml")
Usamos as anotações @GET e @Path para especificar a URL para a solicitação GET da seguinte maneira -
@GET
@Path("/movie/{id}/")
O próprio banco de dados de filmes é inicializado no método init, onde adicionamos cinco itens de filmes ao banco de dados.
Nossa próxima tarefa é escrever um aplicativo de servidor.
Servidor de Desenvolvimento
Para criar um servidor, usamos CXF fornecido JAXRSServerFactoryBean classe.
JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
Definimos suas classes de recursos chamando o setResourceClasses método.
factory.setResourceClasses(Movie.class);
factory.setResourceClasses(MovieService.class);
Definimos o provedor de serviços chamando o setResourceProvider método.
factory.setResourceProvider(MovieService.class,
new SingletonResourceProvider(new MovieService()));
Nós definimos o desejado publish endereço chamando o aetAddress método -
factory.setAddress("http://localhost:9000/");
Por fim, publicamos o servidor chamando o método create no factory instância.
factory.create();
O código completo para o aplicativo do servidor é fornecido abaixo -
//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);
}
}
O pom.xml final
Aqui, incluímos a versão final do pom.xml abaixo -
<?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 em desenvolvimento
Escrever o cliente RS é trivial. Simplesmente criamos um objeto URL e abrimos seu stream. Usamos a classe IOUtils fornecida pelo CXF para copiar o conteúdo do fluxo de entrada para um fluxo local.
URL url = new URL("http://localhost:9000/movieservice/movie/1002");
try (InputStream instream = url.openStream();
CachedOutputStream outstream = new CachedOutputStream()) {
IOUtils.copy(instream, outstream);
}
Todo o código para o aplicativo cliente é fornecido abaixo -
//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);
}
}
}
Testando o aplicativo JAX-RS
Execute o servidor usando o seguinte comando na janela da linha de comando -
mvn -Pserver
Agora, você verá a seguinte mensagem no console -
INFO: Setting the server's publish address to be http://localhost:9000
Agora, abra seu navegador e digite o seguinte URL -
http://localhost:9000/movieservice/movie/1002
Você verá o seguinte na janela do navegador.
Você pode invocar o serviço usando um aplicativo cliente Java que desenvolvemos executando o seguinte comando em uma janela de linha de comando separada.
mvn -Pclient
Você verá a seguinte saída -
<?xml version="1.0" encoding = "UTF-8" standalone="yes"?>
<Movie><id>1002</id><name>Mission Imposssible</name></Movie>
Os exemplos CXF fornecem vários exemplos de como usar o CXF com JAX-RS. Os leitores interessados são incentivados a estudar essas amostras.