viernes, 26 de octubre de 2012

Restful Java Web Services con Tomcat y Eclipse

Espero me de tiempo de terminar este pequeño tutorial.
Bueno, hace poco que estaba estudiando y revisando el tema de estos servicios, quisiera compartir este tutorial para reafirmar lo aprendido... Bueno, sin mas por decir vamos a explicarlo.

No me gusta hablar mucho de teoría en estos tutoriales así que seré breve. Crearemos un ejemplo sencillo de un servicio Rest. Para esto usaremos maven, tomcat y eclipse. Sera un simple saludo pero nos ayudara a entender su funcionamiento.

Lo que me agrada de estos servicios es que así como los servicios web basados en SOAP se cuelgan sobre HTTP para realizar peticiones, los servicios REST también lo hacen, pero lo hacen de la manera mas natural, tan transparente que es suficiente con realizar un GET o POST (PUT, DELETE etc..), esta vez si debemos respetar el significado de cada método del protocolo HTTP.

La ventaja de los REST sobre los SOAP es que ya no nos vamos a preocupar por generar los clientes para invocar los servicios, son mucho mas transparentes y eso nos permite interactuar con otros sistemas de forma mas simple, finalmente la mayoría de los demás lenguajes de programación ya tienen en su core algún API para realizar peticiones HTTP.

Comencemos por crear un proyecto Maven con naturaleza Web con la estructura estándar y dependencias.
Recuerda que para convertir tu proyecto Web de Maven en un proyecto eclipse, debes de aplicar el siguiente comando sobre el pom.xml:

mvn eclipse:eclipse -Dwtpversion=2.0

La estructura que tenemos en nuestro eclipse es la siguiente:

Ya esta, ahora vamos a necesitar unas dependencias del proyecto de Jersey, estas dependencias contienen las classes necesarias que necesitará nuestro proyecto.
Existen diversas implementaciones de la especificación JAX-RS (Restful Web Services), una de ellas es la de Jersey y que es la mas común y la que necesitamos.
Nuestro pom.xml queda así:

Ahora que ya tenemos nuestro proyecto, es hora de codificar...

Nuestro servicio hará lo siguiente, haremos una petición a un servicio y nos regresara la misma información en diferentes formatos (xml, texto y json). La respuesta del servicio dependerá de la url que invoquemos.

La url seria de la siguiente forma:

/mirecurso/text
/mirecurso/json
/mirecurso/xml

Un servicio se hace referencia mediante una URI o un identificador único de un recurso en el servidor,  para nuestro caso será de la siguiente manera:

http://localhost:8090/TestRestful

Y la gran ventaja es que es muy simple de implementar, tanto como hacer un GET sobre la url que vemos arriba.

Bueno, ahora en nuestro eclipse, vamos a crear una clase que maneje las peticiones, nuestra clase se llamará:
MessageResources.java, que es un simple POJO y le agregaremos un par de anotaciones.


Como vemos, nuestra clase esta anotada con @Path, el cual hace match con la url que deseamos invocar.
Teniendo esa clase escrita, vamos a implementar los métodos que van a manejar los diferentes formatos del servicio y que será la salida del mismo:

Ya casi terminamos, como ultimo paso, configuraremos el web.xml para indicarle a Jersey que cualquier petición que inicie con /* será parte de la invocación de nuestro servicio. Es simple, es como configurar cualquier servlet que intercepta las peticiones.
Nuestro web.xml quedaría de la siguiente forma.



Eso es todo, cuando el contenedor del Tomcat inicie detectará las clases anotadas con @Path y las considerará como parte de la URI de nuestro servicio.
Compruébalo haciendo un GET sobre las siguientes URL's.

http://localhost:8090/TestRestful/mirecurso/xml
http://localhost:8090/TestRestful/mirecurso/json
http://localhost:8090/TestRestful/mirecurso/text

Anexo un screen de la salida de mi prueba local. Espero les haya ayudado a crear su primer servicio Rest.



Nos vemos en el siguiente tutorial.
Saludos.

jueves, 4 de octubre de 2012

certificados digitales en Java usando keytool


Comúnmente nos vamos a encontrar con esta excepción:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

La excepción anterior sucede cuando intentamos por ejemplo consumir un servicio web con seguridad https://222.156.221.139/miservicio/WSunservicio.asmx?wsdl

Para este caso lo que necesitamos hacer es instalar el certificado en la maquina virtual de Java (específicamente en el keystore) que tengamos instalado en nuestro equipo para pruebas locales y cuando estemos en ambientes productivos, en la maquina virtual del servidor correspondiente.

La pregunta es, ¿Donde encontramos el famoso keystore de nuestra maquina virtual?. Este archivo se encuentra comúnmente en el JRE.
Por ejemplo, en mi caso esta en la siguiente ruta.


/urs/share/java/jdk1.7.0_07/jre/lib/security

o si estamos en un ambiente de Windows:

C:\Program Files\Java\jre7\lib\security\cacerts


Este es un ejemplo de mi PC.

Ahora que ya ubicamos el keystore, vamos a obtener el certificado usando un browser, por ejemplo usando el firefox.


  1. Pega la url donde se encuentra el recurso del cual queremos obtener el certificado.
  1. Aceptemos e instalemos el certificado con la finalidad de que no nos lo vuelva a pedir


  1. Con el paso anterior, ya hemos instalado el certificado en nuestra computadora.
  2. Para instalar el nuevo certificado (que ya esta en nuestra computadora) en la JVM, necesitamos ayudarnos con una herramienta que ya viene instalada en la maquina virtual y que se llama keytool. Esta es una herramienta que se maneja a nivel de consola, pero existen utilerias que nos ayudan a realizar la misma tarea pero gráficamente. Una de ellas muy buena se llama portcle. http://portecle.sourceforge.net/
  1. Ahora, vamos a usar el keytool a nivel de consola para saber cuales son los certificados que tenemos instalados hoy en día.
  1. Si tenemos configurada las variables de entorno en nuestra maquina, entonces podemos invocar este comando desde cualquier parte de nuestro sistema de archivos. En caso contrario, tenemos que configurarla.
  2. Para ver los certificados existentes: keytool -list -keystore  (si nos pide algún password, escribamos el de por defecto: "changeit"). Si buscamos en la lista que nos despliega no tenemos el certificado actualmente, entonces vamos a instalarlo.
  3. Busquemos en nuestra maquina en el IE bajo Tools->'Internet Options' ->Content->Certificates. Una vez abierto los certificados, localiza el que acabas de instalar y presiona el botón de Exportar. Guárdalo en cualquier parte de tu disco duro usando la opción "DER binario codificado".
  4. O si prefieres usar firefox, vete a Edit ->Preferences ->Advanced ->View Certificates. localiza el certificado que instalaste y presiona el botón de Exportar. Guárdalo en tu disco duro en cualquier carpeta que desees.



  1. Una vez que lo tenemos en nuestra PC. para mi caso "/home/wmb/Desktop/mis-certificados/CRISTAKAR-MEX4" lo instalamos usando el siguiente comando como se ve en la imagen:

  1. En Windows es lo mismo, vemos:
  2. C:\Users\mxe01505114a\Desktop\tmp>keytool -import -noprompt -trustcacerts -alias cristakar-mex4 -file c:\Users\mxe01505114a\Desktop\CRISTAKAR-MEX4.cer -keystore "c:\Program Files\Java\jre7\lib\security\cacerts" -storepass changeit
  3.  Recuerda que debes de tener la variable de entorno de java configurada para invocar "keytool" desde cualquier lugar.
  4. Por ultimo comprobamos que el certificado se haya instalador correctamente con el siguiente comando que nos muestra todos los certificados de la JVM que tenemos instalados: keytool -list -keystore "C:\Program Files\Java\jre7\lib\security\cacerts"


  1. Eso es todo, ya tenemos el certificado en nuestra JVM, espero les haya sido útil.
Nota: Esto no es parte del tutorial, pero si les sirve que bueno. Si estan consumiendo un servicio web con https usando JAX-WS, esto les interesará: