Creando un API REST en Java (parte 1)

Creando un API REST en Java (parte 1)Sin lugar a duda, los servicios REST ya se han convertido en la principal tecnología para construir servicios, superando con creces a los servicios SOAP o comúnmente conocidos como Web Services. A pesar de que REST ya es visiblemente la tendencia en el desarrollo de servicios, sigue existiendo una gran discusión acerca de si SOAP es mejor que REST o al revés, sin embargo, no quiera tocar este tema ahora, pues no es el tema central de este artículo, para eso he creado el artículo “SOA vs REST” donde discutimos sobre estas dos tecnologías y sus ventajas y desventajas.

 

NOTA: Este artículo es parte de un tutorial completo para crear API REST con JAX-RS, si quieres ver el índice completo entra aquí.

 

Antes de comenzar, te cuento que puedes descargar el código completo en https://github.com/oscarjb1/blog-tutorial-jaxrs/tree/master/M%C3%A9todos%20HTTP/api

 

Configurando el proyecto

 

Dicho este, pasemos ahora si a implementar un API REST con Java, para esto, será indispensable crear un proyecto de tipo WEB en tu IDE favorito, en este caso, vamos a crear un “Dynamic web project” en Eclipse, para esto nos dirigimos a file -> new -> Other en el menú superior:

Seleccionamos la opción Dynamic web Project y presionamos Next para iniciar con la configuración de la aplicación:

Una vez aquí, escribimos “api” como nombre del proyecto y seleccionamos nuestro servidor de aplicaciones de preferencia, en nuestro caso, utilizamos Wildfly 11 pero podrías utilizar cualquier otro que tengas disponible. Finalmente, presionamos “Finish” para concluir con la creación del proyecto. El siguiente paso será convertir nuestro proyecto a un proyecto Maven, con la finalidad de administrar más fácilmente nuestras librerías. Para ello, nos posicionaremos sobre el proyecto creado y presionaremos “click derecho“ para abrir las opciones del proyecto, estando allí, nos dirigimos a configure -> convert to Maven Project, tras presionar esto, saldrá una ventana para configurar el proyecto, a lo que simplemente daremos finalizar.

Tras realizar los pasos anteriores deberás ver el proyecto tal y como se ve en la imagen anterior. Podrás observar una pequeña “M” en el ícono del proyecto, señal de que se trata de un proyecto Maven.

El siguiente paso es configurar las librerías de JavaEE y Wildfly con la finalidad de que estén disponibles en nuestro proyecto, por lo que tendremos que ir al archivo pom.xml y agregar las siguientes dos librerías:

 

Guardamos los cambios y tendremos que esperar un momento hasta que Eclipse descarga todas las dependencias necesarias, para esto, verás un indicador de progreso en la parte inferior derecha de Eclipse. Una vez que ha finalizado, estamos listos para empezar a desarrollar.

 

Iniciando el desarrollo

 

Lo primero que debemos de hacer para iniciar nuestra API REST es indicarle el Path base desde el cual estará respondiendo nuestra API. Este path corresponde a la URL a partir de la cual se expondrá nuestros servicios. Para lograr esto, será necesario crear una clase que extienda de “Application”, esta clase puede llamarse como sea y puede colocarse en cualquier paquete, lo único importante es que extienda de Application y defina la anotación @ApplicationPath. En nuestro caso crearemos la clase RestApplication en el package api.

 

 

Como podemos ver, hemos definido “/” como URL base, es decir que los servicios responderán a partir de la raíz del proyecto, pero tu podrías remplazarla por la URL base que más te guste, como por ejemplo “/api” o “/services”.

El siguiente paso será crear nuestro primer servicio, para lo cual deberemos crear una nueva clase, en este caso, crearemos la clase HelloWorldRest en el mismo paquete:

 

Como podrás observar, esta es una clase común y corriente pero que tiene algunas anotaciones, las cuales serán reconocidas por el servidor de aplicaciones para finalmente exponer el servicio, analicemos para que esta cada una de ellas.

La anotación @Path indica la URL en la cual responderá este servicio, cabe mencionar que esta anotación se puede poner a nivel de clase y método, en este caso, al estar a nivel de clase, afecta a todos los servicios que definamos, pero eso lo vamos a analizar más adelante.

Las siguientes dos anotaciones son para indicar que tipo de mensaje esperamos como entrada (consumes) y que tipo de mensaje vamos a responder (produces). En este caso, estamos indicando que esperamos JSON como entrada y que vamos a responder igualmente con JSON.

Finalmente, siguen los métodos, una clase puede tener más de un método, y cada método se puede exponer como un servicio independiente, sin embargo, en esta primera introducción empezaremos con uno. La anotación @GET le indica al servidor de aplicaciones que el método responde por el método GET únicamente. Adicional tenemos anotaciones para los demás métodos, como @POST, @PUT, @DELETE, etc. pero estos los estaremos analizando más adelante.

Podrás observar que el método responde con un tipo llamado Response, esta es una clase de utilidad que nos proporciona el API de JAX-RS para convertir fácilmente un objeto en un JSON en nuestro caso. Esta clase nos proporciona el método ok, el cual nos crea una respuesta con status 200, es decir, respuesta exitosa, la cual recibe el mensaje que queremos responder y el tipo de datos del mensaje, en nuestro caso JSON.

 

Probando nuestro Hello World

 

En este punto hemos terminado nuestro primer servicio, por lo que solo resta desplegarlo y probarlo. Para desplegarlo, basta con presionar el click derecho sobre el proyecto y presionar Run As -> Run on Server, presionar siguiente y finalizar.

Si la aplicación desplego correctamente, podremos probar el servicio en la URL http://localhost:8080/api-0.0.1-SNAPSHOT/helloworld, esta URL la podrás ejecutar directamente sobre el navegador:

En este punto te estarás preguntando como es que se generó esta URL, por lo que explico a continuación:

La URL se forma con la siguiente formula: <server_path>:<port>/<app_context>/<app_path>/<service_path>

La sección <server_path> y <port> corresponde al host del servidor y el puerto en el cual responde, esto corresponde a Wildfly.

La sección <app_context> corresponde a la URL base que nos asigna el servidor de aplicaciones cuando desplegamos.

La sección <app_path> fue la que definimos en la anotación @ApplicationPath. En nuestro caso, al definirla como “/” quiere decir que responderá a partir de la raíz del proyecto.

Finalmente, <service_path> corresponde a la URL definida en la anotación @Path, la cual se definió como “helloworld”.

 

Conclusiones

Hasta este punto hemos aprendido a crear un proyecto web y configurarlo para que responda a nuestras solicitudes como un API REST, por lo que en la siguiente sección de esta guía aprenderemos a utilizar los demás métodos (POST, DELETE, PUT) y aprenderemos a configurar nuestras URL para responder a URL más complejas, por lo que te invito a que te suscribas a mi blog para hacerte llegar las actualizaciones.

 

 

29 thoughts to “Creando un API REST en Java (parte 1)”

  1. Esta bueno el artículo …, la gente debe analizar que en si los servicios web basados en SOAP y/ basados en REST, como parte de una arquitectura son buenos. Así mismo, diferenciar los enfoques que se tengan considerando el auge de los MicroServicios que en si son un tipo especial de servicios dentro de una arquitectura SOA, a nivel del inventario de servicios respectivamente.

    Como que me salí un poco del tema, jejeje el ejemplo está bien pero me hubiese gustado mejor verlo basado en un enfoque Topdown (definiendo tu contrato técnico apoyándote en: WADL, SWAGGER, RAML, etc), esto debido a que este enfoque es más mantenible a nivel de ambas partes: (Service Providers y Service Consumers), así la aplicación de estándares, principios, patrones y buenas practicas se pueden aplicar desde el Diseño respectivamente .

    Saludos Oscar.

    1. Lo que dices tiene sentido, desarrollar los servicios de Arriba abajo. En este articulo solo quise describir la forma de utilizar la tecnología, es por eso que no menciono nada de eso, pero me apunto el comentario para una segunda entrada.

      saludos.

  2. Que tal, estoy probando lo de las api y ya hice los pasos que muestras pero me aparece erro 404 probar la aplicacion..

    calse 1…….
    package prueba;

    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;

    @ApplicationPath(“/”)
    public class HolaMundo extends Application {
    }

    Clase 2……
    package prueba;

    import javax.ws.rs.Consumes;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;

    @Path(“/hola”)
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public class HolamundoRest {
    //@Path(“/hola”)
    @GET
    public Response sayHello() {
    return Response.ok(“Hello World desde el API REST”, MediaType.APPLICATION_JSON).build();
    }
    }

    esta es la direccion que me da eclipse al probar el servicio
    http://localhost:8080/prueba/

    y me imagino que debo agregarle hola
    http://localhost:8080/prueba/hola

    pero ya he visto todo y probado todo y aun no me funciona, podrias ayudarme??

    1. Hola Saul, la URL debe iniciar con el Context de la aplicación, el context es la URL que le antepone el servidor a cada aplicación desplegada, despues de eso, viene la url del servicio, por ejemplo

      http:localhost:8080//hola

  3. Hola Oscar,
    He descargado la aplicacion de git y aun asi obtengo un 404.

    Cual es la url que tengo que seleccionar, es decir, como la tengo que componer y de donde tengo que sacar los valores.

    Gracias

    1. Hola Cristina,

      Yo acabo de realizar una prueba y me respondió correctamente, lo probé sobre un Wildfly 11. Al momento de desplegar te indica cual es el context path de la aplicación, en este caso, la línea que nos interesa es la siguiente:
      23:14:50,116 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool — 98) WFLYUT0021: Registered web context: '/api-0.0.1-SNAPSHOT' for server ‘default-server’

      Como puedes ver, la aplicación está sobre el context '/api-0.0.1-SNAPSHOT', dicho lo anterior, mi Wildfly está sobre el puerto 8080, asi que puede consumir si problemas el servicio de consulta de usuarios desde la URL http://localhost:8080/api-0.0.1-SNAPSHOT/users

      Espero que esto te sirva de algo para hacer funcionar la aplicación.

  4. Hola Oscar,

    Yo tampoco soy capaz de conseguir que se conecte a la url. He utilizado tu proyecto de git. Puedes explicar como se compone la url. de donde sacamos el context.

    Saludos,

  5. Hola Oscar,
    Estaba siguiendo tu tuto usando el servidor de Tomcat, pero me generaba el conocido error de 404, sin embargo decidí implementar JBoss como servidor and it works!
    (Tendré que darle otra revisada a la configuración de tomcat)
    Muchas gracias por el tuto!

    1. Hola Diana, el detalle es que cada servidor de aplicaciones publica las aplicaciones en diferentes context(path) lo que modifica la URL en la cual puedes ver el servicio, te recomiendo que prestes mucha atención en el log que genera el Tomcat al momento del deploy, seguramente allí te indica al context.

      saludos.

  6. Muchisimas gracias. Tú blog me ha sido de mucha ayuda para entender REST. Ánimo, sigue adelante… este tipo de material ayuda muchisimo a los que estamos iniciando. Además, explicas de manera muy precisa y correcta! Excelente contenido

  7. hola Oscar, he visto otros tutoriales sobre rest, y he visto como declaran en las dependencias el uso de jersey que entiendo es la implementacion de jax-rs , he visto que en tu turorial no es necesario , por lo que me surge la duda de cuando si es necesario declarar una implementacion como jersy.

    gracias de antemano!

    1. Hola Julio,
      Pongamos las cosas en el contexto adecuado, JAX-RS es un especificación, por lo tanto, por si solo no sirve, si no que requiere de una implementación, como lo son Jersey, RESTeasy, Restlet.
      Esto quiere decir que cualquier implementación que utilicemos debería de funcionar, pues todas implementan la especificación JAX-RS.

      Dicho lo anterior, procederé a responder tu pregunta, podrás ver que en el archivo pom.xml estoy importando javaee-api, esta librería contiene todo el estándar JEE, es decir, contiene las interfaces y anotaciones de JAX-RS pero sin una implementación funcional, esto quiere decir, que con esta librería yo puedo utilizar las anotaciones e interfaces de JAX-RS pero por si sola no funcionará. El segundo paso es importar la librería org.wildfly.core la cual contiene todas las librerías de Runtime de Wildfly, en esta segunda librería podría venir cualquier implementación de JAX-RS, como lo es Jersy, sin embargo, no me interesa saber cual contiene, por que yo solo utilizo las anotaciones e interfaces estandares de JAX-RS contenidas en javaee-api. Ahora bien, lo interesante viene al momento de hacer el deploy, pues es cuando el aplication server es quien pone la implementación real para que mi aplicación funcione.

      La única razón por la que tu deberías hacer referencia (importar) una implementación concreta como es el caso de Jersy, es cuando requieres utilizar una anotación o interface que sale del Estandar de JAX-RS, en tal caso, requieres el import por que el estandar no las cubrirá.

      Espero haber resuelto todas tus dudas.

      saludos.

    1. Hola Aldo,
      Efectivamente, cada servidor de aplicaciones maneja las URL de forma diferente, lo que te aconsejo es que revices en el log de tu servidor e identifiques que context le asigna a tu aplicación, sabiendo el context, el resto de la URL sería la misma.
      saludos.

  8. Saludos. sigo sin poder ver la pagina, después de un rato en un comentario vi que mencionas que a la hora de iniciar el servidor(WildFly 11.0) te dice el context y efectivamente es la que mencionas tu y no la que arroja por automático. Pero aun así a la hora de meterme a la pagina de helloworld “http://localhost:8080/api-0.0.1-SNAPSHOT/helloworld”, me manda un error de “Not Found” y si me meto a la pivot me arroja “Forbidden”. Soy nuevo en esto y quisiera aprender. Gracias

    1. Hola Raziel, la URL de un servicio se determina por varias partes, :///

      El host y puerto creo que queda muy claro, por lo que no me detendré en eso, con respecto al context, es que te asigna el servidor de aplicaciones para tu aplicación, el app-context es que determinas en la anotación @ApplicationPath, la cual dice a partir de que URL responderá todos los servicios, finalmente, service-uri es la URL que determinas para cada servicio, definida en la anotación @Path. En el caso de @Path, recuerda que se concatena con el path a nivel de clase(si existe) y el del método, la combinación de todo esto te dará la URL del servicio.
      Finalmente, recuerda que es importante consumir el servicio por medio del método adecuado (GET, POST, DELETE, ETC).

      saludos.

Deja un comentario

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