Apache CXF - Guía rápida

En el entorno actual, puede crear una aplicación de servicio web utilizando varias opciones. Puede utilizar uno o más de los varios protocolos estándar y ampliamente aceptados para la comunicación. Por ejemplo , SOAP , XML / HTTP, RESTful HTTP y CORBA (Arquitectura de agente de solicitud de objeto común, que era muy popular en la antigüedad, pero que ahora no se usa con tanta frecuencia.

También tiene la opción de diferentes transportes como HTTP, JMS , JBI y la opción de API de front-end como JAX-RS y JAX-WS . Al tener tantas opciones para el desarrollo de servicios web, existe la necesidad de un marco de servicios de código abierto para unir todas las opciones mencionadas anteriormente y eso es lo que hace Apache CXF .

En este tutorial, aprenderá cómo usar CXF para crear tanto un servicio web como un cliente que consume el servicio, usando una o más de las opciones que hemos enumerado anteriormente. Este tutorial lo guiará a través del desarrollo completo del código tanto para el servidor como para el cliente. Como cada aplicación puede usar solo una de las opciones de cada categoría, a saber, frontend, transporte y protocolo, considerando todas las permutaciones y combinaciones de estos tres, el número de aplicaciones será exorbitantemente alto.

Este tutorial analiza el desarrollo de los siguientes proyectos en detalle:

  • CXF con objetos antiguos simples de Apache CXF (POJO)

  • CXF con JAX-WS

  • CXF con WSDL

  • CXF con JAX-RS

  • CXF con JMS

Para simplificarlo, hemos utilizado maven con su interfaz de línea de comandos. Puede usar su IDE preferido para crear un proyecto maven.

En el próximo capítulo, comencemos con el primero.

En este capítulo, aprenderá a desarrollar una aplicación web sencilla que envíe un mensaje de saludo al usuario. Un proyecto de servicio web utiliza el modelo WSDL . El CXF le permite ocultar este modelo WSDL proporcionando una interfaz simple para mapear las API de Apache CXF al WSDL subyacente.

En este proyecto más simple, la interfaz del servicio web se expondrá directamente al cliente y el cliente utilizará las API nativas de Apache CXF para llamar al servicio web.

Primero, crearemos un servicio web. Cada servicio tiene una interfaz que está expuesta al cliente. Podemos escribir esta interfaz como una interfaz Apache CXF simple o como un documento WSDL. En este enfoque de Apache CXF-First, expondremos nuestro servicio a través de una interfaz Apache CXF.

Desarrollo de servicio web

El servicio que vamos a crear en la web tendrá un único método web llamado greetings. El método toma unstringtipo argumento en el que enviaremos el nombre del usuario. El servicio enviará un mensaje de saludo a la persona que llama con el nombre de usuario recibido incluido en el mensaje.

Interfaz de servicio web

Para exponer la interfaz de nuestro servicio web, crearemos una interfaz Apache CXF de la siguiente manera:

//HelloWorld.java
package com.tutorialspoint.cxf.pojo;
public interface HelloWorld {
   String greetings(String text);
}

La interfaz tiene un solo método llamado greetings. El servidor implementará esta interfaz. En nuestra aplicación trivial, esta interfaz se expone directamente al cliente. Normalmente, en una aplicación de servicio web, utiliza WSDL para describir la interfaz del servicio web. En esta sencilla aplicación, proporcionaremos esta interfaz directa al desarrollador del cliente. El cliente entonces llamaría algreetingsmensaje en el objeto del servidor. Primero, creemos el servicio web.

Implementación de servicios web

los HelloWorld La interfaz está implementada en el HelloWorldImpl Clase Apache CXF como se muestra a continuación -

//HelloWorldImpl.java
package com.tutorialspoint.cxf.pojo;
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String greetings(String text) {
      return "Hi " + text;
   }
}

los greetings El método recibe un parámetro de string type, lo agrega a un mensaje de saludo y devuelve la cadena resultante a la persona que llama.

A continuación, escribimos la aplicación del servidor para alojar el HelloWorld Servicio.

Creando servidor

La aplicación del servidor consta de dos partes:

  • La primera parte crea una fábrica para nuestro servicio web y

  • La segunda parte escribe un main método para instanciarlo.

El servidor usa ServerFactoryBean clase proporcionada por las bibliotecas CXF para exponer nuestra HelloWorldinterfaz a clientes remotos. Por lo tanto, primero instanciamos elServerFactoryBean class y luego establecer sus diversas propiedades -

ServerFactoryBean factory = new ServerFactoryBean();

Configuramos la clase de servicio que se llamará llamando al setServiceClass método en el factory objeto -

factory.setServiceClass(HelloWorld.class);

Configuramos la URL para llamar a nuestro servicio llamando a la fábrica setAddressmétodo. Tenga en cuenta que el servicio se publicará en esta URL.

factory.setAddress("http://localhost:5000/Hello");

En este caso, el servicio se implementa en el servidor integrado y estará escuchando el puerto 5000. Puede optar por cualquier número de puerto de su elección.

Antes de crear la fábrica, debe informar a la fábrica sobre nuestra clase de implementación de servicio. Esto se hace llamando alsetServiceBean método en el factory objeto como se muestra aquí -

factory.setServiceBean(new HelloWorldImpl());

El bean de servicio se establece en la instancia de nuestra clase de implementación de servicio. Finalmente, creamos la fábrica llamando a sucreate método -

factory.create();

Ahora, como hemos desarrollado la fábrica para ejecutar nuestro servicio web, a continuación escribiremos un main método para instanciarlo y mantenerlo en ejecución durante algún tiempo.

Ahora, escribe un main método para instanciar el HelloServer clase de la siguiente manera -

public static void main(String[] args) throws Exception {
   new HelloServer();
   System.out.println("Listening on port 5000 ...");
}

Una vez instanciado, el HelloServerla clase seguirá funcionando indefinidamente. Para implementaciones de producción, definitivamente mantendrá su servidor funcionando para siempre. En la situación actual, terminaríamos el servidor después de un tiempo predeterminado de la siguiente manera:

Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);

El código completo para el HelloServer la clase se da a continuación -

//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);
   }
}

La aplicación de servidor que hemos creado utiliza ServerFactoryBeanclase de las bibliotecas CXF. Ahora debemos incluir estas bibliotecas en nuestro proyecto para compilar con éxito elHelloServerclase. UsaremosMaven para configurar las dependencias del proyecto.

Configuración del proyecto Maven

Para crear un proyecto Maven, escriba el siguiente comando en su ventana de línea de comandos. Tenga en cuenta que hemos probado esto en una máquina Mac. Para las instalaciones de Windows y Linux, las instrucciones pueden diferir en algunos lugares.

mvn archetype:generate

Cuando se le pregunte por las propiedades, ingrese los siguientes 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

Al completar el comando maven, encontrará la estructura de carpetas apropiada creada en su carpeta actual junto con el archivo pom.xml.

La estructura de directorios generada se muestra aquí:

Agregará las dependencias CXF en el pom.xmly también copie los archivos Apache CXF creados anteriormente en la carpeta apropiada de la estructura creada por maven. Para su referencia inmediata, hemos proporcionado a continuación el archivo pom.xml para el proyecto que creamos en nuestra 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>

El pom.xml anterior puede incluir dependencias adicionales que son irrelevantes para este proyecto, pero son necesarias para nuestro próximo proyecto en este tutorial. De todos modos, no hay ningún daño como tal en incluir dependencias adicionales.

Estructura de carpetas del proyecto

La estructura de la carpeta del proyecto en mi máquina después de colocar los archivos Apache CXF del servidor y del cliente se muestra a continuación para su referencia rápida:

Servidor en ejecución

Para construir el proyecto, use el siguiente comando en su ventana de línea de comandos:

mvn clean install

Puede iniciar el servidor usando el siguiente comando:

mvn -Pserver

Esto iniciará el servidor y verá el siguiente mensaje en la consola:

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 ...

Ahora, en la ventana de su navegador, especifique la URL de nuestro servicio publicado. Verá la siguiente salida:

Esto confirma que nuestro servicio se está ejecutando en el puerto especificado en un host local. Dado que no especificamos elgreetings mensaje en nuestra llamada, se devuelve un mensaje de error SOAP al navegador.

Puede seguir probando su servicio web utilizando un cliente SOAP de su elección. Aquí hemos utilizado Postman para probar nuestro servidor.

La salida es como se muestra aquí:

Observa eso SOAP Requestfue codificado a mano. Después de publicar la solicitud, el servidor envió unSOAP Response mensaje, que se ve en la parte inferior de la captura de pantalla.

