Seleccionar y matar un proceso java determinado

Imaginemos el siguiente escenario: tenemos un servidor linux con varios procesos java corriendo, y quedemos matar a uno de ellos sin afectar el resto. En este post veremos cómo generar un script de linux para matar un proceso seleccionado según la clase que contiene el método main.
Si utilizamos el comando killall:

<br />
killall -9 java<br />

logramos parte de nuestro cometido (matar el proceso), pero seguramente nos traiga más problemas que soluciones, ya que matamos TODAS las máquinas virtuales java corriendo al momento de ejecutar el comando.

Podemos hacerlo de forma manual, haciendo un

<br />
ps -fea |grep java<br />

para luego seleccionar el PID (process id) correspondiente a nuestro proceso, tomando en cuenta la clase que inicia el proceso, el classpath utilizado o los parámetros de inicio y luego invocando el comando kill -9 PID.

Si vamos a matar un cierto proceso java bastante seguido, podemos crearnos un shell script que se tome el trabajo de buscar el proceso y matar únicamente al que nosotros querramos.

A este script únicamente le debemos configurar la variable MAIN_CLASS, que contendrá el nombre de la clase que contiene el método main (clase que inicia nuestra aplicación). Basándose en éste nombre, el script buscará todos los procesos que contengan ese nombre en la línea de comandos, extraerá el PID de las líneas que filtró, y ejecutará un kill -9 para cada proceso.

El script entonces, es el siguiente:

<br />
#!/bin/bash<br />
# Nombre del binario<br />
MAIN_CLASS=com.josearrarte.demo.MainClass</p>
<p># Cantidad de reintentos para matarlo<br />
CNT_INTENTOS=5</p>
<p># Funcion para matar el proceso<br />
matar(){<br />
INTENTO=1</p>
<p>while [ `ps -ef --cols=5000 |grep -v &quot;grep&quot;| grep -c ${MAIN_CLASS}` -gt 0 ] &amp;&amp; [ ${INTENTO} -le ${<br />
CNT_INTENTOS} ]; do<br />
  ps -ef --cols=5000 |grep -v &quot;grep&quot;| grep ${MAIN_CLASS}|awk '{ print $2 }'|xargs -i{} kill -9 {} &gt; /dev/null 2&gt; /dev/null<br />
  INTENTO=$(( ${INTENTO} + 1 ))<br />
done<br />
}</p>
<p>matar<br />

Queda abierta la sección de comentarios para proponer mejores formas de matar procesos java.

Manejo transaccional de la base de datos con Spring Framework y AOP

Introducción

Manejar la transaccionabilidad contra una base de datos no es un tema complicado al utilizar JDBC, menos aún utilizando un bean TransactionTemplate de Spring. Sin embargo, siempre que hacemos tareas repetitivas -como escribir código para empezar una trasacción, hacer un commit en caso de éxito o hacer rollback en caso de error- abre la puerta a olvidos o errores de programación.

Spring pone a disposición buenas herramientas para el manejo transaccional contra una base de datos, ya sea de forma programática o de forma declarativa. Si elegimos el enfoque programático, contamos con la clase org.springframework.transaction.support.TransactionTemplate. Si preferimos manejar nuestras transacciones de forma declarativa, contamos con opciones de configuración mediante XMLs y AOP (tx:advice) o utilizando annotations (org.springframework.transaction.annotation.Transactional)
Veremos los diferentes atributos en la definición de una transacción, y las formas de uso de cada uno de los enfoques.

Atributos de una transacción

name

Nombre de la transacción. Por defecto no tienen nombre, y si tienen, este nombre se muestra en los monitores transaccionales, cuando el concepto es aplicable.

propagation

Es el comportamiento de la propagación de la transacción. Por propagación entendemos la forma de asociar la transacción al método que estamos ejecutando. Entre los posibles comportamientos tenemos:

  • REQUIRED: Comportamiento por defecto. Si existe una transacción en curso, el método corre dentro de esa transacción. Si no existe una en curso, creará una nueva transacción.
    tx_prop_required
  • REQUIRES_NEW: Indica que el método debe
    correr dentro de su propia transacción. Si existe una transacción en curso, se suspenderá durante la duración de la invocación al método.
    tx_prop_requires_new
  • MANDATORY: Indica que el método debe correr dentro de una transacción. Si no existe una transacción en curso, se lanzará una excepción.
  • NESTED: Indica que si existe una transacción en progreso, el método se ejecutará dentro de una transacción anidada. Sobre esta transacción se ejecutará commit o rollback sin afectar las otras, (utilizando savepoints) . Si no existe ninguna transacción en curso, se comporta de la misma forma que REQUIRED.
  • NEVER: Indica que el método no debe ser ejecutado utilizando una transacción en curso. Si existe una transacción en curso, se lanzará una
    excepción.
  • NOT_SUPPORTED: Indica que el método no debe ser ejecutado dentro de una transacción. Si existe una en progreso, se suspenderá durante la ejecución del método.
  • SUPPORTS: Indica que el método no requiere una transacción, pero se utilizará si existese alguna en curso.

isolation

El isolation level de la transacción. Por isolation level entendemos la configuración de qué tanto afectan los cambios del DBMS que son externos a nuestra transacción. En el nivel de aislación más bajo vemos cómo van cambiando los datos desde que comenzó nuestra transacción, inclusive si son resultados intermedios de otra transacción. En el nivel más alto, trabajamos con una foto de los datos que no cambia mientras nuestra transacción vive. Entre los posibles valores tenemos:

  • DEFAULT: Utiliza el nivel por defecto, lo determinará la fuente de datos.
  • READ_UNCOMMITED: Este nivel permite que en una transacción se puedan leer datos que aún no han sido commiteados en otras transacciones (lecturas sucias). Pueden suceder además lecturas fantasma (si se hace rollback de la otra transacción, los datos que leímos no fueron válidos) y lecturas no repetibles (una misma consulta puede retornar valores diferentes dentro de la misma transacción).
  • READ_COMMITED: Este nivel no expone datos de una tupla aún no commiteados por otras transacciones, pero permite que otras transacciones cambien datos de las tuplas recuperadas por nuestra transacción. De esta forma, las lecturas sucias se evitan, pero pueden suceder las lecturas fantasma y las lecturas no repetibles.
  • REPEATABLE_READ: Este nivel no permite leer datos aún no commiteados de una tupla, y tampoco permite modificar los datos leídos por una transacción en curso. Sin embargo, si hacemos 2 consultas (SELECTs) con una condición de rango en el WHERE, y otra transacción inserta tuplas entre las 2 consultas y que cumplan con la condición de rango, las consultas retornarán conjuntos de tuplas diferentes. Las lecturas sucias y las lecturas no repetibles se evitan, pero pueden suceder las lecturas fantasma.
  • SERIALIZABLE: Además de las condiciones de REPEATABLE_READ, evita el caso en que en nuestra transacción hacemos una consulta con una condición de rango, otra transacción inserta una tupla que cae cumple la condición, y luego repetimos la consulta en nuestra transacción. Si el es isolation level es SERIALIZABLE, ambas consultas retornarán el mismo resultado. Se evitan las lecturas sucias, las lecturas no repetibles y las lecturas fantasma.

timeout

El timeout de la transacción, expresado en segundos.

read-only

Indica si la transacción debe ser tratada como solo lectura, posibilitando así optimizaciones adicionales.

Uso de transacciones con Spring

Definición de forma programática

Para manejar la transaccionabilidad de forma programática, debemos
tener una referencia a org.springframework.transaction.support.TransactionTemplate en nuestra clase. Para ello, definiremos algunas relaciones entre nuestros beans:

<br />
&lt;bean name=&quot;hibernateTemplate&quot; class=&quot;org.springframework.orm.hibernate3.HibernateTemplate&quot;&gt;<br />
	&lt;constructor-arg ref=&quot;sessionFactory&quot;/&gt;<br />
&lt;/bean&gt;</p>
<p>&lt;bean name=&quot;transactionManager&quot; class=&quot;org.springframework.orm.hibernate3.HibernateTransactionManager&quot;&gt;<br />
	&lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&gt;<br />
	&lt;property name=&quot;sessionFactory&quot; ref=&quot;sessionFactory&quot; /&gt;<br />
&lt;/bean&gt;</p>
<p>&lt;bean name=&quot;transactionTemplate&quot; class=&quot;org.springframework.transaction.support.TransactionTemplate&quot;&gt;<br />
	&lt;constructor-arg ref=&quot;transactionManager&quot;/&gt;<br />
&lt;/bean&gt;<br />

En este ejemplo el framework de ORM utilizado es Hibernate, pero la idea aplica para cualquier framework ORM de los que Spring tiene soporte.
El bean hibernateTemplate entonces es el que agrupa funcionalidades de acceso a datos, apoyándose en las funcionalidades de Hibernate.
El bean transactionManager es una subclase de org.springframework.transaction.support.AbstractPlatformTransactionManager, implementando el manejo de transacciones (determinación de transacciones existentes, suspensión de transacciones, definición del comportamiento transaccional, etc.).
Por último, transactionTemplate simplifica el manejo transaccional y el manejo de excepciones por errores.

La forma de uso del transactionTemplate dentro de nuesta aplicación es la siguiente:

<br />
public class MyEntityDAOImpl implements MyEntityDAO {</p>
<p>	private HibernateTemplate hibernateTemplate;</p>
<p>	private TransactionTemplate transactionTemplate;	</p>
<p>	public List&lt;MyEntity&gt; getAll() {<br />
		return (List&lt;MyEntity&gt;)<br />
getTransactionTemplate().execute(new TransactionCallback() {</p>
<p>			@Override<br />
			public Object doInTransaction(TransactionStatus status) {<br />
				return getHibernateTemplate().loadAll(MyEntity.class);<br />
			}<br />
		});<br />
	}</p>
<p>	/*<br />
	...<br />
	setters y getters de hibernateTemplate y transactionTemplate<br />
	...<br />
	*/<br />
}<br />

