Web Services con Java (JAX-WS)

ReflectionToStringBuilderLos Web Services cada vez son más indispensable a la hora de construir aplicaciones, debido a que ya casi cualquier aplicación empresarial, requiere integrarse o comunicarse con otra. Por este motivo Java ofrece la librería JAX-WS la cual es definida por la especificación JSR 224. La especificación remplace a la JAX-RCP, la cual era únicamente para llamadas a procedimientos remotos, lo cual es diferente a los Web Services.

 

Crear Web Services con Java es mucho más fácil de lo que pudiéramos creer, pues ya que tan solo es necesario anotar una clase, para que esta sea expuesta automáticamente como tal por medio del servidor de aplicaciones. Para demostrar esto, desarrollaremos un Servicio para consultar y crear Empleados.

 

Lo primero que tenemos que hacer, es crear una clase que queremos exponer como WebService, luego la tenemos que anotar con @WebService :

@WebService(serviceName = "EmployeeService", targetNamespace = "http://xmlns.oscarblancarte.com/services/v1/EmployeeService")
public class EmployeeServiceImpl

Las propiedades utilizadas son las siguientes:

  • serviceName: Nombre del servicio, que será utilizado para crear la URL del endpoint.
  • targetNamespace: Define el Namespace del servicio.

 

Basta decir que las propiedades serviceName  y targetNamespace  son opcionales, ya que, de no colocarlas, serán asignadas de forma automática, tomando el nombre de la clase y el paquete en que se encuentra respectivamente.

 

En segundo lugar, es necesario crear los métodos que serán expuestos como las operaciones del WebService, estos métodos, deben de ser anotados con @WebMethod , veamos cómo quedaría una clase WebService terminada:

package com.osb.jax.ws.services.interfaces;

import com.osb.jax.ws.services.types.Employee;
import java.util.*;
import javax.jws.*;

/**
 * @author Oscar Blancarte
 */
@WebService(serviceName = "EmployeeService", targetNamespace = "http://xmlns.oscarblancarte.com/services/v1/EmployeeService")
public class EmployeeServiceImpl {
    
    private static final List<Employee> EMPLOYEES = new ArrayList<>();
    
    @WebMethod
    @WebResult(name = "employee")
    public List<Employee> getEmployeeList(){
        return EMPLOYEES;
    }
    
    @WebMethod
    public boolean createEmployee(@WebParam(name = "employee") Employee employee){
        EMPLOYEES.add(employee);
        return true;
    }
}

 

La anotación @WebParam  es utilizado para personalizar el nombre del parámetro en el WSDL.

 

La definición de la clase Employee es la siguiente:

package com.osb.jax.ws.services.types;


/**
 * @author Oscar Blancarte
 */
public class Employee {
    
    private Long id;
    private String name;

    public Employee() {
    }
    
    public Employee(Long id, String name) {
        this.id = id;
        this.name = 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;
    }
    
    
}

 

Finalmente, solo serán necesario deployar en el servidor de aplicaciones nuestro proyecto, en este caso, estamos utilizando Wildfly 9, pero podrías utilizar cualquier servidor que sea de tu preferencia. Una vez deployado, podrás ver el servicio en la URL: http://localhost:8080/JAX-WS-1.0-SNAPSHOT/EmployeeService?wsdl.

 

Podemos probar el servicio con SOAP-UI para ver el servicio y las dos operaciones:

Web Services con Java

 

Observemos que tenemos dos operaciones:

  • createEmployee: nos permite crear un nuevo Empleado
  • getEmployeeList: obtener un listado de todos los Empleados registrados.

 

Primeo ejecutaremos el método createEmployee:

Web Services con Java

Con este paso, ya habremos creado un nuevo Empleado llamado Oscar Blancarte.

 

El segundo paso, será consultar los empleados con el método getEmployeeList:

Web Services con Java

 

Como vemos, crear Servicios Web es tan simple como anotar una simple clase y desplegarla en nuestro servidor de aplicaciones.

 

 

