Apache CXF - Guia rápido
No ambiente de hoje, você pode criar um aplicativo de serviço da Web usando várias opções. Você pode usar um ou mais dos vários protocolos padrão e amplamente aceitos para comunicação. Por exemplo , SOAP , XML / HTTP, RESTful HTTP e CORBA (Common Object Request Broker Architecture, que era muito popular antigamente, mas não era usada com tanta frequência agora.
Você também tem a opção de diferentes transportes, como HTTP, JMS , JBI e a escolha de APIs de front-end como JAX-RS e JAX-WS . Tendo tantas opções para o desenvolvimento de serviços da web, há uma necessidade de uma estrutura de serviços de código aberto para unir todas as opções mencionadas acima e é isso que o Apache CXF faz.
Neste tutorial, você aprenderá como usar o CXF para criar um serviço da web e um cliente que consome o serviço, usando uma ou mais das opções que listamos acima. Este tutorial irá guiá-lo por todo o desenvolvimento de código para servidor e cliente. Como cada aplicativo pode usar apenas uma das opções de cada categoria, ou seja, frontend, transporte e protocolo, considerando todas as permutações e combinações desses três, o número de aplicativos será exorbitante.
Este tutorial discute o desenvolvimento dos seguintes projetos em detalhes -
CXF com Plain Old Apache CXF Objects (POJO)
CXF com JAX-WS
CXF com WSDL
CXF com JAX-RS
CXF com JMS
Para mantê-lo simples, usamos o maven com sua interface de linha de comando. Você pode usar seu IDE preferido para criar um projeto maven.
No próximo capítulo, vamos começar com o primeiro.
Neste capítulo, você aprenderá a desenvolver um aplicativo da Web simples que envia uma mensagem de saudação ao usuário. Um projeto de serviço da web usa o modelo WSDL . O CXF permite ocultar esse modelo WSDL fornecendo um front-end simples para mapear APIs do Apache CXF para o WSDL subjacente.
Neste projeto mais simples, a interface do serviço da web será exposta diretamente ao cliente e o cliente usaria APIs CXF nativas do Apache para chamar o serviço da web.
Primeiro, criaremos um serviço da web. Todo serviço possui uma interface que é exposta ao cliente. Podemos escrever essa interface como uma interface simples do Apache CXF ou como um documento WSDL. Nesta abordagem do Apache CXF-First, exporemos nosso serviço por meio de uma interface do Apache CXF.
Desenvolvimento de serviço da web
O serviço que vamos criar na web terá um único método da web chamado greetings. O método leva umstringtipo de argumento no qual enviaremos o nome do usuário. O serviço enviará de volta uma mensagem de saudação ao chamador com o nome de usuário recebido incluído na mensagem.
Interface de serviço da web
Para expor a interface de nosso serviço da web, criaremos uma interface Apache CXF da seguinte maneira -
//HelloWorld.java
package com.tutorialspoint.cxf.pojo;
public interface HelloWorld {
String greetings(String text);
}
A interface tem apenas um método chamado greetings. O servidor implementará esta interface. Em nossa aplicação trivial, essa interface é exposta diretamente ao cliente. Normalmente, em um aplicativo de serviço da web, você usa WSDL para descrever a interface do serviço da web. Neste aplicativo simples, forneceremos essa interface direta ao desenvolvedor do cliente. O cliente então ligaria para ogreetingsmensagem no objeto do servidor. Então, primeiro vamos criar o serviço da web.
Implementação de serviço web
o HelloWorld interface é implementada no HelloWorldImpl Classe Apache CXF conforme mostrado abaixo -
//HelloWorldImpl.java
package com.tutorialspoint.cxf.pojo;
public class HelloWorldImpl implements HelloWorld {
@Override
public String greetings(String text) {
return "Hi " + text;
}
}
o greetings método recebe um parâmetro de string digite, anexa a uma mensagem de saudação e retorna a string resultante para o chamador.
Em seguida, escrevemos o aplicativo de servidor para hospedar o HelloWorld serviço.
Criando Servidor
O aplicativo de servidor consiste em duas partes -
A primeira parte cria uma fábrica para nosso serviço web, e
A segunda parte escreve um main método para instanciá-lo.
O servidor usa ServerFactoryBean classe fornecida por bibliotecas CXF para expor nosso HelloWorldinterface para clientes remotos. Assim, primeiro instanciamos oServerFactoryBean classe e, em seguida, defina suas várias propriedades -
ServerFactoryBean factory = new ServerFactoryBean();
Definimos a classe de serviço a ser chamada chamando o setServiceClass método no factory objeto -
factory.setServiceClass(HelloWorld.class);
Definimos o URL para chamar nosso serviço ligando para o setAddressmétodo. Observe que o serviço será publicado neste URL.
factory.setAddress("http://localhost:5000/Hello");
Nesse caso, o serviço é implantado no servidor embutido e escutará a porta 5000. Você pode optar por qualquer número de porta de sua escolha.
Antes de criar a fábrica, você precisa informá-la sobre nossa classe de implementação de serviço. Isso é feito chamando osetServiceBean método no factory objeto como mostrado aqui -
factory.setServiceBean(new HelloWorldImpl());
O bean de serviço é definido como a instância de nossa classe de implementação de serviço. Finalmente, criamos a fábrica chamando seucreate método -
factory.create();
Agora, como desenvolvemos a fábrica para executar nosso serviço da web, vamos escrever um main método para instanciá-lo e mantê-lo em execução por algum tempo.
Agora, escreva um main método para instanciar o HelloServer classe como segue -
public static void main(String[] args) throws Exception {
new HelloServer();
System.out.println("Listening on port 5000 ...");
}
Uma vez instanciado, o HelloServera classe continuará funcionando indefinidamente. Para implantações de produção, você definitivamente manterá seu servidor funcionando para sempre. Na situação atual, encerraríamos o servidor após um tempo predeterminado da seguinte forma -
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);
Todo o código para o HelloServer a aula é dada abaixo -
//HelloServer.java
//HelloServer.java
package com.tutorialspoint.cxf.pojo;
import org.apache.cxf.frontend.ServerFactoryBean;
public class HelloServer {
protected HelloServer() throws Exception {
ServerFactoryBean factory = new ServerFactoryBean();
factory.setServiceClass(HelloWorld.class);
factory.setAddress("http://localhost:5000/Hello");
factory.setServiceBean(new HelloWorldImpl());
factory.create();
}
public static void main(String[] args) throws Exception {
new HelloServer();
System.out.println("Listening on port 5000 ...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);
}
}
O aplicativo de servidor que criamos usa ServerFactoryBeanclasse das bibliotecas CXF. Devemos agora incluir essas bibliotecas em nosso projeto para compilar com sucesso oHelloServerclasse. Nós vamos usarMaven para configurar as dependências do projeto.
Configurando o Projeto Maven
Para criar um projeto Maven, digite o seguinte comando na janela da linha de comando. Observe que testamos isso em uma máquina Mac. Para instalações do Windows e Linux, as instruções podem ser diferentes em alguns lugares.
mvn archetype:generate
Quando perguntado sobre as propriedades, insira os seguintes valores -
Define value for property 'groupId': : com.tutorialspoint
Define value for property 'artifactId': : cxf-pojo
Define value for property 'version': 1.0-SNAPSHOT: : 1.0
Define value for property 'package': com.tutorialspoint: : com.tutorialspoint.cxf.pojo
Ao concluir o comando maven, você encontrará a estrutura de pastas apropriada criada na pasta atual junto com o arquivo pom.xml.
A estrutura de diretório gerada é mostrada aqui -
Você adicionará as dependências CXF no pom.xmle também copie os arquivos Apache CXF criados acima para a pasta apropriada da estrutura criada pelo maven. Para sua referência, fornecemos abaixo o arquivo pom.xml para o projeto que criamos em nossa máquina.
<?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-pojo</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<profiles>
<profile>
<id>server</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.pojo.HelloServer
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</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.pojo.HelloClient
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-logging</artifactId>
<version>3.3.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>3.3.0</version>
<type>jar</type>
</dependency>
<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-frontend-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<!-- Jetty is needed if you're using the CXFServlet -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<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>
</project>
O pom.xml acima pode incluir dependências adicionais que são irrelevantes para este projeto, mas são necessárias para o nosso próximo projeto neste tutorial. De qualquer forma, não há mal nenhum em incluir dependências adicionais.
Estrutura da Pasta do Projeto
A estrutura da pasta do projeto na minha máquina após colocar os arquivos CXF do cliente e do servidor Apache é mostrada abaixo para sua referência rápida -
Servidor em execução
Para construir o projeto, use o seguinte comando em sua janela de linha de comando -
mvn clean install
Você pode iniciar o servidor usando o seguinte comando -
mvn -Pserver
Isso iniciará o servidor e você verá o seguinte prompt no console -
INFO: Creating Service {http://pojo.cxf.tutorialspoint.com/}HelloWorld from class com.tutorialspoint.cxf.pojo.HelloWorld
INFO: Setting the server's publish address to be http://localhost:5000/Hello
Listening on port 5000 ...
Agora, na janela do seu navegador, especifique o URL do nosso serviço publicado. Você verá a seguinte saída -
Isso confirma que nosso serviço está sendo executado na porta especificada em um host local. Uma vez que não especificamos ogreetings mensagem em nossa chamada, uma mensagem de falha SOAP é retornada ao navegador.
Você pode testar ainda mais seu serviço da web usando um cliente SOAP de sua escolha. Aqui, usamos o Postman para testar nosso servidor.
A saída é mostrada aqui -
Observe aquilo SOAP Requestfoi codificado manualmente. Depois de postar a solicitação, o servidor enviou umSOAP Response mensagem, que é vista na parte inferior da captura de tela.
A partir disso, você pode entender que o CXF mantém o uso de protocolos SOAP para solicitação e resposta, enquanto fornece uma visão unificada de uma variedade de tecnologias da web que existem no mundo atual. Isso simplifica muito o desenvolvimento de aplicativos da web.
Nossa próxima tarefa é criar um cliente que consumirá o serviço da web que você criou.
Criando Cliente
No aplicativo do servidor HelloWorldé a interface que expõe nosso serviço da web. O serviço da web em si apenas fornece uma mensagem de saudação simples ao cliente. Normalmente, a interface do serviço da web é exposta ao mundo externo usando WSDL (Web Services Description Language). Neste aplicativo trivial, iremos expor nosso serviço da web para o cliente expondo diretamente a interface do serviço e que é oHelloWorld.class.
Para isso, o CXF oferece uma classe de fábrica chamada ClientProxyFactoryBean que nos permite anexar à interface desejada para a instância de fábrica criada.
Primeiro, criamos uma instância de bean de fábrica da seguinte maneira -
ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
Nós chamamos o setAddressna instância do bean de fábrica para definir a URL pela qual nosso serviço da web pode ser chamado. Em nosso caso, usaremos a URL usada ao criar o servidor em nossa etapa anterior -
factory.setAddress("http://localhost:5000/Hello");
Em seguida, chamamos o create método no factory instância para anexar nossa interface de serviço HelloWorld.class para isso.
HelloWorld helloServer = factory.create(HelloWorld.class);
Finalmente, chamamos o greetings método para chamar o serviço da web remoto.
System.out.println(helloServer.greetings(System.getProperty("user.name")));
Isso imprimiria uma mensagem de saudação em seu console.
A fonte completa do aplicativo cliente é mostrada abaixo -
//HelloClient.java
package com.tutorialspoint.cxf.pojo;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
public class HelloClient {
public static void main(String[] args) throws Exception {
ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
factory.setAddress("http://localhost:5000/Hello");
HelloWorld helloServer = factory.create(HelloWorld.class);
System.out.println(helloServer.greetings(System.getProperty("user.name")));
}
}
Cliente em execução
Certifique-se de que o servidor ainda esteja em execução em sua máquina. No caso, se ele expirou, reinicie o servidor com o seguinte comando -
mvn -Pserver
Você verá a seguinte mensagem no console -
Listening on port 5000 ...
Agora, antes que o servidor expire o tempo definido para 5 minutos, abra outra janela de linha de comando e inicie o cliente com o seguinte comando -
mvn -Pclient
Você verá uma mensagem semelhante à seguinte na linha de comando -
Hi tutorialspoint
Observe que tutorialspointé o nosso nome de usuário. Você receberá uma saudação com seu próprio nome.
No próximo capítulo, aprenderemos como usar o CXF em um projeto JAX-WS (Apache CXF API para XML Web Services).
Neste aplicativo JAX-WS, usaremos a abordagem Apache CXF primeiro, como o aplicativo POJO anterior. Portanto, primeiro criaremos uma interface para nosso serviço da web.
Declaração de interface de serviço
Como no caso anterior, criaremos um serviço trivial que possui apenas um método de interface chamado saudações. O código para a interface de serviço é mostrado abaixo -
//HelloWorld.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
String greetings(String text);
}
Nós anotamos a interface com um @WebServicetag. A seguir, implementaremos essa interface.
Implementando Interface da Web
A implementação da interface da web é mostrada aqui -
//HelloWorldImpl.java
package com.tutorialspoint.cxf.jaxws.helloworld;
public class HelloWorldImpl implements HelloWorld {
@Override
public String greetings(String name) {
return ("hi " + name);
}
}
O método de saudação é anotado com @Overridetag. O método retorna uma mensagem "oi" ao chamador.
A seguir, escreveremos o código para desenvolver o servidor.
Servidor de Desenvolvimento
Ao contrário do aplicativo POJO, agora iremos desacoplar a interface usando a classe Endpoint fornecida pelo CXF para publicar nosso serviço. Isso é feito nas duas linhas de código a seguir -
HelloWorld implementor = new HelloWorldImpl();
Endpoint.publish(
"http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature()
);
O primeiro parâmetro do método de publicação especifica a URL na qual nosso serviço será disponibilizado aos clientes. O segundo parâmetro especifica a classe de implementação para nosso serviço. Todo o código do servidor é mostrado abaixo -
//Server.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
public static void main(String[] args) throws Exception {
HelloWorld implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature());
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);
}
}
Para implantar nosso servidor, você precisará fazer mais algumas modificações em seu projeto, conforme listado abaixo.
Implantando Servidor
Finalmente, para implantar o aplicativo de servidor, você precisará fazer mais uma modificação em pom.xml para configurar seu aplicativo como um aplicativo da web. O código que você precisa adicionar ao seupom.xml é dado abaixo -
<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.jaxws.helloworld.Server
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Antes de implantar o aplicativo, você precisa adicionar mais dois arquivos ao seu projeto. Eles são mostrados na imagem abaixo -
Esses arquivos são arquivos padrão CXF que definem o mapeamento para CXFServlet. O código dentro doweb.xml arquivo é mostrado aqui para sua referência rápida -
//Web.xml
<?xml version = "1.0" encoding = "UTF-8"??>
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>cxf</display-name>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>
1
</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>
cxf
</servlet-name>
<url-pattern>
/services/*
</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
No cxf-servlet.xml,você declara as propriedades do ponto de extremidade do seu serviço. Isso é mostrado no snippet de código abaixo -
<beans ...>
<jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
id = "helloHTTP"
address = "http://localhost:9090/HelloServerPort"
serviceName = "helloworld:HelloServiceService"
endpointName = "helloworld:HelloServicePort">
</jaxws:endpoint>
</beans>
Aqui, definimos a id para nosso endpoint de serviço, o endereço no qual o serviço estará disponível, o nome do serviço e o nome do endpoint. Agora, você aprendeu como seu serviço é roteado e processado por um servlet CXF.
O pom.xml final
o pom.xmlinclui mais algumas dependências. Em vez de descrever todas as dependências, incluímos a versão final de 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-jaxws</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.jaxws.helloworld.Server
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</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.jaxws.helloworld.Client
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<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-features-logging</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>
</dependencies>
</project>
Observe que também inclui um perfil para construir o cliente que iremos aprender nas seções posteriores deste tutorial.
Executando o serviço HelloWorld
Agora você está pronto para executar o aplicativo da web. Na janela de comando, execute o script de construção usando o seguinte comando.
mvn clean install
mvn -Pserver
Você verá a seguinte mensagem no console -
INFO: Setting the server's publish address to be http://localhost:9090/HelloServerPort
Server ready…
Como anteriormente, você pode testar o servidor abrindo a URL do servidor em seu navegador.
Como não especificamos nenhuma operação, apenas uma mensagem de falha é retornada ao navegador por nosso aplicativo.
Agora, tente adicionar o ?wsdl ao seu URL e você verá a seguinte saída -
Portanto, nosso aplicativo de servidor está funcionando conforme o esperado. Você pode usar o cliente SOAP, comoPostman descrito anteriormente para testar ainda mais seu serviço.
Na próxima seção, aprenderemos como escrever um cliente que usa nosso serviço.
Cliente em desenvolvimento
Escrever o cliente em um aplicativo CXF é tão trivial quanto escrever um servidor. Aqui está o código completo para o cliente -
//Client.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public final class Client {
private static final QName SERVICE_NAME
= new QName("http://helloworld.jaxws.cxf.tutorialspoint.com/",
"HelloWorld");
private static final QName PORT_NAME
= new QName("http://helloworld.jaxws.cxf.tutorialspoint.com/",
"HelloWorldPort");
private Client() {
}
public static void main(String[] args) throws Exception {
Service service = Service.create(SERVICE_NAME);
System.out.println("service created");
String endpointAddress = "http://localhost:9090/HelloServerPort";
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,
endpointAddress);
HelloWorld hw = service.getPort(HelloWorld.class);
System.out.println(hw.greetings("World"));
}
}
Aqui, usamos o CXF fornecido Serviceclasse para vincular ao serviço conhecido. Nós chamamos ocreate método no Serviceclasse para obter uma instância do serviço. Definimos a porta conhecida chamando oaddPort método no service instância.
Agora, estamos prontos para consumir o serviço, o que fazemos obtendo primeiro a interface do serviço chamando o getPort método no serviceinstância. Finalmente, chamamos nossogreetings método para imprimir a mensagem de saudação no console.
Agora, como você aprendeu os fundamentos do CXF usando a abordagem Apache CXF-First, você aprenderá como usar o CXF com a abordagem WSDL-First em nosso próximo capítulo.
O aplicativo CXF-POJO que você desenvolveu resulta em um acoplamento muito forte entre o cliente e o servidor. Fornecer acesso direto à interface de serviço também pode representar ameaças graves à segurança. Assim, normalmente é desejável o desacoplamento entre o cliente e o servidor, o que é obtido por meio de WSDL (Web Services Description Language).
Escrevemos a interface de serviço da web em um documento WSDL que é baseado em XML. Usaremos uma ferramenta para mapear este WSDL para interfaces Apache CXF que são então implementadas e usadas por nossos aplicativos cliente e servidor. Para fornecer desacoplamento, começar com um WSDL é a forma preferida. Para isso, você precisa primeiro aprender um novo idioma - WSDL. Escrever WSDL requer uma abordagem cuidadosa e seria melhor se você pudesse obter algum entendimento sobre isso antes de começar a trabalhar nele.
Nesta lição, começaremos definindo uma interface de serviço da web em um documento WSDL. Aprenderemos como usar o CXF para criar aplicativos de servidor e cliente começando com WSDL. Manteremos o aplicativo simples para manter o foco no uso do CXF. Depois que o aplicativo do servidor for criado, iremos publicá-lo em uma URL desejada usando uma classe CXF embutida.
Primeiro, vamos descrever o WSDL que vamos usar.
WSDL para HelloWorld
O serviço da web que vamos implementar terá um único método da web chamado greetings que aceita um stringparâmetro que contém o nome do usuário e retorna uma mensagem de string para o chamador após anexar uma mensagem de saudação ao nome do usuário. O wsdl completo é mostrado abaixo -
//Hello.wsdl
<?xml version = "1.0" encoding = "UTF-8"?>
<wsdl:definitions xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns = "http://helloworld.tutorialspoint.com/"
xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
name = "HelloWorld"
targetNamespace = "http://helloworld.tutorialspoint.com/">
<wsdl:types>
<xsd:schema attributeFormDefault = "unqualified"
elementFormDefault = "qualified"
targetNamespace = "http://helloworld.tutorialspoint.com/">
<xsd:element name = "greetings" type = "tns:greetings"/>
<xsd:complexType name = "greetings">
<xsd:sequence>
<xsd:element minOccurs = "0" name = "arg0" type = "xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name = "greetingsResponse"
type = "tns:greetingsResponse"/>
<xsd:complexType name = "greetingsResponse">
<xsd:sequence>
<xsd:element minOccurs = "0" name = "return" type = "xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name = "greetings">
<wsdl:part element = "tns:greetings" name = "parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name = "greetingsResponse">
<wsdl:part element = "tns:greetingsResponse" name = "parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name = "HelloWorldPortType">
<wsdl:operation name = "greetings">
<wsdl:input message = "tns:greetings" name = "greetings"> </wsdl:input>
<wsdl:output message = "tns:greetingsResponse" name = "greetingsResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name = "HelloWorldSoapBinding" type = "tns:HelloWorldPortType">
<soap:binding style = "document"
transport = "http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name = "greetings">
<soap:operation soapAction = "" style = "document"/>
<wsdl:input name = "greetings"></wsdl:input>
<wsdl:output name = "greetingsResponse">
<soap:body use = "literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name = "HelloWorldService">
<wsdl:port binding = "tns:HelloWorldSoapBinding" name = "HelloWorldPort">
<soap:address location = "http://localhost:9090/HelloServerPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Observe que escrever um wsdl sintaticamente correto sempre foi um desafio para os desenvolvedores; existem muitas ferramentas e editores online disponíveis para criar um wsdl. Esses editores pedem os nomes das mensagens que você deseja implementar, juntamente com os parâmetros que deseja passar em uma mensagem e o tipo de mensagem de retorno que deseja que seu aplicativo cliente receba. Se você conhece a sintaxe wsdl, pode codificar manualmente o documento inteiro ou usar um dos editores para criar o seu próprio.
No wsdl acima, definimos uma única mensagem chamada greetings. A mensagem é entregue ao serviço chamadoHelloWorldService que está funcionando em http://localhost:9090/HelloServerPort.
Com isso, passaremos agora ao desenvolvimento do servidor. Antes de desenvolver o servidor, precisamos gerar a interface Apache CXF para nosso serviço web. Isso deve ser feito a partir do wsdl fornecido. Para fazer isso, você usa uma ferramenta chamadawsdl2java.
O plugin wsdl2java
Como usaremos o maven para construir o projeto, você precisará adicionar o seguinte plugin ao pom.xml Arquivo.
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/hello.wsdl</wsdl>
<faultSerialVersionUID> 1 </faultSerialVersionUID>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Observe que especificamos a localização do wsdl arquivo como src/main/resources/Hello.wsdl. Você terá que se certificar de criar uma estrutura de diretório apropriada para o seu projeto e adicionar o mostrado anteriormentehello.wsdl arquivo para a pasta especificada.
o wsdl2javaplugin irá compilar este wsdl e criar classes Apache CXF em uma pasta pré-definida. A estrutura completa do projeto é mostrada aqui para sua referência imediata.
Agora, você está pronto para criar um servidor usando o wsdl2javaclasses geradas. As classes que wsdl2java criou são mostradas na figura abaixo -
Interface de serviço gerada
Na lista de classes geradas, você deve ter notado que uma delas é uma interface Apache CXF - esta é HelloWorldPortType.java. Examine este arquivo em seu editor de código. O conteúdo do arquivo é mostrado aqui para sua referência -
//HelloWorldPortType.java
package com.tutorialspoint.helloworld;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.3.0
* 2019-02-11T12:05:55.220+05:30
* Generated source version: 3.3.0
*
*/
@WebService(targetNamespace = "http://helloworld.tutorialspoint.com/",
name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {
@WebMethod
@RequestWrapper(localName = "greetings", targetNamespace =
"http://helloworld.tutorialspoint.com/", className =
"com.tutorialspoint.helloworld.Greetings")
@ResponseWrapper(localName = "greetingsResponse", targetNamespace =
"http://helloworld.tutorialspoint.com/", className =
"com.tutorialspoint.helloworld.GreetingsResponse")
@WebResult(name = "return", targetNamespace =
"http://helloworld.tutorialspoint.com/")
public java.lang.String greetings(
@WebParam(name = "arg0", targetNamespace =
"http://helloworld.tutorialspoint.com/")
java.lang.String arg0
);
}
Observe que a interface contém um método chamado greetings. Este era um tipo de mensagem em nosso wsdl. owsdl2javaferramenta adicionou este método à interface gerada. Agora, você pode entender que, quaisquer que sejam as mensagens gravadas em seu wsdl, um método correspondente seria gerado na interface.
Agora, sua tarefa seria implementar todos esses métodos correspondentes às várias mensagens que você definiu em seu wsdl. Observe que no exemplo anterior do Apache CXF-First, começamos com uma interface Apache CXF para nosso serviço da web. Nesse caso, a interface Apache CXF é criada a partir do wsdl.
Implementando a Interface de Serviço
A implementação da interface de serviço é trivial. A implementação completa é mostrada na lista abaixo -
//HelloWorldImpl.java
package com.tutorialspoint.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {
@Override
public String greetings(String name) {
return ("hi " + name);
}
}
O código implementa o único método de interface chamado greetings. O método leva um parâmetro destring tipo, acrescenta uma mensagem "hi" a ele e retorna a string resultante para o chamador.
A seguir, escreveremos o aplicativo do servidor.
Servidor de Desenvolvimento
O desenvolvimento de aplicativos de servidor é mais uma vez trivial. Aqui, usaremos o CXF fornecidoEndpointclasse para publicar nosso serviço. Isso é feito nas duas linhas de código a seguir -
HelloWorldPortType implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature());
Primeiro, criamos um objeto de nossa classe de implementador de serviço - HelloWorldImpl. Então, passamos esta referência como um segundo parâmetro para opublishmétodo. O primeiro parâmetro é o endereço no qual o serviço é publicado - os clientes usariam essa URL para acessar o serviço. Toda a fonte do aplicativo de servidor é fornecida aqui -
//Server.java
package com.tutorialspoint.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
public static void main(String[] args) throws Exception {
HelloWorldPortType implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature());
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
Para construir esta classe de servidor, você precisará adicionar um perfil de construção em seu pom.xml. Isso é mostrado abaixo -
<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.helloworld.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>
Observe que o nome totalmente qualificado do Serverclasse é especificada na configuração. Além disso, a tag de dependência especifica que usaremos o servidor web jetty integrado para implantar nosso aplicativo de servidor.
Implantando Servidor
Finalmente, para implantar o aplicativo de servidor, você precisará fazer mais uma modificação em pom.xml para configurar seu aplicativo como um aplicativo da web. O código que você precisa adicionar ao seupom.xml é dado abaixo -
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>*.wsdl</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
Antes de implantar o aplicativo, você precisa adicionar mais dois arquivos ao seu projeto. Eles são mostrados na imagem abaixo -
Esses arquivos são arquivos padrão CXF que definem o mapeamento para CXFServlet. O código dentro doweb.xml arquivo é mostrado aqui para sua referência rápida -
//cxf-servlet.xml
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>cxf</display-name>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
No cxf-servlet.xmlvocê declara as propriedades do ponto de extremidade do seu serviço. Isso é mostrado no snippet de código abaixo -
<beans ...>
<jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
id="helloHTTP"
address = "http://localhost:9090/HelloServerPort"
serviceName = "helloworld:HelloServiceService"
endpointName = "helloworld:HelloServicePort">
</jaxws:endpoint>
</beans>
Aqui, definimos a id para nosso endpoint de serviço, o endereço no qual o serviço estará disponível, o nome do serviço e o nome do endpoint. Agora, você entende como seu serviço é roteado e processado por um servlet CXF.
O pom.xml final
o pom.xmlinclui mais algumas dependências. Em vez de descrever todas as dependências, incluímos a versão final de 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-wsdl</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>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>*.wsdl</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/Hello.wsdl</wsdl>
<faultSerialVersionUID>1</faultSerialVersionUID>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<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.helloworld.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.helloworld.Client
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<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-management</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-metrics</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf.xjc-utils</groupId>
<artifactId>cxf-xjc-runtime</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-logging</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-beta2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
Observe que também inclui um perfil para construir o cliente que aprenderemos em breve nas seções posteriores.
Executando o serviço HelloWorld
Agora você está pronto para executar o aplicativo da web. Na janela de comando, execute o script de construção usando o seguinte comando.
mvn clean install
Isso irá gerar as classes Apache CXF apropriadas de seu wsdl, compilar suas classes Apache CXF, implementar o servidor no servidor jetty integrado e executar seu aplicativo.
Você verá a seguinte mensagem no console -
INFO: Setting the server's publish address to be
http://localhost:9090/HelloServerPort
Server ready...
Como antes, você pode testar o servidor abrindo a URL do servidor em seu navegador.
Como não especificamos nenhuma operação, apenas uma mensagem de falha é retornada ao navegador por nosso aplicativo. Agora, tente adicionar o?wsdl ao seu URL e você verá a seguinte saída -
Portanto, nosso aplicativo de servidor está funcionando conforme o esperado. Você pode usar o cliente SOAP, comoPostman descrito anteriormente para testar ainda mais seu serviço.
A próxima parte deste tutorial é escrever um cliente que usa nosso serviço.
Cliente em desenvolvimento
Escrever o cliente em um aplicativo CXF é tão importante quanto escrever em um servidor. Aqui está o código completo para o cliente que consiste essencialmente em apenas três linhas, o resto das linhas apenas imprime as informações do serviço para o usuário.
//Client.java
package com.tutorialspoint.helloworld;
public class Client {
public static void main(String[] args) throws Exception {
//Create the service client with its default wsdlurl
HelloWorldService helloServiceService = new HelloWorldService();
System.out.println("service: " +
helloServiceService.getServiceName());
System.out.println("wsdl location: " +
helloServiceService.getWSDLDocumentLocation());
HelloWorldPortType helloService =
helloServiceService.getHelloWorldPort();
System.out.println(helloService.greetings
(System.getProperty("user.name")));
}
}
Aqui, simplesmente criamos uma instância do nosso serviço HelloWorldService, obtenha sua porta chamando getHelloWorldPort método, e então passar nosso greetingsmensagem para ele. Execute o cliente e você verá a seguinte saída -
service: {http://helloworld.tutorialspoint.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang
Até agora, você aprendeu como usar o CXF com as arquiteturas Apache CXF-First e WSDL-First. Na abordagem Apache CXF-First, você usou um POJO comServerFactoryBeanclasse de bibliotecas CXF para criar um servidor. Para criar um cliente que você usouClientProxyFactoryBeanclasse da biblioteca CXF. Na abordagem WSDL-First, você usouEndpointclasse para publicar o serviço na URL desejada e um implementador especificado. Agora você pode estender essas técnicas para integrar diferentes protocolos e transportes.
Antes de prosseguir neste capítulo, presumimos que você saiba como escrever um serviço da Web RESTful em Java. Vou mostrar como usar o CXF além desse JAX-RS (API Java para serviços da Web RESTful). 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 forma -
@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 ligando para 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 de criação 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 de CXF fornecem vários exemplos de como usar o CXF com JAX-RS. Os leitores interessados são incentivados a estudar essas amostras.
Conforme mencionado anteriormente, você pode usar CXF com transporte JMS. Nesse caso, o cliente enviará uma mensagem JMS a um Servidor de Mensagens conhecido. Nosso aplicativo de servidor está continuamente ouvindo o servidor de mensagens para as mensagens recebidas. Quando a mensagem chega, ele a processa, executa a solicitação do cliente e envia a resposta como outra mensagem ao cliente.
Como anteriormente, primeiro criaremos um aplicativo de servidor de amostra que fornece um método da web único chamado sayHi.
Criando Interface de Serviço
A interface de serviço para nosso HelloWorld serviço é mostrado aqui -
//HelloWorld.java
package com.tutorialspoint.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
@WebMethod
String sayHi(@WebParam(name = "name") String name);
}
Serviço de Implementação
A implementação da interface de serviço é definida da seguinte forma -
//HelloWorldImpl.java
package com.tutorialspoint.service.impl;
import javax.jws.WebService;
import com.tutorialspoint.service.HelloWorld;
@WebService
public class HelloWorldImpl implements HelloWorld {
@Override
public String sayHi(String name) {
return "Hello " + name;
}
}
A implementação simplesmente retorna uma mensagem de Olá ao usuário. Como você pode ver, a interface e sua implementação são semelhantes a todos os projetos anteriores neste tutorial que você estudou até agora.
Agora, vem o ponto mais importante que é criar um aplicativo de servidor que configure uma fila de mensagens e continue ouvindo as mensagens recebidas.
Criando Servidor
No aplicativo de servidor, primeiro criamos um JMS ponto final da seguinte forma -
private static final String JMS_ENDPOINT_URI =
"jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
+ "&jndiConnectionFactoryName=ConnectionFactory"
+ "&jndiInitialContextFactory"
+ "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+ "&jndiURL = tcp://localhost:61616";
Observe que configuramos uma fila em uma porta especificada que vive por um determinado período de tempo. Agora criamos um serviço de mensagens instanciandoorg.apache.activemq.broker.BrokerServiceclasse. Esta é uma classe de servidor paraActiveMQ servidor de mensagens.
BrokerService broker = new BrokerService();
Você pode usar qualquer outro servidor de mensagens de sua escolha, exceto ActiveMQ. Agora, conectamos este servidor a um URI desejado.
broker.addConnector("tcp://localhost:61616");
Configuramos o diretório para o armazenamento de dados das mensagens recebidas -
broker.setDataDirectory("target/activemq-data");
Finalmente, iniciamos o servidor usando o método start -
broker.start();
Em seguida, criamos uma instância do nosso bean de serviço HelloWorld usando a classe de bean de fábrica do servidor, conforme usado em nosso aplicativo POJO anterior -
Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);
Em seguida, configuramos o endpoint JMS na fábrica para que a fábrica continue ouvindo as mensagens recebidas -
factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);
Finalmente, configuramos a classe do implementador na fábrica e começamos a executá-la -
factory.setServiceBean(implementor);
factory.create();
Neste ponto, seu servidor está instalado e funcionando. Observe que, como usamos a classe do bean de fábrica como no aplicativo POJO, a necessidade do CXFServlet e do arquivo web.xml não é necessária.
O código completo do aplicativo do servidor é mostrado aqui -
//ServerJMS.java
package com.tutorialspoint.server;
import java.util.Collections;
import org.apache.cxf.ext.logging.LoggingFeature;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;
import com.tutorialspoint.service.HelloWorld;
import com.tutorialspoint.service.impl.HelloWorldImpl;
import org.apache.activemq.broker.BrokerService;
public final class ServerJMS {
private static final String JMS_ENDPOINT_URI =
"jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
+ "&jndiConnectionFactoryName=ConnectionFactory"
+ "&jndiInitialContextFactory"
+ "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+ "&jndiURL = tcp://localhost:61616";
public static void main(String[] args) throws Exception {
BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61616");
broker.setDataDirectory("target/activemq-data");
broker.start();
Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);
factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);
factory.setServiceBean(implementor);
factory.setFeatures(Collections.singletonList(new LoggingFeature()));
factory.create();
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
Adicionando Dependências
O aplicativo de servidor que criamos usa o servidor de mensagens ActiveMQ. Portanto, você precisará adicionar mais algumas dependências ao seu projeto. O arquivo pom.xml completo é mostrado aqui para você entender as dependências adicionais necessárias.
<?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-jms</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.server.ServerJMS
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</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.client.ClientJMS
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
<version>5.15.8</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-kahadb-store</artifactId>
<version>5.15.8</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-jms</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-logging</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>
</dependencies>
</project>
Servidor em execução
Para iniciar a execução do servidor, como nos casos anteriores, digite o seguinte comando na janela de comando -
mvn -Pserver
Isso iniciará o servidor de mensagens ActiveMQ, configurará a fila de mensagens e criará um bean de fábrica que continua escutando esta fila.
Nossa próxima tarefa é criar um aplicativo cliente.
Criando Cliente
No aplicativo cliente, primeiro configuramos o terminal JMS igual ao usado no aplicativo servidor -
private static final String JMS_ENDPOINT_URI =
"jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
+ "&jndiConnectionFactoryName=ConnectionFactory"
+ "&jndiInitialContextFactory"
+ " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+ "&jndiURL = tcp://localhost:61616";
Criamos uma fábrica como no aplicativo POJO.
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
Definimos o URI do endpoint e a classe do implementador da seguinte forma -
factory.setTransportId (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress (JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);
Finalmente, chamamos o método de serviço e imprimimos sua saída resultante -
String reply = client.sayHi("TutorialsPoint");
System.out.println(reply);
O código completo do cliente é fornecido abaixo -
// ClientJMS.java
package com.tutorialspoint.client;
import com.tutorialspoint.service.HelloWorld;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;
public final class ClientJMS {
private static final String JMS_ENDPOINT_URI =
"jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
+ "&jndiConnectionFactoryName=ConnectionFactory"
+ "&jndiInitialContextFactory"
+ " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+ "&jndiURL = tcp://localhost:61616";
public static void main(String[] args) throws Exception {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);
String reply = client.sayHi("TutorialsPoint");
System.out.println(reply);
System.exit(0);
}
}
Apache CXF - Conclusão
O CXF fornece uma abordagem unificada para combinar vários protocolos e transportes da web que existem no mundo de hoje para a criação de aplicativos da web. Você aprendeu como começar com uma interface Java tradicional para criar um aplicativo da web que usa CXF. A seguir, você aprendeu como criar um aplicativo da web e seu cliente começando com WSDL.
O WSDL fornece uma representação XML de sua interface de serviço. Você usou a ferramenta wsdl2java para criar interfaces Java a partir de WSDL e, finalmente, escreveu o servidor e o cliente usando as interfaces criadas. O tutorial também apresentou brevemente o uso do CXF em seu aplicativo de serviço da Web RESTful. Por fim, também discutimos como o CXF pode ser usado com o JMS. Agora você pode consultar as amostras CXF para estudos adicionais.
Note - Todo o código-fonte do projeto pode ser baixado aqui.