A partir de esto, puede comprender que CXF mantiene el uso de protocolos SOAP tanto para la solicitud como para la respuesta al mismo tiempo que le brinda una vista unificada de una variedad de tecnologías web que existen en el mundo actual. Esto simplifica enormemente el desarrollo de aplicaciones web.

Nuestra siguiente tarea es crear un cliente que consumirá el servicio web que ha creado.

Crear cliente

En la aplicación del servidor HelloWorldes la interfaz que expone nuestro servicio web. El servicio web en sí solo proporciona un mensaje de bienvenida sencillo al cliente. Por lo general, la interfaz del servicio web se expone al mundo exterior mediante WSDL (Lenguaje de descripción de servicios web). En esta trivial aplicación, expondremos nuestro servicio web al cliente exponiendo directamente la interfaz del servicio y esa es laHelloWorld.class.

Para este propósito, CXF proporciona una clase de fábrica llamada ClientProxyFactoryBean que nos permite adjuntar a la interfaz deseada a la instancia de fábrica creada.

Primero, creamos una instancia de bean de fábrica de la siguiente manera:

ClientProxyFactoryBean factory = new ClientProxyFactoryBean();

Llamamos al setAddressen la instancia de bean de fábrica para establecer la URL mediante la cual se puede invocar nuestro servicio web. En nuestro caso, usaremos la URL utilizada al crear el servidor en nuestro paso anterior:

factory.setAddress("http://localhost:5000/Hello");

A continuación, llamamos al create método en el factory instancia para adjuntar nuestra interfaz de servicio HelloWorld.class lo.

HelloWorld helloServer = factory.create(HelloWorld.class);

Finalmente, llamamos al greetings método para invocar el servicio web remoto.

System.out.println(helloServer.greetings(System.getProperty("user.name")));

Esto imprimiría un mensaje de saludo en su consola.

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

//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 en ejecución

Asegúrese de que el servidor aún se esté ejecutando en su máquina. En caso de que se agote el tiempo de espera, reinicie el servidor con el siguiente comando:

mvn -Pserver

Verá el siguiente mensaje en la consola:

Listening on port 5000 ...

Ahora, antes de que se agote el tiempo de espera del servidor, que hemos establecido en 5 minutos, abra otra ventana de línea de comando e inicie el cliente con el siguiente comando:

mvn -Pclient

Verá un mensaje similar al siguiente en la línea de comando:

Hi tutorialspoint

Tenga en cuenta que tutorialspointes nuestro nombre de usuario. Recibirás un saludo con tu propio nombre.

En el próximo capítulo, aprenderemos cómo usar CXF en un proyecto JAX-WS (Apache CXF API para servicios web XML).

En esta aplicación JAX-WS, usaremos el primer enfoque de Apache CXF como la aplicación POJO anterior. Entonces, primero crearemos una interfaz para nuestro servicio web.

Declaración de interfaz de servicio

Como en el caso anterior, crearemos un servicio trivial que solo tiene un método de interfaz llamado saludos. El código para la interfaz de servicio se muestra a continuación:

//HelloWorld.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.jws.WebService;

@WebService
public interface HelloWorld {
   String greetings(String text);
}

Anotamos la interfaz con un @WebServiceetiqueta. A continuación, implementaremos esta interfaz.

Implementación de la interfaz web

La implementación de la interfaz web se muestra aquí:

//HelloWorldImpl.java
package com.tutorialspoint.cxf.jaxws.helloworld;
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String greetings(String name) {
      return ("hi " + name);
   }
}

El método de los saludos está anotado con @Overrideetiqueta. El método devuelve un mensaje de "hola" a la persona que llama.

A continuación, escribiremos el código para desarrollar el servidor.

Servidor de desarrollo

A diferencia de la aplicación POJO, ahora desacoplaremos la interfaz utilizando la clase Endpoint proporcionada por CXF para publicar nuestro servicio. Esto se hace en las siguientes dos líneas de código:

HelloWorld implementor = new HelloWorldImpl();
Endpoint.publish(
   "http://localhost:9090/HelloServerPort",
   implementor,
   new LoggingFeature()
);

El primer parámetro del método de publicación especifica la URL en la que nuestro servicio estará disponible para los clientes. El segundo parámetro especifica la clase de implementación de nuestro servicio. El código completo para el servidor se muestra a continuación:

//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 implementar nuestro servidor, deberá realizar algunas modificaciones más en su proyecto, como se indica a continuación.

Implementación del servidor

Finalmente, para implementar la aplicación del servidor, deberá realizar una modificación más en pom.xml para configurar su aplicación como una aplicación web. El código que necesita agregar a supom.xml se da a continuación -

<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 implementar la aplicación, debe agregar dos archivos más a su proyecto. Estos se muestran en la captura de pantalla a continuación:

Estos archivos son archivos estándar CXF que definen la asignación para CXFServlet. El código dentro delweb.xml El archivo se muestra aquí para su referencia 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>

En el cxf-servlet.xml,declara las propiedades para el punto final de su servicio. Esto se muestra en el fragmento de código a continuación:

<beans ...>
   <jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
      id = "helloHTTP"
      address = "http://localhost:9090/HelloServerPort"
      serviceName = "helloworld:HelloServiceService"
      endpointName = "helloworld:HelloServicePort">
   </jaxws:endpoint>
</beans>

Aquí definimos la identificación de nuestro punto final de servicio, la dirección en la que estará disponible el servicio, el nombre del servicio y el nombre del punto final. Ahora, aprendió cómo un servlet CXF enruta y procesa su servicio.

El pom.xml final

los pom.xmlincluye algunas dependencias más. En lugar de describir todas las dependencias, 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-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>

Tenga en cuenta que también incluye un perfil para compilar el cliente que aprenderemos en las secciones posteriores de este tutorial.

Ejecución del servicio HelloWorld

Ahora, está listo para ejecutar la aplicación web. En la ventana de comandos, ejecute el script de compilación con el siguiente comando.

mvn clean install
mvn -Pserver

Verá el siguiente mensaje en la consola:

INFO: Setting the server's publish address to be http://localhost:9090/HelloServerPort
Server ready…

Como antes, puede probar el servidor abriendo la URL del servidor en su navegador.

Como no especificamos ninguna operación, nuestra aplicación solo devuelve un mensaje de error al navegador.

Ahora, intente agregar el ?wsdl a su URL y verá el siguiente resultado:

Entonces, nuestra aplicación de servidor se está ejecutando como se esperaba. Puede utilizar el cliente SOAP comoPostman descrito anteriormente para probar más su servicio.

En la siguiente sección, aprenderemos cómo escribir un cliente que utiliza nuestro servicio.

Cliente en desarrollo

Escribir el cliente en una aplicación CXF es tan trivial como escribir un servidor. Aquí está el código completo para el 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"));
   }
}

Aquí, utilizamos el CXF suministrado Serviceclass para enlazar con el servicio conocido. Llamamos alcreate método en el Serviceclass para obtener una instancia del servicio. Configuramos el puerto conocido llamando aladdPort método en el service ejemplo.

Ahora, estamos listos para consumir el servicio, lo que hacemos obteniendo primero la interfaz del servicio llamando al getPort método en el serviceejemplo. Finalmente, llamamos a nuestrogreetings método para imprimir el mensaje de saludo en la consola.

Ahora, como ha aprendido los conceptos básicos de CXF utilizando el enfoque Apache CXF-First, ahora aprenderá cómo usar CXF con el enfoque WSDL-First en nuestro próximo capítulo.

La aplicación CXF-POJO que ha desarrollado da como resultado un acoplamiento muy estrecho entre el cliente y el servidor. Dar acceso directo a la interfaz de servicio también puede plantear graves amenazas a la seguridad. Por lo tanto, generalmente se desea el desacoplamiento entre el cliente y el servidor, lo que se logra utilizando WSDL (Lenguaje de descripción de servicios web).

Escribimos la interfaz del servicio web en un documento WSDL que está basado en XML. Usaremos una herramienta para mapear este WSDL a las interfaces Apache CXF que luego son implementadas y utilizadas por nuestras aplicaciones cliente y servidor. Para proporcionar desacoplamiento, comenzar con un WSDL es una forma preferida. Para ello, primero debe aprender un nuevo idioma: WSDL. Escribir WSDL necesita un enfoque cuidadoso y sería mejor si pudiera comprenderlo antes de comenzar a trabajar en él.

En esta lección, comenzaremos definiendo una interfaz de servicio web en un documento WSDL. Aprenderemos a usar CXF para crear aplicaciones tanto de servidor como de cliente comenzando con WSDL. Mantendremos la aplicación simple para mantener el enfoque en el uso de CXF. Una vez creada la aplicación del servidor, la publicaremos en la URL deseada utilizando una clase CXF incorporada.

Primero, describamos el WSDL que vamos a utilizar.

WSDL para HelloWorld

El servicio web que vamos a implementar tendrá un único método web llamado greetings que acepta un stringparámetro que contiene el nombre de usuario y devuelve un mensaje de cadena a la persona que llama después de agregar un mensaje de saludo al nombre de usuario. El wsdl completo se muestra a continuación:

//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>

Tenga en cuenta que escribir un wsdl sintácticamente correcto siempre ha sido un desafío para los desarrolladores; hay muchas herramientas y editores en línea disponibles para crear un wsdl. Estos editores solicitan los nombres de los mensajes que desea implementar junto con los parámetros que desea pasar en un mensaje y el tipo de mensaje de retorno que desea que reciba su aplicación cliente. Si conoce la sintaxis de wsdl, puede codificar manualmente todo el documento o usar uno de los editores para crear el suyo.

En el wsdl anterior, hemos definido un solo mensaje llamado greetings. El mensaje se entrega al servicio llamadoHelloWorldService que se está ejecutando en http://localhost:9090/HelloServerPort.

Con esto, ahora procederemos al desarrollo del servidor. Antes de desarrollar el servidor, necesitamos generar la interfaz Apache CXF para nuestro servicio web. Esto se debe hacer desde el wsdl dado. Para hacer esto, usa una herramienta llamadawsdl2java.

El complemento wsdl2java

Como usaremos maven para construir el proyecto, deberá agregar el siguiente complemento al pom.xml archivo.

<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>

Tenga en cuenta que especificamos la ubicación del wsdl archivar como src/main/resources/Hello.wsdl. Tendrá que asegurarse de crear una estructura de directorio adecuada para su proyecto y agregar lo que se muestra anteriormentehello.wsdl archivo a la carpeta especificada.

los wsdl2javaEl complemento compilará este wsdl y creará clases de Apache CXF en una carpeta predefinida. La estructura completa del proyecto se muestra aquí para su referencia inmediata.

Ahora, está listo para crear un servidor usando el wsdl2javaclases generadas. Las clases que ha creado wsdl2java se muestran en la siguiente figura:

Interfaz de servicio generada

En la lista de clases generadas, debe haber notado que una de ellas es una interfaz Apache CXF; esto es HelloWorldPortType.java. Examine este archivo en su editor de código. El contenido del archivo se muestra aquí para su referencia inmediata:

//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
   );
}

Tenga en cuenta que la interfaz contiene un método llamado greetings. Este fue un tipo de mensaje en nuestro wsdl. loswsdl2javaLa herramienta ha agregado este método a la interfaz generada. Ahora, puede comprender que cualquier mensaje que escriba en su wsdl, se generará un método correspondiente en la interfaz.

Ahora, su tarea sería implementar todos estos métodos correspondientes a los diversos mensajes que ha definido en su wsdl. Tenga en cuenta que en el ejemplo anterior de Apache CXF-First, comenzamos con una interfaz Apache CXF para nuestro servicio web. En este caso, la interfaz Apache CXF se crea a partir de wsdl.

Implementación de la interfaz de servicio

La implementación de la interfaz de servicio es trivial. La implementación completa se muestra en la lista a continuación:

//HelloWorldImpl.java
package com.tutorialspoint.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {
   @Override
   public String greetings(String name) {
      return ("hi " + name);
   }
}

El código implementa el método de interfaz único llamado greetings. El método toma un parámetro destring type, antepone un mensaje "hola" y devuelve la cadena resultante a la persona que llama.

A continuación, escribiremos la aplicación del servidor.

Servidor de desarrollo

Desarrollar una aplicación de servidor es una vez más trivial. Aquí, usaremos el CXF suministradoEndpointclase para publicar nuestro servicio. Esto se hace en las siguientes dos líneas de código:

HelloWorldPortType implementor = new HelloWorldImpl();
   Endpoint.publish("http://localhost:9090/HelloServerPort",
      implementor,
      new LoggingFeature());

Primero, creamos un objeto de nuestra clase de implementador de servicios: HelloWorldImpl. Luego, pasamos esta referencia como un segundo parámetro alpublishmétodo. El primer parámetro es la dirección en la que se publica el servicio; los clientes usarían esta URL para acceder al servicio. Aquí se proporciona la fuente completa de la aplicación del servidor:

//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 clase de servidor, necesitará agregar un perfil de compilación en su pom.xml. Esto se muestra a continuación:

<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>

Tenga en cuenta que el nombre completo del ServerLa clase se especifica en la configuración. Además, la etiqueta de dependencia especifica que usaremos el servidor web embarcadero integrado para implementar nuestra aplicación de servidor.

Implementación del servidor

Finalmente, para implementar la aplicación del servidor, deberá realizar una modificación más en pom.xml para configurar su aplicación como una aplicación web. El código que necesita agregar a supom.xml se da a continuación -

<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 implementar la aplicación, debe agregar dos archivos más a su proyecto. Estos se muestran en la captura de pantalla a continuación:

Estos archivos son archivos estándar CXF que definen la asignación para CXFServlet. El código dentro delweb.xml El archivo se muestra aquí para su referencia 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>

En el cxf-servlet.xmldeclara las propiedades para el punto final de su servicio. Esto se muestra en el fragmento de código a continuación:

<beans ...>
   <jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
      id="helloHTTP"
      address = "http://localhost:9090/HelloServerPort"
      serviceName = "helloworld:HelloServiceService"
      endpointName = "helloworld:HelloServicePort">
   </jaxws:endpoint>
</beans>

Aquí definimos la identificación de nuestro punto final de servicio, la dirección en la que estará disponible el servicio, el nombre del servicio y el nombre del punto final. Ahora, comprende cómo un servlet CXF enruta y procesa su servicio.

El pom.xml final

los pom.xmlincluye algunas dependencias más. En lugar de describir todas las dependencias, 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-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>

Tenga en cuenta que también incluye un perfil para crear clientes que pronto aprenderemos en las secciones posteriores.

Ejecución del servicio HelloWorld

Ahora, está listo para ejecutar la aplicación web. En la ventana de comandos, ejecute el script de compilación con el siguiente comando.

mvn clean install

Esto generará las clases Apache CXF apropiadas desde su wsdl, compilará sus clases Apache CXF, implementará el servidor en el servidor embarcadero integrado y ejecutará su aplicación.

Verá el siguiente mensaje en la consola:

INFO: Setting the server's publish address to be 
http://localhost:9090/HelloServerPort
Server ready...

Como antes, puede probar el servidor abriendo la URL del servidor en su navegador.

Como no especificamos ninguna operación, nuestra aplicación solo devuelve un mensaje de error al navegador. Ahora, intente agregar el?wsdl a su URL y verá el siguiente resultado:

Entonces, nuestra aplicación de servidor se está ejecutando como se esperaba. Puede utilizar el cliente SOAP comoPostman descrito anteriormente para probar más su servicio.

La siguiente parte de este tutorial es escribir un cliente que utilice nuestro servicio.

Cliente en desarrollo

Escribir el cliente en una aplicación CXF es tan importante como escribir un servidor. Aquí está el código completo para el cliente que esencialmente consta de solo tres líneas, el resto de las líneas solo imprime la información del servicio para el usuario.

//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")));
   }
}

Aquí, simplemente creamos una instancia de nuestro servicio. HelloWorldService, consigue su puerto llamando getHelloWorldPort método, y luego pasar nuestro greetingsmensaje para él. Ejecute el cliente y verá el siguiente resultado:

service: {http://helloworld.tutorialspoint.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang

Hasta ahora, ha aprendido a utilizar CXF con las arquitecturas Apache CXF-First y WSDL-First. En el enfoque Apache CXF-First, usó un POJO conServerFactoryBeanclass de las bibliotecas CXF para crear un servidor. Para crear un cliente que usasteClientProxyFactoryBeanclase de la biblioteca CXF. En el enfoque WSDL-First, usóEndpointclass para publicar el servicio en la URL deseada y un implementador especificado. Ahora puede ampliar estas técnicas para integrar diferentes protocolos y transportes.

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 sobre 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 siguiente 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()));

Establecemos 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 para 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 de 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.

Como se mencionó anteriormente, puede usar CXF con transporte JMS. En este caso, el cliente enviará un mensaje JMS a un servidor de mensajería conocido. Nuestra aplicación de servidor escucha continuamente el servidor de mensajería para los mensajes entrantes. Cuando llega el mensaje, procesa el mensaje, ejecuta la solicitud del cliente y envía la respuesta como otro mensaje al cliente.