50 thoughts to “Web Services con Java (JAX-WS)”

  1. Hola me encanto tu articulo oye tengo una duda ojala me pudieras ayudar, soy nuevo en java y creé un servicio web utilizando net beans y tengo algunas clases con metodos para hacer algunas operaciones y esos metodos me regresan parametros por lo general tipo cadena en su mayoria el problema es que en algunos metodos creo algunos objetos para ejecutar metodos de otras clases pero el servicio web no hace nada es decir envio el parametro (texto ) recibido del cliente y se va hacia los metodos y no hace nada no me da ningun resultado
    solo se ejcuta el servicio pero no hace nada y ya lo estuve revisando y si funciona correctamente hasta que escribo la instruccion para crear un objeto.

    1. Hola Charly, tu pregunta es complicada de responder, pues probablemente sea un escenario muy concreto de tu desarrollo, pues en teoría, esto que comentas no debería tener un impacto sobre tu desarrollo.

  2. Hola excelente tu post me ayudó bastante porque estoy haciendo un service web para una empresa de impuestos.

    Ahora mis dudas son:

    Como puedo arrojar una excepción si un @WebParam está nulo o no tiene la información esperada, además que esos @WebParam aparezca en el wsdl de la aplicación cómo parámetros obligatorios.

    Tengo que implementar seguridad usando , donde lo colocaría para que si el usuario no existe o no sea válido no llame a un webservice.

    Gracias

    1. Hola Jairo, gracias por tu comentario.

      Con respecto al primer punto que mencionas, para marcar un campo como obligatorio, deberás usar las anotaciones de JAXB, la cual es un API especial para controlar la forma en que un Objeto se convierte en XML y como el XML se convierte en objetos. Internamente Java usa JAXB para convertir el request en un objeto Java, de la misma forma, usa JAXB para convertir el objeto de respuesta en un XML, lo que tienes que hacer es darle una revisada a la documentación de esta API, como resumen te podría decir que uses la anotación @XmlElement(name = "xxx", required = true) sobre el elemento que quieres marcar como requerido, donde el atributo required le indica a JAXB que el campo deberá ser obligatorio, y por consecuencia, el WSLD lo debería de marcar como tal.
      Con respecto a la validacón, hay varias formas, podrías validar el input contra el Schema, validar manualmente cada campo mediante condiciones, podrías usar el API de Bean Validator, etc, en realidad hay varias formas, todo dependerá de que tan sofisticado quieres que sean tus validaciones y claro el tiempo que tengas para implementarlas.

      Con respecto a lo de la seguridad, creo que no terminaste la oración, por que dice “Tengo que implementar seguridad usando”, pero no dices que estás usando.

      1. Hola gracias por responder.

        Se borró la parte que describía la autenticación que debe usar UsernameToken (username y password),

        leere la parte del @XmlElement, tienes algún libro que describa con facilidad y ejemplos de uso de las anotaciones?

        Saludos.

        1. lo de la autenticación es algo largo para explicarlo aquí, pero te puedo recomendar la siguiente liga, en donde lo explican muy bien: https://java.globinch.com/enterprise-java/web-services/jax-ws/secure-metro-jax-ws-usernametoken-web-service-signature-encryption/

          Con respecto al libro sobre JAXB, existen libros que lo cubren pero no es el tema central, mi recomendación es que busques en google documentación, esta es un API bastante fácil de aprender, sobre todo si lo necesitas para realizar algunas anotaciones simples.

          Como un tema adicional, te puedo recomendar mi libro de Aplicaciones reactivas con React, NodeJS & MongoDB, en el explico como crear un API REST con NodeJS y te enseño a usar la autenticación por medio de JSON Web Tokens (JWT), ademas de que aprenderás React y MongoDB, que son tecnologías altamente demandadas y pagas hoy en día por si estas interesado.

  3. Sumamente simple y la manera más fácil de construir un Web Services, sin ccomplicarse con tantos frameworks. Claro que depende bastante del proyecto. MUCHAS GRACIAS camarada. 🙂

    1. Hola Andres, por desgracia no conozco manuales en español, lo que sí, es que te puedo recomendar el libro “Java Web Services – Up and running”, yo lo compre hace unos años, pero está muy bueno, explica todo lo referente a la construcción de servicios con Java, el único problema es que está en Ingles.

      saludos.

  4. Debo Felicitarte, desde hace días estoy buscando como utilizar el JAX-WS, he visto muchos tutoriales y ninguno explica claramente que debe ir dentro del Web Service y lo explicaste de maravilla con el ejemplo. Me funcionó con tu ejemplo.
    Para hacer el cliente debo exportar el wsdl? y hacer un main para probarlo es así?
    Saludos y gracias

    1. Hola Andrea, el WSDL se genera en automático, solo agrega ?wsdl al final de la url del servicio. Para crear un cliente basado en un servicio existente te puedes apoyar del IDE, siempre tienen herramientas para crearlos, de otro modo, puedes utilizar la herramienta WSGEN que ya viene incluida en el JDK, piedes googlerar para entender como utilizarla

  5. Buenas, queria hacer una consulta en particual. Tengo desarrollado un conjunto de agentes inteligenten con la librearia JADE, realizado en IDE Netbeans. Mi consulta consiste en, ¿cómo puedo implementar estos agentes en un web service?, para que luego, pueda ser utilizado por medio de una aplicación móvil, desarrollado con Android. Espero tu respuesta, muy buena publicación.

    1. Hola, yo no implementaría estos Agentes como WebServices, en su lugar, crearía una capa de servicios que envuelva lo que ya tienes, por ejemplo, puedes crear un proyecto aparte que exponga únicamente los servicios y estos se conecten a tus agentes. De esta forma, no impactas a tus agentes y puedes exponerlo por internet 🙂

      1. Oscar buenas noches, no estaría entendiendo lo que es la unificación de los servicios con los agentes, dado que los agentes funcionan en tiempo real, son asíncronos. Nose como puedo hacer que los agentes tomen esos datos que provienen de la web a un agente. Si oodrias proporcionarme una orientación de cómo seria te estaría agradecido, desde ya muchas gracias. Te dejo mi mail para estar en contactos.
        Gracias por haber contestado.

        1. Hola Oscar, lo que me comentas no me hace mucho sentido, pues el nombre del prefijo no debería de afectar la forma en que consumes el servicio, lo único que podría afectarte en tal caso, es que el namespace asociado al prefijo fuera diferente al esperado, lo cual no creo, pues el Envolope es auto generado por el API de JAX-WS.

          Ahora bien, si aun así quieres editarlo, te podrías presentar ante dos escenarios, invocar el servicio por medio de las clases Bindings (Auto generados por JAX-WS), o invocar los servicio por medio de bajo nivel.
          En el primer caso, no podrás hacer nada, pues JAX-WS se encarga de generar el envoltorio (Envelope), por lo que lo único que podrías afectar es el payload. En el otro caso, tendrás que sobre escribir los namespace con el API de JAXB. No recuerdo los detalles de implementación de JAXB para hacer esto, por lo que te sugiero que te des una vuelta por Google.

          Espero que esto puedo ayudarte.

          1. Te explico mi problema, el request que espero es el siguiente:

            string
            boolean

            Y el request que se genera en mi WS es este:

            ?
            ?

            Por lo que me dices, la petición no ella a mi WS debido a que me llega xmlns:soap y yo espero xmlns:temp, ¿como puedo modificar esa parte?, para yo esperar el xmlns:soap.

            Saludos.

          2. Hola Oscar, en el comentario anterior te explique los dos casos que se te podrían presentar, y te comenté que no recuerdo los detalles de implementación, y realmente no tengo tiempo para adentrarme a analizarlos para darte la respuesta definitiva, con las pistas que te dí, deberías de poder buscar en google una solución al problema.

            Lamento no poder hacer nada más, pero realmente no tengo tiempo para analizar detalladamente tu error.
            saludos.

  6. Hola Óscar,
    Primero Brother agradecer por compartir de manera resumida los temas, se que aprender lleva mucho tiempo y explicarlo de manera resumida es muy amable de tu parte.
    Todo bien respecto al tema quería preguntarte un poco más sobre el deployed, si tienes alguna entrada en el blog que explique el proceso en wildfly o alguna pista para consultarlo en Google.
    Gracias

    1. Hola Erick, no tengo ningún artículo sobre como desplegar en Wildfly, pero es realmente muy facil, puedes usar un IDE como Eclipse o Netbeans y agregar el servidor directamente sobre el IDE, cuando le des RUN al proyecto este se encargará de realizar el deploy de forma automática, la otra alternativa es crear el EAR o el WAR y copiarlos en la carpeta /stanalone/deploy y listo, se delegará de forma automática, claro, tienes que revisar si no salen error el deplegar para que puedas ver tu app corriendo.
      saludos

    1. Hola Richard, en los webservices todo es XML, no se comprendo tu pregunta, quizás lo que quieres decir es que un campo del XML debe de contener otro XML, en tal caso puede hacer dos cosas, definir el campo como Any Type y agregar el XML allí o puedes crear un campo CDATA, donde puede agregar libremente el contenido que sea dentro de el.

      saludos.

      1. Gracias por responder

        necesito crear un web service que reciba informacion de una camara de seguridad, el fabricante informa que esto es lo que envia la camara

        POST /CynthiaTest HTTP/1.1
        Content Type: application/xml; charset=”UTF 8″
        Content Length:743
        Connection: Close
        Host:10.5.2.101

        10.33.3.200</
        HTTP
        a4:14:37:5a:9a:65</
        1</
        2017 07 26T17:31:59+08:00
        449</
        PeopleCounting</
        active</
        peopleCounting alarm
        Camera 01

        realTime</statisticalMethods

        2017 07 26T17:31:59+08:00

        1603<enter/
        1164<exit/
        25<pass/

        solo necesito almacenar el “time” “enter” y “exit

        gracias por tu apoyo
        saludos

        1. este es el xml que envia la camara, no se por que en el post anterior no quedo bien

          saludos

          POST /CynthiaTest HTTP/1.1
          Content Type: application/xml; charset=”UTF 8″
          Content Length:743
          Connection: Close
          Host:10.5.2.101

          10.33.3.200
          HTTP
          a4:14:37:5a:9a:65
          1
          2017 07 26T17:31:59+08:00
          449
          PeopleCounting
          active
          peopleCounting alarm
          Camera 01

          realTime</statisticalMethods

          2017 07 26T17:31:59+08:00

          1603
          1164
          25

          1. hola Richard, lo que veo es que no tiene ni idea de como consumir un WebService, por lo que no puedo responderte todo eso en una sola respuesta, mi recomendación es que busques una guia más completa del tema para que puedas resolver muchas de las dudas que tienes. por mi parte te podría decir que lo que quieres hacer es fácil, pero no es algo que pueda responderte por aquí, por que sería explicarte como funcionan los webservices, como recuperas el datos, etc.

  7. hola muy buen articulo, una pregunta a a la parte que creas un cliente o ves que clientes estan almacenados, a ese proceso se le puede llamar “consumir el servicio WEB”?

        1. Hola Christian, no recuerdo si es el 9090, tendrías que entrar a ver la documentación o revisar el archivo stanalone.xml que está en la ruta /stanalone/config, por otra parte, por default no tiene user admin, lo tienes que crear con un script llamado users.sh que está en la carpeta /bin. La verdad yo pocas veces he necesitado entrar a la consola, todo lo configuro desde los XML de configuración, además, la consola que trae e está muy precaria, casi no sirve para nada.

  8. hola buen articulo, una pregunta yo cree un servicio web de tipo post el cual ingresa datos a la base pero tengo un problema y es que al consumir el servicio desde dos clientes al mismo tiempo toma solo una petición y la otra no la ejecuta pero igual devuelve true como si hubiera guardado los dos registros

    1. Hola Kevin, la verdad es complicado decirte a ciencia cierta que puede estar pasando sin ver el código, pero te podría decir que comiences analizando las transacciones, quizás, no las estás cerrando correctamente.

      saludos.

  9. Hola. soy nueva en lo q es web services y no habia encontrado ningun articulo tan claro y excelente como este, muchisimas gracias por compartirlo!
    solo tengo una duda, si quisiera consultar un empleado por su id o su nombre, sin que desplegue tooda la lista, como podria hacer?

    Muchas gracias de nuevo por compratir tus conocimientos

      1. Muchas gracias por responderme! Pero tengo un problema de universidad que dice….
        Crear un servicio web el cual recibe un número de ID y devuelve una estructura XML que corresponde a la información de un cliente.
        Además debe crear un cliente para ese servicio web el cual debe enviar un ID ingresado y mostrar el XML que recibió como respuesta.
        El servicio web debe ser de tipo SOAP de preferencia, se puede usar la librería JAVAX-WS, Axis2 u otras que conozca el estudiante.
        Solo se evalúa el dominio de los servicios web SOAP, no se solicita creación ni conexión a bases de datos de ningún tipo.

        Por eso pregunto, no se si yo he entendido mal el ejercicio o si se podrà hacer eso o en definitiva se debe usar conexion a base de datos?

        Gracias por tu tiempo.

        1. Hola Grace, el problema dice que no es necesario conectarte a la base de datos, por lo que podrías inicializar una Lista con datos pre-cargados, y así cuando te mande el ID, solo buscas el objecto por medio de su ID.

  10. Hola, interesante articulo

    consulta, descargue jaxws-rt-2.2.8 pero no me queda claro en que carpeta dentro de lib debo dejarla dentro de mi proyecto java para que me la acepte.

    Saludos.

    1. Por eso mismo utilizo Maven, para no preocuparme por los Jar, en tu caso, la carpeta pueda ser la quie quieres, lo importante es que lo agregues al classpath, para eso tienes que ir a las propiedades del proyecto y agregar ese Jar al classpath

  11. Tengo un proyecto ya echo, pero necesito agregar la funcionalidad para recibir datos desde un sistema externo a través de SOAP, aparte de lo que comentas aquí se debe agregar algo al POM? o configurar algo más?, ya hice lo que comentaste y no me funciona. Gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *