Creación de Webservice SOAP mediante Anotaciones

Vamos a ver cuáles son los pasos a seguir para implementar un webservice SOAP utilizando la anotaciones que nos brinda la librería JAX-WS de Java. En el blog ya hemos explicado en algún post anterior cómo se creaba el esqueleto de un webservice SOAP, pero en el post actual vamos a ir un poco más allá y a tratar de explicar el uso de las anotaciones más importantes.

 

Dicho lo anterior, toca concretar un poco y procedemos a enumerar las herramientas y tecnologías que vamos a usar para la creación del webservice.

  • IDE Eclipse 
  • Java versión 8
  • Proyecto Maven
  • Servidor Tomcat
  • Librería JAX-WS

 

Creación de Webservice SOAP mediante Anotaciones

 

Dicho lo anterior, vamos a entrar en materia y comenzamos a enumerar los pasos necesarios para la creación de un webservice SOAP.

 

1º) Entramos en Eclipse y nos creamos un proyecto de tipo "Dynamic Web Project". Acto seguido, marcamos el proyecto y hacemos clic con el botón derecho. En el menú seleccionamos la opción CONFIGURE - CONVERT TO MAVEN PROJECT

En la ventana emergente "Maven POM" indicamos el nombre del ARTIFACT ID y del GROUP ID (esto es, del paquete raíz del proyecto, que en nuestro ejemplo será com.universo.soap). Pulsamos el botón FINISH.

Nos debería quedar un esqueleto de este tipo.



2º) Editamos el fichero pom.xml y le añadimos las propiedades de Java 8. En mi caso realmente no me hacían falta, pues ya las tenía por defecto, pero quizás vosotros sí las necesitéis en vuestro proyecto. A continuación, tenemos que añadir la librería JAXWS-RT, que es la que nos permitirá implementar el webservice de este ejemplo.

El fichero pom.xml debería quedar del siguiente modo:


<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.universo.soap</groupId>

  <artifactId>WebserviceSoapApp</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>war</packaging>

 

  <properties>

    <java.version>1.8</java.version>

    <maven.compiler.target>1.8</maven.compiler.target>

    <maven.compiler.source>1.8</maven.compiler.source>

  </properties>

 

  <dependencies>

       <dependency>

           <groupId>com.sun.xml.ws</groupId>

           <artifactId>jaxws-rt</artifactId>

           <version>2.3.2</version>

       </dependency>

  </dependencies>

 

  <build>

    <plugins>

      <plugin>

        <artifactId>maven-compiler-plugin</artifactId>

        <version>3.8.1</version>

        <configuration>

          <source>1.8</source>

          <target>1.8</target>

        </configuration>

      </plugin>

      <plugin>

        <artifactId>maven-war-plugin</artifactId>

        <version>3.2.3</version>

      </plugin>

    </plugins>

  </build>

</project>


3º) A continuación, seleccionamos el proyecto y seleccionamos la opción MAVEN - UPDATE PROJECT. En la ventana de "Update Maven Project" que nos saldrá a continuación, pulsamos el botón ACEPTAR. Eclipse procederá a descargar las librerías indicadas en las dependencias de nuestro pom.xml y las dejará asociadas a nuestros proyecto.

Las librerías de nuestro "Maven Dependencies" deberían quedar algo así:

 

Como se aprecia, ya se ha descargado la librería jaxws-rt-2.3.2.jar, que es la que nos permitirá implementar el webservice de nuestro ejemplo.


Implementación de las clases del Webservice SOAP


4º) Nos creamos la clase servicio HolaMundo.java dentro del paquete com.universo.soap.server. Esta clase es la que ejecutará la lógica del webservice.


// **************************************************

package com.universo.soap.server;

 

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

import javax.jws.soap.SOAPBinding.Style;

 

//http://localhost:8080/AnotacionSoapApp/ws/hola

@WebService(name="HolaMundoPortType",

       targetNamespace="http://server.soap.universo.com/",

       serviceName="HolaMundoService"

       endpointInterface="com.universo.soap.server.HolaMundo",

       portName="HolaMundoPortName")

@SOAPBinding(style = Style.RPC)

public class HolaMundo {

 

    @WebMethod

    @WebResult(name ="saludo")

    public String ciao(@WebParam(name ="nombre") String nombre) throws OperacionFault {

      // Validacion de parametro

      if (nombre == null || nombre.isEmpty()) {

            BaseException be = new BaseException("5000", "Error", "Nombre requerido");

            throw new OperacionFault("Nombre requerido", be);

      }

      // Respuesta

      String respuesta = String.format("Ciao %s", nombre);

        return respuesta;

    }

   

}

// **************************************************


