Por default el usuario de la configuración es “TELMEX” todo com mayúsculas y la contraseña es la clave WPA que viene en la etiqueta del Router.

Para configurar Apache CXF en una aplicación web, lo puedes hacer de muchas formas. Esto me confunde, ya que hay distintos ejemplos en internet.

Mi forma preferida es configurar un servlet en el archivo web.xml y configurar los servicios en un archivo beans.xml. Un ejemplo básico de estos archivos sería como el siguiente:

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<init-param>
<param-name>config-location</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>

beans.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

<import resource="classpath:META-INF/cxf/cxf.xml" />

<jaxws:endpoint id="HelloSOAP" address="/ws/helloService"
implementor="com.acme.ws.soap.HelloServiceImpl" />

<jaxrs:server id="rest-api" address="/rest">
<jaxrs:serviceBeans>
<bean id="HelloREST" class="com.acme.ws.rest.HelloREST" />
</jaxrs:serviceBeans>
</jaxrs:server>

</beans>

Las dependencias necesarias en Maven son las siguientes:


<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>

La dependencia a la librería spring-web es necesaria desde la versión 2.6 de Apache CXF. Las dependencias de SLF4J son opcionales, pero muy recomendables para ver la información del Log. Si quieres saber como configurar SLF4J puedes verlo aquí.

Fuentes:
Apache CXF — Servlet Transport.
http://stackoverflow.com/questions/6349424/apache-cxf-rs-extensions-issue-in-2-4-0

Para saber cuáles son las ventajas y desventajas entre un formato y otro, puedes ver la siguiente discusión

http://stackoverflow.com/questions/1256835/why-chose-xml-over-properties-files-for-log4j-configuration

Desde mi punto de vista, deberíamos usar el formato XML.

Aquí dejo un ejemplo de un archivo de configuración properties y su equivalente en xml que encontré en esta página.

log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<!-- A1 is set to be a ConsoleAppender -->
 <appender name="A1" class="org.apache.log4j.ConsoleAppender">
 <!-- A1 uses PatternLayout -->
 <layout class="org.apache.log4j.PatternLayout">
 <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n"/>
 </layout>
 </appender>

<root>
 <!-- Set root logger level to DEBUG and its only appender to A1 -->
 <priority value ="debug" />
 <appender-ref ref="A1" />
 </root>

</log4j:configuration>

Cuando ejecutas una aplicación GWT en Eclipse -ya sea Debug as Web Application ó Run as Web Application- utiliza Jetty como servidor web.

En una aplicación necesitaba poner una serie de archivos disponibles en dicho servidor. Como los archivos ya los tenía en una carpeta, no quise copiarlos a una carpeta en el servidor web (src/main/webapp), así que creé un enlace simbólico a la carpeta. Al querer acceder a los recursos me aparecía el siguiente mensaje en el log

[WARN] Aliased resource: file:/home/cirovladimir/projects/java/videohaus/videohaus-gwt/target/videohaus-gwt-0.0.1-SNAPSHOT/storage/videos/demo.mp4==file:/home/cirovladimir/Videos/videohaus/demo.mp4
[WARN] 404 – GET /storage/videos/demo.mp4 (127.0.0.1) 1446 bytes

El problema es que, por cuestiones de seguridad, Jetty no permite acceder a los recursos mediante un alias (mayúsculas y minúsculas, nombres cortos, enlaces simbólicos y carácteres extras).

Para desactivar esta carácteristica y permitir los enlaces simbólicos, podemos agregar un parámetro a la configuración de ejecución. Selecciona el proyecto y da clic en el menú “Run->Debug Configurations..”, luego agrega el parámetro “-Dorg.mortbay.util.FileResource.checkAliases=false” en la pestaña de argumentos en la sección de argumentos de la máquina virtual.

UPDATE: Existe una opción con el comando “mount” para montar una carpeta local en otra, y con esto ya no es necesario configurar Jetty para seguir los enlaces simbólicos. El comando es

 sudo mount --bind origen nueva_carpeta
 

si quieres que el montaje permanezca después de reiniciar tu computadora, agrega la siguiente línea en el archivo /etc/fstab

 origen &nbsp; nueva_carpeta &nbsp; none   bind   0   0
 

curiosamente esta solución la encontré cuando investigaba como montar una carpeta mediante NFS.

Fuentes:
https://groups.google.com/d/msg/google-web-toolkit/kMZv6jkYitw/yYfM54duu3wJ
http://docs.codehaus.org/display/JETTY/How+to+enable+serving+aliased+files
https://help.ubuntu.com/community/SettingUpNFSHowTo

El registro de eventos en una aplicación puede ser muy útil a la hora de buscar errores. Para ello existe una excelente librería llamada SLF4J.

En un proyecto maven agregamos la dependencia a dicha librería mediante las siguientes líneas

<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>1.6.1</version>
</dependency>

Como SLF4J no es una implementación sino solamente define las interfaces (API), también es necesario agregar una librería que implemente dichas interfaces. En este caso utilizaremos log4j, para ello agregamos la siguiente dependencia

<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 <version>1.6.1</version>
</dependency>

Ahora vamos a crear un archivo llamado log4j.properties en la carpeta src/main/resources -este archivo será copiado automaticamente por Maven al directorio target/proyecto/WEB-INF/classes para que pueda ser leído en tiempo de ejecución por la librería log4j- con el siguiente contenido

# Escpecificar el nivel de mensajes que queremos ver y los receptores de mensajes
log4j.rootLogger=DEBUG, A1

# Agregar a la consola como único receptor y especificar formato del mensaje
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n

Ahora sólo falta registrar los mensajes en nuestro código, por ejemplo

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Video {
 final Logger log=LoggerFactory.getLogger(Video.class);
 public static List<Video> getVideos(){
 try{
 // obtener lista de videos
 }catch(Exception e){
 log.error("Error al obtener la lista de videos",e);
 }
 }
}

Listo, de esta forma aparecerán los mensajes en la consola de Eclipse 😉

Fuentes:
http://logging.apache.org/log4j/1.2/manual.html
http://blog.mograbi.info/2010/08/setting-up-log4j-in-maven-project.html

En un proyecto en el que utilizamos Apache Shiro, para la autenticación y autorización de usuarios, el proceso de verificación de permisos tardaba demasiado. Esto debido a que no habíamos configurado un CacheManager, lo que ocasionaba que se tuviera que realizar una consulta a la base de datos (dado que utilizamos un JdbcRealm) por cada llamada al método SecurityUtils.getSubject().isPermitted()

Para configurar como CacheManager una instancia de la clase EhCacheManager debes agregar primero la dependencia la librería shiro-ehcache

<dependency>
     <groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
     <version>1.2.0</version>
</dependency>

una vez hecho esto, configura el CacheManager en el archivo shiro.ini

cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager
jdbcRealm.cacheManager=$cacheManager

Listo! con esto mejorará el rendimiento al verificar los permisos del usuario. Recuerda invalidar el caché mediante una llamada al método clearCachedAuthorizationInfo() cuando realices cambios a los permisos del usuario.

Fuentes:
http://shiro.apache.org/caching.html
http://shiro.apache.org/static/current/apidocs/org/apache/shiro/cache/ehcache/EhCacheManager.html
http://shiro.apache.org/session-management.html
 

GWT+RestEasy en JBoss AS7

septiembre 12, 2011

Recientemente instalé JBoss AS7 y quede impresionado con su velocidad y rendimiento. Rápidamente quise migrar un proyecto a este servidor pero desafortunadamente no funcionó. Esto debido a que en la aplicación utilizo servicios REST con Jersey y esto ocasionó un error. Fue entonces que decidí utilizar RestEasy en vez de Jersey.

Lo primero que necesitamos es crear una aplicación de GWT con soporte para Maven. Una vez hecho esto, abrimos el archivo pom.xml y agregamos el repositorio de JBoss donde se encuentran las librerías de RestEasy

    <repositories>
        <repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
            <layout>default</layout>
        </repository>
    </repositories>

luego agregamos la dependencia a RestEasy

<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.2.1.GA</version>
</dependency>
</dependencies>

Por último tendríamos que configurar el archivo web.xml. La configuración va a depender de si vamos a depurar/ejecutar la aplicación en “Web Development Mode” (Debug As->Web Application) o si vamos a instalar la aplicación en el servidor JBoss AS7.
Para la primera opción necesitamos agregar lo siguiente

<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/api</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>

Y si vamos a generar el archivo war y colocarlo en JBoss AS7 (Run As -> Maven build…   goals: clean package) tenemos que sustituir las líneas anteriores por las siguientes:

<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>

Fuentes:
http://www.mkyong.com/ (resteasy-hello-world-example)
RestEasy – User Guide
JBoss AS7 Documentation – JAX-RS