Como antes, primero crearemos una aplicación de servidor de muestra que proporciona un método web singular llamado sayHi.

Crear interfaz de servicio

La interfaz de servicio para nuestro HelloWorld el servicio se muestra aquí -

//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);
}

Servicio de implementación

La implementación de la interfaz de servicio se define de la siguiente manera:

//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;
   }
}

La implementación simplemente devuelve un mensaje de saludo al usuario. Como puede ver, la interfaz y su implementación son similares a todos los proyectos anteriores en este tutorial que ha estudiado hasta ahora.

Ahora, viene el punto más importante que es crear una aplicación de servidor que configure una cola de mensajes y siga escuchando los mensajes entrantes.

Creando servidor

En la aplicación del servidor, primero creamos un JMS punto final de la siguiente manera:

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";

Tenga en cuenta que configuramos una cola en un puerto específico que vive durante un período de tiempo específico. Ahora creamos un servicio de mensajería instalandoorg.apache.activemq.broker.BrokerServiceclase. Esta es una clase de servidor paraActiveMQ servidor de mensajería.

BrokerService broker = new BrokerService();

Puede utilizar cualquier otro servidor de mensajería de su elección que no sea ActiveMQ. Ahora conectamos este servidor a un URI deseado.

broker.addConnector("tcp://localhost:61616");

Configuramos el directorio para el almacenamiento de datos de los mensajes entrantes -

broker.setDataDirectory("target/activemq-data");

Finalmente, iniciamos el servidor usando el método de inicio -

broker.start();

A continuación, creamos una instancia de nuestro bean de servicio HelloWorld usando la clase de bean de fábrica del servidor como se usó en nuestra aplicación POJO anterior -

Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);

A continuación, configuramos el punto final JMS en la fábrica para que la fábrica siga escuchando los mensajes entrantes:

factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);

Finalmente, configuramos la clase implementadora en la fábrica y comenzamos a ejecutarla -

factory.setServiceBean(implementor);
factory.create();

En este punto, su servidor está en funcionamiento. Tenga en cuenta que, dado que hemos utilizado la clase de bean de fábrica como en la aplicación POJO, no se requiere la necesidad de CXFServlet y el archivo web.xml.

Aquí se muestra el código completo de la aplicación del servidor:

//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);
   }
}

Agregar dependencias

La aplicación de servidor que hemos creado utiliza el servidor de mensajería ActiveMQ. Por lo tanto, deberá agregar algunas dependencias más a su proyecto. Aquí se muestra el archivo pom.xml completo para que comprenda las dependencias adicionales necesarias.

<?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 en ejecución

Para comenzar a ejecutar el servidor, como en los casos anteriores, escriba el siguiente comando en su ventana de comandos:

mvn -Pserver

Esto iniciará el servidor de mensajes ActiveMQ, configurará la cola de mensajería y creará un bean de fábrica que seguirá escuchando esta cola.

Nuestra siguiente tarea es crear una aplicación cliente.

Crear cliente

En la aplicación cliente, primero configuramos el punto final JMS igual que el utilizado en la aplicación del 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";

Creamos una fábrica como en la aplicación POJO.

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

Establecemos el URI del punto final y la clase de implementador de la siguiente manera:

factory.setTransportId (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress (JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);

Finalmente, llamamos al método de servicio e imprimimos su salida resultante:

String reply = client.sayHi("TutorialsPoint");
System.out.println(reply);

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

// 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 - Conclusión

CXF proporciona un enfoque unificado para mezclar y combinar varios protocolos y transportes web que existen en el mundo actual para crear aplicaciones web. Aprendió cómo comenzar con una interfaz Java tradicional para crear una aplicación web que use CXF. A continuación, aprendió cómo crear una aplicación web y su cliente comenzando con WSDL.

El WSDL proporciona una representación XML de su interfaz de servicio. Usó la herramienta wsdl2java para crear interfaces Java desde WSDL y finalmente escribió tanto el servidor como el cliente usando las interfaces creadas. El tutorial también le presentó brevemente el uso de CXF en su aplicación de servicio web RESTful. Finalmente, también discutimos cómo se puede usar CXF con JMS. Ahora puede consultar las muestras de CXF para un estudio más detallado.

Note - El código fuente del proyecto completo se puede descargar desde aquí.