5º) A continuación, nos creamos la clase OperacionFault.java. Esta clase es la que gestionará los Fault generados por el webservice.


// **************************************************

package com.universo.soap.server;

 

import javax.xml.ws.WebFault;

 

@WebFault(name="operationfault",

       targetNamespace = "http://server.soap.universo.com/",

       faultBean="com.universo.soap.server.BaseException")

public class OperacionFault extends Exception {

    /**

       *

       */

       private static final long serialVersionUID = 1L;

      

       private BaseException be;

 

       public OperacionFault(String mensaje, BaseException be) {

        super(mensaje);

       

        this.be = be;

    }

      

    public OperacionFault(String message, BaseException faultInfo, Throwable cause) {

        super(message, cause);

        this.be = be;

    }

      

    public BaseException getFaultInfo() {

        return this.be;

    }

   

}

// **************************************************

 

6º) Creamos la clase BaseException.java. Esta será la clase que definirá el contenido de las excepciones generadas por nuestro webservice.

 

// **************************************************

package com.universo.soap.server;

 

public class BaseException {

 

       private String errorID;

       private String errorType;

       private String errorDesc;

      

       public BaseException(String errorID, String errorType, String errorDesc) {

             this.errorID = errorID;

             this.errorType = errorType;

             this.errorDesc = errorDesc;

       }

      

       public String getErrorID() {

             return errorID;

       }

       public void setErrorID(String errorID) {

             this.errorID = errorID;

       }

       public String getErrorType() {

             return errorType;

       }

       public void setErrorType(String errorType) {

             this.errorType = errorType;

       }

       public String getErrorDesc() {

             return errorDesc;

       }

       public void setErrorDesc(String errorDesc) {

             this.errorDesc = errorDesc;

       }

      

}

// **************************************************

 

Configuración del Webservice SOAP

 

7º) A continuación, nos creamos el fichero de configuración sun-jaxws.xml dentro de la carpeta WEB-INF de nuestro proyecto. En este fichero hay que indicar la ubicación del servicio que se debe ejecutar y el patrón de la URL en la que quedará publicado.

El contenido del xml será el siguiente:


<?xml version="1.0" encoding="UTF-8"?>

<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">

  <endpoint

     name="HolaWebService"

     implementation="com.universo.soap.server.HolaMundo"

     url-pattern="/ws/hola"/>

</endpoints>

 

8º) Llegados a este punto, hay que modificar el fichero web.xml para indicar la configuración del JAXWSServlet. Habrá que incluir los apartados de <listener>, <servlet> y <servlet-mapping>.

El contenido modificado de web.xml debería quedar algo así.

 

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