Todo lo que pase dentro del método doInTransaction estará encapsulado dentro de una transacción.

Definición de forma declarativa – XMLs

El bean nos permite crear un aspecto (por más info acerca de AOP, ver este post) encargado de iniciar una transacción contra la base de datos al invocar un método que encaje en la definición del pointcut. En este pointcut se podría definir para un método de una clase, para toda la clase, o incluso para todo un paquete que identifique la capa de negocios o de acceso a datos de nuestra aplicación.

Para configurar un en nuestra aplicación, incluiremos en nuestros XMLs de Spring los siguientes beans:

<br />
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />
	xmlns:tx=&quot;http://www.springframework.org/schema/tx&quot;<br />
	xmlns:aop=&quot;http://www.springframework.org/schema/aop&quot;<br />
	xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd<br />
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd<br />
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd&quot;&gt;</p>
<p>	&lt;aop:config&gt;<br />
		&lt;aop:advisor pointcut=&quot;execution(public * demo.dao.*.create(..))&quot; advice-ref=&quot;tx-advice&quot; /&gt;<br />
	&lt;/aop:config&gt;</p>
<p>	&lt;tx:advice id=&quot;tx-advice&quot;&gt;<br />
		&lt;tx:attributes&gt;<br />
			&lt;tx:method name=&quot;*&quot; propagation=&quot;REQUIRED&quot; isolation=&quot;DEFAULT&quot; rollback-for=&quot;Throwable&quot; no-rollback-for=&quot;BusinessException&quot; /&gt;<br />
			&lt;tx:method name=&quot;get*&quot; propagation=&quot;SUPPORTS&quot; read-only=&quot;true&quot; /&gt;<br />
		&lt;/tx:attributes&gt;<br />
	&lt;/tx:advice&gt;</p>
<p>&lt;/beans&gt;<br />

Tendiendo hacia convención en lugar de configuración, asume que existe un bean llamado «transactionManager», instancia de la clase -en caso de Hibernate- org.springframework.orm.hibernate3.HibernateTransactionManager. Si nuestro transaction manager tiene un nombre diferente, debemos referenciarlo incluyendo un atributo transaction-manager al bean .

El atributo name es el único parámetro requerido, y tiene un significado diferente al que se le da en la configuración programática. En este caso, sirve para filtrar los nombres de los métodos que se asociarán a esta las transacciones. Soporta comodines (*) en los nombres, por ejemplo ‘get*’, ‘handle*’, ‘on*Event’.

Al bean le podemos configurar todos los atributos descritos al inicio del post (propagation, isolation leven, timeout, etc.), y además:

  • rollback-for: Lista de excepciones -separadas por comas- para las cuales se dispara un rollback de la transacción
  • no-rollback-for: Lista de excepciones -separadas por comas- para las cuales no se dispara un rollback de la transacción

Uso de forma declarativa – @Annotations

Si bien simplifica mucho el manejo de transacciones, podemos utilizar annotations para simplificarlo aún más.

Utilizando sólo una línea en la configuración XML de nuestra aplicación podemos dar lugar a configurar el manejo transaccional a nivel de annotations. Esta línea tiene el siguiente formato:

<br />
&lt;tx:annotation-driven transaction-manager=&quot;txManager&quot; /&gt;<br />

El atributo transaction-manager debe ser incluido si nuestro transaction manager no se llama «transactionManager».

El tener configurado este bean nos habilita a poder anotar nuestras clases y métodos con @Transactional y definir de esta forma nuestras transacciones de forma declarativa y dentro de nuestro código Java.

<br />
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)<br />
public class MyServiceImpl implements MyService {</p>
<p>	...</p>
<p>	@Transactional(propagation=Propagation.REQUIRED, readOnly=false)<br />
	public void addMyEntity(MyEntity e) {<br />
		...<br />
	}</p>
<p>	...<br />
}<br />

En este ejemplo, todos los métodos de la clase son anotados como de solo lectura y con el comportamiento de propagación SUPPORTS. Al método addMyEntity se le especifica un comportamiento diferente, anotándolo con el comportamiento de propagación REQUIRED, y eliminando la restricción de solo lectura.

Cabe destacar que @Transactional puede ser utilizado también en interfaces indicando el comportamiento de todas las implementaciones de dicha interface.

Conclusión

Un manejo transaccional apropiado en nuestras aplicaciones es cada día más importante para asegurar robustez, especialmente en ambientes inciertos (desconexiones, latencias) y de alta concurrencia.

Spring nos brinda posiblidades concretas y muy poderosas para aislarnos de la problemática del manejo transaccional, dándonos opciones para las diferentes preferencias de enfoque y opciones en el desarrollo de aplicaciones. Vimos desde cómo hacer para declarar transacciones en el código, teniendo total control acerca del inicio y fin de las mismas. También vimos cómo declarar el ciclo de vida de las transacciones utilizando AOP y Spring juntos, a través de configuración XML. Finalmente vimos aún más simplificada la tarea, habilitando la configuración transaccional mediante annotations, y de esta manera definir en nuestras clases -o interfaces- el comportamiento deseado.

Hoy en día podemos hacer uso de esta flexibilidad y potencia, que quizá hasta hace poco estaba restringida a EJBs, utilizando un framework no intrusivo como Spring, un concepto cada ves más utilizado como AOP y nuestros viejos y queridos POJOs para nuestra lógica.

Referencias

AOP con Spring framework

Introducción

¿Qué es AOP?

Aspect-Oriented Programming (AOP) es un paradigma de programación que nos permite separar «aspectos» o «intenciones» de nuestro software en diferentes módulos según su responsabilidad. De esta manera puede verse como otra herramienta para poder diferenciar en nuestro código las diferentes necesidades, encapsulando los diferentes conceptos como ser los requerimientos funcionales, seguridad, profiling de tiempos, transaccionabilidad contra una base de datos, logging, entre otros.

En Wikipedia ofrecen una definición bastante completa de los términos básicos utilizados en el mundo AOP:

  • Aspect (Aspecto) es una funcionalidad transversal (cross-cutting) que se va a implementar de forma modular y separada del resto del sistema. El ejemplo más común y simple de un aspecto es el logging (registro de sucesos) dentro del sistema, ya que necesariamente afecta a todas las partes del sistema que generan un suceso.
  • Join point (Punto de Cruce o de Unión) es un punto de ejecución dentro del sistema donde un aspecto puede ser conectado, como una llamada a un método, el lanzamiento de una excepción o la modificación de un campo. El código del aspecto será insertado en el flujo de ejecución de la aplicación para añadir su funcionalidad.
  • Advice (Consejo) es la implementación del aspecto, es decir, contiene el código que implementa la nueva funcionalidad. Se insertan en la aplicación en los Puntos de Cruce.
  • Pointcut (Puntos de Corte) define los Consejos que se aplicarán a cada Punto de Cruce. Se especifica mediante Expresiones Regulares o mediante patrones de nombres (de clases, métodos o campos), e incluso dinámicamente en tiempo de ejecución según el valor de ciertos parámetros.
  • Introduction (Introducción) permite añadir métodos o atributos a clases ya existentes. Un ejemplo en el que resultaría útil es la creación de un Consejo de Auditoría que mantenga la fecha de la última modificación de un objeto, mediante una variable y un método setUltimaModificacion(fecha), que podrían ser introducidos en todas las clases (o sólo en algunas) para proporcionarlas esta nueva funcionalidad.
  • Target (Destinatario) es la clase aconsejada, la clase que es objeto de un consejo. Sin AOP, esta clase debería contener su lógica, además de la lógica del aspecto.
  • Proxy (Resultante) es el objeto creado después de aplicar el Consejo al Objeto Destinatario. El resto de la aplicación únicamente tendrá que soportar al Objeto Destinatario (pre-AOP) y no al Objeto Resultante (post-AOP).
  • Weaving (Tejido) es el proceso de aplicar Aspectos a los Objetos Destinatarios para crear los nuevos Objetos Resultantes en los especificados Puntos de Cruce. Este proceso puede ocurrir a lo largo del ciclo de vida del Objeto Destinatario:
    • Aspectos en Tiempo de Compilación, que necesita un compilador especial.
    • Aspectos en Tiempo de Carga, los Aspectos se implementan cuando el Objeto Destinatario es cargado. Requiere un ClassLoader especial.
    • Aspectos en Tiempo de Ejecución.

AOP con Spring Framework

Spring Framework nos ofrece un potencial muy interesante, utilizando el framework de AOP AspectJ, y permitiéndonos usarlo declarando beans muy similares a los tradicionales, y ofreciendo la suficiente flexibilidad para la gran mayoría de los escenarios.
Podemos modificar o agregar comportamiento de nuestros beans en diferentes momentos de la invocación:

  • Antes de invocar a un metodo.
  • Luego de invocar un método, si retornó OK.
  • Luego de invocar un método, si lanzó excepción.
  • Reemplazar la ejecución de un método.

Ejemplos de uso

A continuación veremos algunos casos de uso típicos en los que AOP aplica como solución.

Transaccionabilidad contra una base de datos

Escribí otro post que se centra en este tema, y uno de los enfoques que plantea para resolver esta problemática es definir las transacciones de forma declarativa utilizando AOP.

Profiling

Supongamos que queremos medir y enviar a un log el tiempo que demora la invocación a un conjunto de métodos de nuestras clases. Una opción sería agregar un cronómetro en cada uno de los métodos a monitorear -tomando el tiempo al iniciar, y tomando nuevamente el tiempo en un finally antes de retornar-. Otra opción es crear un aspecto al cual le especificamos qué métodos serán los que tiene que cronometrar.

Definiremos entonces una clase totalmente aislada del resto de la lógica de nuestro sistema, encargada de iniciar un cronómetro, ejecutar el método, parar el cronómetro y enviar a System.out el tiempo insumido.

<br />
package demo.aop;</p>
<p>import org.<br />
aspectj.lang.ProceedingJoinPoint;<br />
import org.springframework.util.StopWatch;</p>
<p>public class AopProfiler {</p>
<p>	public Object doProfile(ProceedingJoinPoint call) throws Throwable {</p>
<p>		StopWatch clock = new StopWatch(&quot;Started profiling&quot;);</p>
<p>		try {<br />
			clock.start(call.toShortString());<br />
			return call.proceed();<br />
		} finally {<br />
			clock.stop();<br />
			System.out.println(clock.prettyPrint());<br />
		}<br />
	}<br />
}<br />

Utilizando Spring y AspectJ, la única restricción impuesta a la clase que define el aspecto es que tenga un método que recibe un objeto de tipo ProceedingJoinPoint y que lance Throwable; no son importantes ni el nombre de la clase ni el del método.

La configuración de los beans en Spring quedaría de la siguiente forma:

<br />
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;<br />
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />
	xmlns:aop=&quot;http://www.<br />
springframework.org/schema/aop&quot;<br />
	xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd<br />
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd&quot;&gt;</p>
<p>	&lt;bean name=&quot;aopProfiler&quot; class=&quot;demo.aop.AopProfiler&quot; /&gt;</p>
<p>	&lt;aop:config&gt;<br />
		&lt;aop:aspect ref=&quot;aopProfiler&quot;&gt;<br />
			&lt;aop:pointcut id=&quot;pointcut&quot; expression=&quot;execution(public * demo.dao.PersonDAOImpl.getById(..))&quot; /&gt;<br />
			&lt;aop:around method=&quot;doProfile&quot; pointcut-ref=&quot;pointcut&quot; /&gt;<br />
		&lt;/aop:aspect&gt;<br />
	&lt;/aop:config&gt;<br />
&lt;/beans&gt;<br />

Lo destacable de esta configuración son los namespaces que agregamos en el elemento para soportar los beans especiales para la configuración de AOP. El bean llamado «aopProfiler» no tiene nada de especial, simplemente es una referencia a la clase antes definida. La magia ocurre en el bean , en donde definimos el aspecto. define el pointcut del aspecto. Este pointcut en particular significa que el aspecto se va a ejecutar cada vez que ejecutemos el método getById de la clase demo.dao.PersonDAOImpl, sin importar qué parametros le pasemos. El elemento describe el comportamiento del aspecto; cuando se detecte una invocación a este método, el framework desviará la llamada al método doProfile de la clase definida en el bean aopProfiler. Cabe notar que parte de la implementación de este aspecto es invocar al método original (invocando el método org.aspectj.lang.ProceedingJoinPoint.proceed()), pero no es mandatorio.

Logging

Otra aplicación de AOP interesante podría ser registrar las invocaciones a cada método de un conjunto determinado de paquetes, clases o métodos de nuestra aplicación. Adaptando el ejemplo anterior no sería muy difícil implementar un aspecto de logging.
Podríamos darle una funcialidad extra, registrando además los parámetros de la invocación; el método org.aspectj.lang.ProceedingJoinPoint.getArgs() nos abre esta posibilidad, retornando un Object[] con los parámetros de invocación.

Seguridad

El control de acceso a nuestros objetos es otra aplicación típica en las que AOP encaja de forma muy natural. En este caso no daremos ejemplos puntuales de implementación, sino que nos referiremos a un producto ya maduro y centrado especialmente en este punto: Spring Security.

Una de las funcionalidades disponibles en Spring Security es la configuración de restricciones de acceso a los métodos de nuestra lógica de negocios. Esta configuración de las restricciones se puede hacer mediante annotations como por ejemplo @Secured de la siguiente forma:

<br />
npublic interface BankService {</p>
<p>	@Secured(&quot;IS_AUTHENTICATED_ANONYMOUSLY&quot;)<br />
	public Account readAccount(Long id);</p>
<p>	@Secured(&quot;IS_AUTHENTICATED_ANONYMOUSLY&quot;)<br />
	public Account[] findAccounts();</p>
<p>	@Secured(&quot;ROLE_TELLER&quot;)<br />
	public Account post(Account account, double amount);<br />
}<br />

Otra forma posible -la que nos interesa destacar- es definiendo pointcuts específicos para este fin, de la forma:

<br />
&lt;global-method-security&gt;<br />
	&lt;protect-pointcut expression=&quot;execution(* com.mycompany.*Service.*(..))&quot; access=&quot;ROLE_USER&quot;/&gt;<br />
&lt;/global-method-security&gt;<br />

Este enfoque es particularmente potente; este ejemplo en particular nos permite definir en 3 líneas una restricción de acceso a todos los métodos de las clases llamadas *Service del paquete com.mycompany.

Por información más detallada, referirse a la documentación y ejemplos de Spring Security.

Conclusiones

Si bien se puede argumentar que el uso de las herramientas de AOP pueden impactar en la performance de una aplicación (aunque la performance no fue considerada en este post), nos abre un abanico de posiblidades en lo que tiene que ver con mejorar la claridad de nuestro código, dado que separamos la lógica de negocios de otros aspectos de nuestra aplicación como ser transaccionabilidad, logging, verificación de permisos de acceso, entre otros.
Gracias a esta separación de responsabilidades nuestra lógica que más simple de verificar, ya que es más fácil escribir POJOs -y sus correspondientes tests- que encapsulen las funciones para la que fueron concebidas.

Referencias

Problemas en Eclipse de proyectos Maven con dependencias a AspectJ

Hace unos días un compañero de trabajo yo nos encontramos con una situación un poco extraña utilizando Maven y AspectJ, digna de comaprtirla. En un proyecto Java en el que utilizamos Maven, algunas de las dependencias en el pom.xml eran las siguientes:

<br />
&lt;dependency&gt;<br />
    &lt;groupId&gt;aspectj&lt;/groupId&gt;<br />
    &lt;artifactId&gt;aspectjrt&lt;/artifactId&gt;<br />
    &lt;version&gt;1.5.3&lt;/version&gt;<br />
&lt;/dependency&gt;<br />
&lt;dependency&gt;<br />
    &lt;groupId&gt;aspectj&lt;/groupId&gt;<br />
    &lt;artifactId&gt;aspectjtools&lt;/artifactId&gt;<br />
    &lt;version&gt;1.5.3&lt;/version&gt;<br />
&lt;/dependency&gt;<br />
&lt;dependency&gt;<br />
    &lt;groupId&gt;aspectj&lt;/groupId&gt;<br />
    &lt;artifactId&gt;aspectjweaver&lt;/artifactId&gt;<br />
    &lt;version&gt;1.5.3&lt;/version&gt;<br />
&lt;/dependency&gt;<br />

Sin embargo, al hacer un mvn eclipse:eclipse en la PC de mi compañero, esas dependencias no se veían reflejadas en el proyecto de Eclipse. La salida del comando de
Maven no mostraba errores, e inclusive bajaba los JARs de AspectJ al repositorio local, y sin embargo, no había rastros de esas dependencias en el Build path del proyecto. En mi PC no había problemas, las dependencias se bajaban y referenciaban de forma correcta.

Probamos diferentes versiones de Maven (2.1.0 y 2.2.0), pero no se solucionó. Probamos diferentes versiones de las dependencias de AspectJ, y tampoco tuvimos suerte. Después de buscar un poco encontramos un par de bugs reportados, en este link, este link y este otro, y comprendimos que el problema venía por el lado del plugin maven-eclipse-plugin de Maven, y no por el lado de nuestro proyecto. Comprobamos que este error se da utlizando las versiones posteriores a la 2.5.1 del plugin (2.6 en adelante), y que las diferencias en nuestros ambientes de
desarrollo se daban porque yo tenía configurado un proxy HTTP, que me retornaba una versión vieja del maven-metadata-central.xml del plugin. En cuanto saqué la configuración del proxy del settings.xml de Maven, Maven actualizó los JARs del plugin en mi PC, y ambos ambientes reflejaron el mismo problema.

El problema se da cuando el soporte para AJDT está activado. Para solucionarlo, debemos agregar la línea <ajdtVersion>none</ajdtVersion> a la configuración de maven-eclipse-plugin en el pom.xml de nuestro proyecto:

<br />
&lt;project ...&gt;<br />
	...<br />
	&lt;build&gt;<br />
		&lt;plugins&gt;<br />
			...<br />
			&lt;plugin&gt;<br />
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
				&lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;<br />
				&lt;configuration&gt;<br />
					...<br />
					&lt;ajdtVersion&gt;none&lt;/ajdtVersion&gt;<br />
					...<br />
				&lt;/configuration&gt;<br />
			&lt;/plugin&gt;<br />
			...<br />
		&lt;/plugins&gt;<br />
	&lt;/build&gt;<br />
	...<br />
&lt;/project&gt;<br />

Referencias

https://fisheye.codehaus.org/browse/MECLIPSE-544
https://fisheye.codehaus.org/browse/MECLIPSE-558
https://bugs.eclipse.org/bugs/show_bug.cgi?id=270554
http://dev.eclipse.org/newslists/news.eclipse.technology.ajdt/msg01933.html

http://maven.apache.org/plugins/maven-eclipse-plugin/examples/ajdt-projects.html

Crear un nuevo proyecto Java con Maven

El plugin archetype de Maven nos permite crear un proyecto de Maven 2 a partir de un template existente.

Para crear un proyecto Java simple (directorio de código fuente, directorio de código fuente para tests, clase de ejemplo, clase de test de ejemplo y pom.xml) utilizamos el goal archetype:create en el directorio padre del proyecto, de la siguiente manera:

<br />
mvn archetype:create -DgroupId=com.josearrarte -DartifactId=test<br />

Este comando crea el proyecto con un POM como el siguiente:

<br />
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;<br />
  xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />
  xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;</p>
<p>	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;<br />
	&lt;groupId&gt;com.josearrarte&lt;/groupId&gt;<br />
	&lt;artifactId&gt;test&lt;/artifactId&gt;<br />
	&lt;packaging&gt;jar&lt;/packaging&gt;<br />
	&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;<br />
	&lt;name&gt;test&lt;/name&gt;<br />
	&lt;url&gt;http://maven.apache.org&lt;/url&gt;</p>
<p>	&lt;dependencies&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;junit&lt;/groupId&gt;<br />
			&lt;artifactId&gt;junit&lt;/artifactId&gt;<br />
			&lt;version&gt;3.8.1&lt;/version&gt;<br />
			&lt;scope&gt;test&lt;/scope&gt;<br />
		&lt;/dependency&gt;<br />
	&lt;/dependencies&gt;<br />
&lt;/project&gt;<br />

La estructura de directorios generada queda:

<br />
(root)<br />
|   pom.xml<br />
|<br />
---src<br />
    +---main<br />
    |   ---java<br />
    |       ---com<br />
    |           ---josearrarte<br />
    |                   App.java<br />
    |<br />
    ---test<br />
        ---java<br />
            ---com<br />
                ---josearrarte<br />
                        AppTest.java<br />

Otros posibles goals del plugin archetype son los siguientes:

  • archetype:generate muesta un catálogo de plantillas y pide al usuario que seleccione uno. Luego de un conjunto de pasos variables (según la cantidad de parámetros pedidos al usuario), el plugin se baja la plantilla, procesa los parámetros y genera un projecto Maven.
  • archetype:create-from-project crea una nueva plantilla a partir de un proyecto existente.
  • archetype:crawl: escanea el repositorio en búsqueda de nuevos templates y actualiza el catálogo

Más info:

Audio y video en Java utilizando ffmpeg, Jffmpeg, y JMF

Introducción

Supongamos que queremos implementar un reproductor multimedia en Java. Si a priori no conocemos los codecs de audio o video que debemos soportar, o si simplemente no existe una implementación de ese codec en Java, podemos interactuar con ffmpeg para reproducir multimedia en un montón de formatos diferentes. Para ello podemos utilizar JMF, Jffmpeg del lado del “mundo Java” interactuando con ffmpeg del lado del “mundo nativo”.

ffmpeg es una solución muy completa, open source y multi plataforma para grabar, convertir y reproducir audio y video. El proyecto está licenciado bajo LGPL o GPL (dependiendo de la configuración).

JMF (Java Media Framework) es una API  que permite agregar audio y video a nuestras aplicaciones y applets implementadas sobre tecnología Java. Además de reproducir, JMF nos permite
capturar, transcodificar o hacer streaming en varios formatos.

Jffmpeg es el puente entre ffmpeg y JMF. Si bien JMF soporta algunos formatos, eventualmente nos cruzaremos con el mensaje de error «Unable to handle format:…», especialmente al intentar reproducir los formatos más nuevos. Este plugin de JMF un wrapper Java que utiliza JNI para hacer las llamadas directas al código nativo de ffmpeg.

Instalación en Linux

Vamos a instalar y configurar las diferentes partes de la solución para poder reproducir video en Linux. Quizá el post tienda a compilar todo y configurar “a mano”, es debido a que documenta la necesidad de reproducción de pautas publicitarias en un NLPOS, un flavour de Linux de Novell bastante recortado y orientado a puntos de venta.

1. Instalación de ffmpeg

Como primer punto, compilaremos e instalaremos ffmpeg a partir del código fuente. Tenemos varias opciones: hacer un checkout de SVN, hacer un GIT clone,
o bajarnos el código de la última versión estable. Para cualquier opción, contamos con lo que necesitamos aquí.

Es una buena idea instalar codecs externos para luego poder integrarlos con ffmpeg. Entre estos codecs externos tenemos a LAME para MPEG Audio Layer III,  AMR para 3GPP y xvid para los estándares MPEG-4 Simple Profile and Advanced Simple Profile.

La primer parte de este link nos muestra cómo instalar los diferentes tanto los codecs externos como ffmpeg.

Para la instalación más básica, sin codecs externos, basta con hacer un

./configure

en el directorio en donde está ubicado el código de ffmpeg, luego un

make

y finalmente, con permisos de root un

make install

En distribuciones de Linux más “modernas”  seguramente tengamos la opción de instalar ffmpeg desde repositorios de paquetes, sin la necesidad de compilarlo a mano.

2. Instalación de JMF

JMF no tiene mucha ciencia para instalarlo, simplemente bajamos el instalador de aquí y lo corremos en el directorio que queramos instalarlo. Yo lo ejecuté desde /usr/lib para que JMF quede en /usr/lib/JMF-2.1.1e/ (llamaremos ${JMF_HOME} al directorio de instalación), pero no repercute en el funcionamiento. Debemos recordar que ${JMF_HOME}/lib/jmf.jar deberá estar en el classpath de nuestra aplicación.

3. Instalación de Jffmpeg

Jffmpeg tampoco da muchas dificultades para instalarlo. Podemos bajar el JAR y el .so (o .dll) de aquí, y descomprimirlos en el directorio que nos resulte más cómodo. Lo que debemos tener en cuenta después, es que el JAR deberá estar
en el classpath de nuestra aplicación, y el .so en LD_LIBRARY_PATH, o configurado en el path de las librerías de Linux.

Llamaremos ${JFFMPEG_HOME} al directorio en donde tenemos el JAR y el .so.

4. Classpath, LD_LIBRARY_PATH, etc.

Tanto las librerías nativas como los JARs de JMF y Jffmpeg deberán estar referenciadas por nuestra aplicación para ser tenidas en cuenta.

Para los JARs basta con agregarlos a una variable de entorno que luego se referenciará en el classpath de nuestra aplicación.

Para las librerías nativas podemos agregar un archivo de extensión conf en /etc/ld.so.conf.d/ que contenga una línea para cada directorio que deba ser considerado al buscar las librerías.

La otra opción es agregar los directorios a la variable de entorno LD_LIBRARY_PATH. Esta variable contiene una lista de directorio separados por coma, la cual es utilizada por el sistema operativo para buscar librerías antes de recurrir al conjunto predeterminado de directorios.

Si no queremos definir este conjunto de variables a mano, podemos editar el archivo ~/.bashrc agregando las siguientes líneas (quizá las rutas no sean las que correspondan):

<br />
# cat ~/.bashrc</p>
<p>export JMF_HOME=/usr/lib/JMF-2.1.1e<br />
export JFFMPEG_HOME=/root/jffmpeg<br />
export CLASSPATH=$ JMF_HOME /lib/jmf.jar:$JFFMPEG_HOME/jffmpeg-1.1.0.jar:.:$CLASSPATH<br />
export LD_LIBRARY_PATH=$ JMF_HOME /lib:$JFFMPEG_HOME:${LD_LIBRARY_PATH}<br />
export JAVA_HOME=/usr/java/jdk1.6.0_14<br />

5. Registro de los codecs

Para agregar los codecs de Jffmpeg en JMF utilizaremos la herramienta JMFRegistry que viene con el Java Media Framework. Podemos ejecutarlo por consola tipeando “java JMFRegistry” o desde las preferencias del JMStudio, otra herramienta de JMF que hace de Media Player.

Para cada cambio que listamos a continuación, debemos hacer clickear el botón de commit.

En la pestaña de “Mime types” registramos las siguientes extensiones:

  1. video/vob -> vob
  2. audio/ogg -> ogg

Bajo la pestaña “
Plugins” registramos los siguientes “Demultiplexers”:

  1. net.sourceforge.jffmpeg.demux.vob.VobDemux
  2. net.sourceforge.jffmpeg.demux.ogg.OggDemux

Y bajo la pestaña “Codec” registramos los siguientes codecs:

  1. net.sourceforge.jffmpeg.VideoDecoder
  2. net.sourceforge.jffmpeg.AudioDecoder

6. Parámetros de la aplicación

Como último paso, debemos recordar agregar ya sea la variable $CLASSPATH al classpath de nuestra aplicación, o cada JAR por separado (${JMF_HOME}libjmf.jar,   ${JFFMPEG_HOME}jffmpeg-1.1.0.jar).

Conclusión

Si bien no es “soplar y hacer botellas”, en Java tenemos la posibilidad de agregar contenido multimedia a nuestras aplicaciones o applets utilizando la potencialidad que nos dan los codecs implementados como código nativo al sistema operativo.

En este post vimos un ejemplo en instalación y configuración en Linux; la configuración en Windows no es demasiado diferente.

Referencias

http://jffmpeg.sourceforge.net/download.html

http://downloads.xvid.org/downloads/xvidcore-1.2.2.tar.bz2

http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/download.html

http://www.ffmpeg.org/

http://jffmpeg.sourceforge.net/

http://www.hiteshagrawal.com/ffmpeg/installing-ffmpeg-easily-on-linux

http://www.elctech.com/articles/installing-ffmpeg-with-faac-and-x264-encoders-from-source-on-ubuntu

http://www.luniks.net/luniksnet/html/java/jtvd/doc/jmf.html

http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Web services code-first y contract-first (de Lijin’s Localhost)

Una colección de links con blog posts muy completos acerca de creación de web services code-first y contract-first utilizando CXF.

Code-first

1. Creating Web services using Apache CXF (Part 1) : The Basics.

2. Creating Web services using Apache CXF (Part 2) : Development.

3. Creating Web services using Apache CXF (Part 3) : Configuration.

4. Creating Web services using Apache CXF (Part 4): Testing.

Contract-first

1. Creating “Contract First” – Web Services using CXF (Top Down Approach) Part 1: Creating XSDs.

2. Creating Web Services using CXF (Contract first Approach) Part 2 : WSDL Creation.