Cómo configurar Log4j con Spring

2 comentarios
Configurar Log4j con Spring es muy sencillo. Suponiendo que tienes el log4j.jar en la carpeta lib de tu aplicación o servidor más el fichero de configuración log4j.properties o log4j.xml, basta con añadir las siguientes líneas al fichero Spring applicationContext.xml (pej) de tu aplicación:


<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.springframework.util.Log4jConfigurer.initLogging" />
<property name="arguments">
<list>
<value>ruta_a_fichero_configuracion_log4j</value>
</list>
</property>
</bean>

Un ejemplo de ruta_a_fichero_configuracion_log4j podría ser classpath:conf/log4j.properties.

Si la aplicación es web, aún es mas sencillo. Sólo habría que añadir lo siguiente al fichero web.xml:


<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>ruta_a_fichero_configuracion_log4j</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

De nuevo, un ejemplo de ruta_a_fichero_configuracion_log4j podría ser /WEB-INF/log4j.xml.

Cliente webservice Axis2, Http version y Squid

1 comentarios
Este ha sido mi último marrón. Un cliente webservice con Axis2 que habia desarrollado hacía tiempo como parte de un evolutivo de una importante aplicación. El software estaba probado en los entornos de desarrollo y pruebas. El proyecto validado, entregado y cerrado. Sólo que por esas cosas que pasan, habían ido pasando los meses y aún no se habia puesto en producción.

Al final llega el gran día y toma AxisFault:

Unable to sendViaPost to url[http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
org.apache.axis2.AxisFault: Transport error: 501 Error: Not Implemented
at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:298)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:192)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:77)
...

Investigando el error descubrí que lo de Not Implemented se refiere a la versión 1.1 del protocolo HTTP. Me encantan los mensajes de error descriptivos!

Pero, ¿qué era lo que no soportaba HTTP/1.1? Resultó ser un Squid que habian introducido en la infraestructura de red durante estos meses de espera para hacer de proxy de salida del servidor de la aplicación.

Al final, y como solución de compromiso mientras los de Sistemas miran cómo hacer que soporte HTTP/1.1, hemos modificado la aplicación para hacer configurable la versión de HTTP a usar por el cliente webservice. El código es muy sencillo. A continuación un ejemplo de cómo configurar las opciones del stub para usar HTTP/1.0:


...
options.setProperty(
org.apache.axis2.transport.http.HTTPConstants.HTTP_PROTOCOL_VERSION
, org.apache.axis2.transport.http.HTTPConstants.HEADER_PROTOCOL_10);
...

Vistos los problemas que estamos sufriendo ultimamente, he decidido mantener siempre configurables la versión de HTTP y el Chunked. De hecho, usando Chunked a false y HTTP/1.1 el Squid tampoco se quejaba.

Aquí podeis encontrar más información sobre cómo configurar estas y otras opciones HTTP de un cliente webservice, como el timeout y el character set encoding.

Visual jQuery: excelente referencia online para jQuery

0 comentarios
Hace unos dias y vía el blog Hermoso día descubrí Visual jQuery, una excelente referencia online para jQuery, para muchos el ganador de la llamada guerra de frameworks Ajax o javascript. Yo no entro en guerras pero si os puedo decir a los que no lo conozcais que en mi equipo llevamos usándolo meses y merece mucho la pena: potente, ligero, estable y extensible hasta el infinito.

En Visual jQuery podrás consultar todas las funcionalidades de jQuery en su versión actual 1.2.6, perfectamente ordenadas y con ejemplos muy útiles.

Si quereis ver más recursos sobre jQuery podeis echar un vistazo en mi delicius donde llevo muchos enlaces acumulados con articulos, tutoriales, buenas prácticas y plugins.

Java Templates en Eclipse: Logger

5 comentarios
Los Templates del editor Java de Eclipse son estupendos. Ya sabeis, cuando estás programando una clase Java, tecleas por ejemplo for, pulsas Ctrl + Espacio y te aparece un popup con las posibles estructuras del bucle for para autocompletar. La de teclas que te puedes ahorrar en un par de años!

No sólo existen templates para las estructuras de control, también hay para traza, declaración de métodos, inicialización de atributos, constantes, lazy y más. La pantalla donde gestionar los templates está en Window -> Preferences -> Java -> Editor -> Templates.

Ahora piensa en una línea de código que repitas en casi todas tus clases y para la que no haya un template en Eclipse. ¿Es ésta?

private static final Log logger = LogFactory.getLog(NombreClase.class);

Si es así, puedes crearte un template, llamémosle logger, con este simple código:

private static final ${loggerType:newType(org.apache.commons.logging.Log)} logger =
${logFactoryType:newType(org.apache.commons.logging.LogFactory)}
.getLog(${enclosing_type}.class);



Aquí te dejo otro para el típico debug (evitando procesar el posible mensaje):

if (logger.isDebugEnabled()) {
logger.debug(${msg});
}



Y tú, ¿usas alguno más que no vaya de serie?

¿En qué se diferencia un programador de dios?

4 comentarios


Dios no se cree programador.

Un servidor ya tiene sus años y entre los años de facultad, de profesional y leyendo portales he visto a un buen número de programadores. Si tuviera que elegir 1 única característica común entre todos, y por supuesto me incluyo, sería la vanidad.

Ejemplos hay muchos, quién no ha visto a otro sentirse mejor que alguien porque simplemente conoce un framework, herramienta, proyecto,... o el significado de unas siglas! O cuando alguien echa por tierra el trabajo de otro y afirma que él podría hacerlo mejor. Pero es que algunos son capaces de borrarlo cuando funciona y volver a hacerlo!