id="WebApp_ID" version="4.0">

  <display-name>WebserviceSoapApp</display-name>

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.jsp</welcome-file>

  </welcome-file-list>

 

       <listener>

             <listener-class>

                    com.sun.xml.ws.transport.http.servlet.WSServletContextListener

             </listener-class>

       </listener>

 

       <servlet>

           <servlet-name>JAXWSServlet</servlet-name>

           <servlet-class>

               com.sun.xml.ws.transport.http.servlet.WSServlet

           </servlet-class>

       </servlet>

      

       <servlet-mapping>

           <servlet-name>JAXWSServlet</servlet-name>

           <url-pattern>/ws/*</url-pattern>

       </servlet-mapping>

      

</web-app>

 

9º) Tras la inclusión de todos los ficheros anteriores, el proyecto debería quedar estructurado de la siguiente forma.


 

Publicación del Webservice SOAP

 

10º) A continuación, procedemos a arrancar el Tomcat y añadimos nuestro proyecto al servidor. Si hemos creado correctamente la aplicación, no deberíamos tener problemas de arranque. 


jul 05, 2021 6:57:17 PM com.sun.xml.ws.server.MonitorBase createRoot

INFORMACIÓN: Metro monitoring rootname successfully set to: com.sun.metro:pp=/,type=WSEndpoint,name=/AnotacionSoapApp-HolaMundoService-HolaMundoPortName

jul 05, 2021 6:57:18 PM com.sun.xml.ws.transport.http.servlet.WSServletDelegate <init>

INFORMACIÓN: WSSERVLET14: inicializando el servlet de JAX-WS

jul 05, 2021 6:57:18 PM com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized

INFORMACIÓN: WSSERVLET12: inicializando el listener de contexto de JAX-WS

jul 05, 2021 6:57:18 PM com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized

INFORMACIÓN: WSSERVLET12: inicializando el listener de contexto de JAX-WS

jul 05, 2021 6:57:18 PM org.apache.coyote.AbstractProtocol start

INFORMACIÓN: Starting ProtocolHandler ["http-nio-8080"]

jul 05, 2021 6:57:18 PM org.apache.catalina.startup.Catalina start

INFORMACIÓN: Server startup in [7.421] milliseconds

 

11º) De esta forma, nuestro servicio ha debido quedar publicado correctamente. Ahora debemos tener en cuenta que "AnotacionSoapApp" es el nombre de nuestro proyecto y que "/ws/hola" es el patrón URL que hemos establecido en el fichero sun-jaxws.xml. Por tanto, el endpoint en el que debemos buscar nuestro servicio será el siguiente:

http://localhost:8080/AnotacionSoapApp/ws/hola


Si ponemos dicho endpoint en un navegador, nos aparecerá la siguiente información (recordad, siempre y cuando el servicio esté correctamente publicado):


 

Ahí tendremos la información acerca del endpoint del webservice.

Punto Final Información
Nombre de Servicio\:{http://server.soap.universo.com/}HolaMundoService
Nombre de Puerto\:{http://server.soap.universo.com/}HolaMundoPortName
Dirección\:http://localhost:8080/AnotacionSoapApp/ws/hola
WSDL\:http://localhost:8080/AnotacionSoapApp/ws/hola?wsdl
Clase de Implantación\:com.universo.soap.server.HolaMundo

 

12º) Adicionalmente, podemos ver el contrato WSDL (formato basado en XML) de nuestro servicio SOAP accediendo al siguiente endpoint:

http://localhost:8080/AnotacionSoapApp/ws/hola?wsdl


Si ponemos dicho endpoint en un navegador, se mostrará lo siguiente:


 

Como ya hemos explicado en el blog en ocasiones anteriores, el fichero WSDL es el que nos proporciona toda la información acerca de dónde está publicado nuestro servicio SOAP y con qué datos debe realizarse la invocación para obtener la respuesta esperada. Conocer el WSDL nos permite realizar su invocación desde cualquier proyecto externo.

El contenido de nuestro WSDL es el siguiente:

<definitions targetNamespace="http://server.soap.universo.com/" name="HolaMundoService">

<types>

<xsd:schema>

<xsd:import namespace="http://server.soap.universo.com/" schemaLocation="http://localhost:8080/AnotacionSoapApp/ws/hola?xsd=1"/>

</xsd:schema>

</types>

<message name="ciao">

<part name="nombre" type="xsd:string"/>

</message>

<message name="ciaoResponse">

<part name="saludo" type="xsd:string"/>

</message>

<message name="OperacionFault">

<part name="fault" element="tns:operationfault"/>

</message>

<portType name="HolaMundoPortType">

<operation name="ciao">

<input wsam:Action="http://server.soap.universo.com/HolaMundoPortType/ciaoRequest" message="tns:ciao"/>

<output wsam:Action="http://server.soap.universo.com/HolaMundoPortType/ciaoResponse" message="tns:ciaoResponse"/>

<fault message="tns:OperacionFault" name="OperacionFault" wsam:Action="http://server.soap.universo.com/HolaMundoPortType/ciao/Fault/OperacionFault"/>

</operation>

</portType>

<binding name="HolaMundoPortNameBinding" type="tns:HolaMundoPortType">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>

<operation name="ciao">

<soap:operation soapAction=""/>

<input>

<soap:body use="literal" namespace="http://server.soap.universo.com/"/>

</input>

<output>

<soap:body use="literal" namespace="http://server.soap.universo.com/"/>

</output>

<fault name="OperacionFault">

<soap:fault name="OperacionFault" use="literal"/>

</fault>

</operation>

</binding>

<service name="HolaMundoService">

<port name="HolaMundoPortName" binding="tns:HolaMundoPortNameBinding">

<soap:address location="http://localhost:8080/AnotacionSoapApp/ws/hola"/>

</port>

</service>

</definitions>

 

Una vez que tenemos implementado el webservice en el lado del servidor, ahora nos tocaría desarrollar en el lado del cliente el servicio que debe proceder a consumirlo. Para ello, veremos que resultará imprescindible conocer la estructura de su WSDL. Pero eso ya queda para otro post, que será la parte complementaria del que hemos publicado hoy.

 

Pues nada, eso es todo lo que quería contar en relación con la creación de un Webservice donde se haga uso de diferentes anotaciones JAX-WS. En concreto, hemos visto en funcionamiento las anotaciones @WebService, @SOAPBinding y @WebFault, entre otras. Esto nos ayudará a tener más claro cuál es el alcance de cada una de ellas dentro de un servicio SOAP.

Saludos.

 

Comentarios

Entradas populares de este blog

Componentes y Ventanas de Java Swing

Creación de Webservice SOAP básico

Fichero standalone del Servidor JBoss EAP