Y que conste que me incluyo, de hecho la semana pasada despotricaba en privado contra un programador de otra empresa porque supuestamente volvia a fallar uno de sus servicios web y es que lo estaba llamando yo mal... que cara se me quedó!

Más ejemplos, los que menosprecian a aquellos que trabajan en un entorno obsoleto y mis favoritos, los reinventores de la rueda ya terminen haciendo una rueda o un cuadrado (sindrome NIH).

Solemos pecar de sólo mirar las cosas desde nuestro punto de vista y no entendemos a los demás hasta que nos pasa a nosotros. Una vez sufrida la lección en nuestras propias carnes, somos capaces de atar nuestra vanidad en corto y ser mas comprensivos la siguiente vez.

O no. En algunos la vanidad anda constantemente hambrienta, resultando inconcebible la diferencia entre lo buenos que se creen y lo que dice su código y el resto de su trabajo. Suele ser gente realmente difícil de tratar. Afortunadamente, hoy me pillan muy lejos.

Útiles atajos de teclado en Eclipse

17 comentarios
Es obligación de un buen programador sacarle el máximo partido a las herramientas que usa en el día a día. El primer paso es conocer una buena parte de los atajos de teclado de tu IDE favorito, en mi caso Eclipse.

Y aquí os dejo una lista de los atajos que yo encuentro más útiles:
  • Ctrl + T: Navegar por la jerarquía del tipo seleccionado. Mucho más útil que el típico Ctrl + click cuando el tipo es un interface.
  • Ctrl + May + G: Buscar las ocurrencias del tipo o variable seleccionado por todo el workspace.
  • Ctrl + H: Abrir la ventana de búsquedas.
  • Ctrl + May + R: Buscar y abrir por nombre de fichero.
  • Ctrl + May + T: Buscar y abrir por nombre de tipo.
  • Ctrl + E: Navegar por los ficheros abiertos.
  • Ctrl + O: Navegar por lista de atributos y métodos. Si lo pulsas 2 veces añade los atributos y métodos de las clases padre.
  • Ctrl + L: Ir a número de línea.
  • Alt + May + L: Mostrar la lista de todos los atajos de teclado. Si pulsas 2 veces abres la ventana de configuración de atajos de teclado donde podrás ver, modificar y crear nuevos atajos.

Y tú, ¿conoces alguno más?

Resolviendo problemas de interoperabilidad Axis2-SAP R/3

6 comentarios
Actualmente me encuentro sumido en una de las experiencias profesionalas más exigentes que he vivido, al frente de un equipo encargado de desarrollar una aplicación web Java que hará de front-end para varios módulos de un entorno SAP R/3 que está implantando nuestro cliente. La integración se está haciendo mediante webservices SOAP, con las tecnologías Axis2 para nuestra aplicación Java y XI para el entorno SAP. Sin duda una buena prueba para la supuesta interoperabilidad de los servicios web.

El primer problema técnico lo sufrí generando los clientes webservices con WSDL2Java. En principio iba a usar ADB como databinding XML pero el WSDL2Java dió errores con algunos WSDLs, así que decidí cambiarlo por XMLBeans. En comparación es un poco más complejo a la hora de usarlo, tanto el API en sí como los artefactos generados, pero mucho más potente y fiable. Además permite aprovechar todas las restricciones que había definidas en los WSDLs y que seguramente sería lo que fallaba con ADB.

El segundo y auténtico problema vino a la hora de invocar los servicios web SAP con los clientes webservices generados. Los servicios usaban autenticación HTTP Basic y ya los había probado previamente con la herramienta SoapUi. Pero a la hora de invocarlos con los clientes que había generado desde código Java fallaban inexplicablemente, devolviendo el siguiente AxisFault:

org.apache.axis2.AxisFault: problem accessing the parser. Parser already accessed!
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:72)
at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:495)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1973)

Resultaba increible, no eran precisamente los primeros clientes webservices que usaba y había comprobado que el XML enviado era el mismo con SoapUi que con mis clientes.
Después de mucho Google, dí con la solución, o eso creía yo, usar autenticación Preemptive. El código es sencillo:


HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);

auth.setPreemptiveAuthentication(true);

Modifiqué mi código y volví a ejecutar, sólo para obtener un nuevo AxisFault:


Caused by: org.apache.axis2.AxisFault: Server Error
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:486)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:343)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:389)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)

Esta vez sí que parecía chungo, sin 1 pista en el mensaje de error Google no podía ayudarme mucho.

Volví a comparar los mensajes que enviaba SoapUi con los de mi cliente Java y encontré la diferencia en la cabecera HTTP de autenticación. Como ya estaba usando autenticación Preemptive decidí repasar que más podía modificar de la configuración HTTP que estaba usando mi cliente. Probé y probé hasta que dí con la tecla, desactivar el http chunking:


Options options = new Options();
[...]
options.setProperty(HTTPConstants.CHUNKED, "false");

De hecho, con el http chunking desactivado ya no necesito autenticación Preemptive.
Aun no tengo muy claro cúal era la causa. En la misma dmz del servidor SAP hay otros servicios web que usamos y con ninguno ha habido problemas nunca. Lo que me inclina a pensar que el causante es el propio servidor SAP y su configuración http. Lo cierto es que vamos con el tiempo justísimo todos y no nos sobra para indagar más.
En total, un par de horas perdidas, una cosa nueva aprendida y prueba superada.