Spring maintenant payant

Oui la nouvelle du week-end ou plutot de fin de semaine sur le changement de licence de Spring me reste en travers de la gorge, même si j’en comprends les raisons.

Mais d’un coup je me sens coupable d’avoir poussé depuis 2004 à l’utilisation de Spring sur plusieurs projets et d’en avoir été le défenseur auprès de certains collègues réticents sur les principes d’injection de dépendances, de conteneur léger et même d’AOP. Sur mes 2 derniers projets, j’ai même introduit Spring Security (anciennement ACEGI) et utilisé Spring MVC pour une petite application interne chez mon employeur précédent. Et oui, le changement de licence s’applique aussi à tous ces projets.Cela me fait maintenant me re-questionner sur l’utilisation de ce framework.

D’abord pourquoi Spring ? Logiquement après avoir lu les livres de Rod Johnson “J2EE design and development” et “J2EE Development without EJB” son utilisation semblait être une vrai alternatives aux Ejb 2.x pour les raisons suivantes :

  • des objets et services métiers n’implémentant aucune interface technique (juste des POJO).
  • l’injection de dépendances favorisant le couplage faible entre les objets.
  • les tests unitaires sans déployer dans le conteneur EJB accélérant ainsi les phases de test.
  • la rapidité de démarrage du conteneur Spring pemettant de l’utiliser en dehors d’un serveur application.
    Mais Spring est aussi utilisé maintenant pour toutes ses fonctionnalités qui facilitent le développement d’application JavaEE :
  • son intercepteurs transactionnels et son annotation @Transactional
  • l’accès aux services des serveurs d’application par simple déclaration (j2ee:jndi-lookup)
  • la création de proxy sur des Ejb (2.1, 3.0), Web-Services (JAX-RPC et JAXWS) .
    En fait, j’ai en fait toujours été très satisfait de Spring Core et impressionné par sa stabilité et son excellente documentation tout cela en opensource et gratuit. Les applications développées avec étaient même plus portables que les traditionnelles applications J2EE. Mais la lune de miel a une fin et je pense maintenant que je vais devoir m’intéresser aux alternatives, car je vois mal certains clients payer pour une librairie (cela changera peut-être pour avec Spring dm Server).

    Les alternatives

Pour moi la + évidente :

  • JavaEE 5 et les EJB 3
    Et oui avec des conteneurs d’EJB en mode embedded pouvant être utilisés pour les tests et démarrant en quelques lignes de codes ( voir par exemple OpenEJB de la fondation Apache ou encore JBoss embedded ). De + cette solution a l’immense mérite d’être standard.Maintenant techniquement, le mécanisme d’interception d’EJB 3 n’est pas aussi riche que celui proposé par Spring et son support d’AspectJ. Le mécanisme ne permet d’injecter uniquement des Ejbs ou des ressources JNDI. Mais au moins les tests sans déploiement sont possibles, le code simplifié et épuré. De +, Ejb 3.1 apportent aussi son lot de nouveautés comme l’annotation @Singleton ou la non-obligation de créer une interface métier.

  • Guice

Peut-être un peu jeune et n’est qu’un “IOC container” mais pourquoi pas pour une utilisation pour des applications standalone.

Spring entityManagerFactory in jta and non-jta modes

This blog post is about using JPA with Spring in 2 contexts :

  • production with a JTA transaction manager
  • testing with transactions handled by jpa transaction manager.
    It has been inspired by Erich Soomsam blog postYou can achieve such configuration with a PersistenceUnitPostProcessor having a single persistence.xml file and 2 Spring context files (1 for each environment).Since you are likely to have at least 2 different Spring dataSource definitions : 1 for production that performs a JNDI lookup to find a bound datasource and 1 for development that uses a local and Spring declared datasource backed by a JDBC connection pool (C3p0 or DBCP), place the entityManager declaration in the same file as the datasource declaration. Let’s say that the default persistence.xml use the non-jta datasource:
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
    <persistence-unit transaction-type="RESOURCE_LOCAL"
    name="seamphony">
    <properties> <!-- Scan for annotated classes and Hibernate mapping XML files -->
    <property value="class, hbm" name="hibernate.archive.autodetection" />
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
    </properties>
    </persistence-unit>
    </persistence>

    Here’s how you can use Spring to post process the persistence unit and configure it for production (here with MySQL datasource and JBoss Transaction Manager):
    <bean
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    id="entityManagerFactory">
    <property ref="dataSource" name="dataSource"></property>
    <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property value="MYSQL" name="database" />
    <property value="true" name="showSql" />
    <property value="org.hibernate.dialect.MySQLDialect" name="databasePlatform" />
    </bean>
    </property>
    <property name="jpaPropertyMap" />
    </bean>
    <map>
    <entry value="org.hibernate.transaction.JBossTransactionManagerLookup"
    key="hibernate.transaction.manager_lookup_class">
    <entry value="true" key="hibernate.transaction.flush_before_completion" />
    <entry value="true" key="hibernate.transaction.auto_close_session" />
    <entry value="jta" key="hibernate.current_session_context_class" />
    <entry value="auto" key="hibernate.connection.release_mode" />
    </entry>
    </map>
    <property name="persistenceUnitPostProcessors">
    <list>
    <bean class="JtaPersistenceUnitPostProcessor">
    <property value="true" name="jtaMode"></property>
    <property ref="dataSource" name="jtaDataSource"></property>
    </bean>
    </list>
    </property><!-- Datasource Lookup -->
    <bean class="org.springframework.jndi.JndiObjectFactoryBean" id="dataSource">
    <property name="resourceRef">
    <value>false</value>
    </property>
    <property name="jndiName">
    <value>java:/MyDS</value>
    </property>
    </bean><!-- Transaction Manager -->
    <bean class="org.springframework.transaction.jta.JtaTransactionManager"
    id="transactionManager">
    <property value="java:/TransactionManager" name="transactionManagerName" />
    <property value="false" name="autodetectUserTransaction" />
    </bean>

Here’s the class that reads the jta mode property and configure the transaction type accordingly:

import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
public class JtaPersistenceUnitPostProcessor implements
PersistenceUnitPostProcessor {
private boolean jtaMode = false;
private DataSource jtaDataSource;
private PersistenceUnitTransactionType transacType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
public void postProcessPersistenceUnitInfo(
MutablePersistenceUnitInfo mutablePersistenceUnitInfo) {
if (jtaMode) {
transacType = PersistenceUnitTransactionType.JTA;
mutablePersistenceUnitInfo
.setJtaDataSource(this.getJtaDataSource());
}
mutablePersistenceUnitInfo.setTransactionType(transacType);
}
public boolean isJtaMode() {
return jtaMode;
}
public void setJtaMode(boolean jtaMode) {
this.jtaMode = jtaMode;
}
public DataSource getJtaDataSource() {
return jtaDataSource;
}
public void setJtaDataSource(DataSource jtaDataSource) {
this.jtaDataSource = jtaDataSource;
}
}

Spring really helps tuning your persistence unit for different environments. It could be achieved by a custom build task that could alter the persistence.xml file but since this example assumes that Spring is already used, it can be avoided.

A groovy use case

I recently discovered Spring’s ability to declare beans that are script-based. This feature can be used to mock business interfaces with Groovy implementations. In a JavaEE container where startup and redeployment can take a while, it can be very useful, in pre-integration tests, to change the behaviour of your business services especially without redeploying the whole EAR or restarting the server.Here’s an example declaration:

<bean id="MockServiceImpl" class="org.springframework.scripting.groovy.GroovyScriptFactory">
<constructor-arg value="${mocks.path}/MockServiceImpl.groovy"></constructor-arg>
</bean>
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor">
<property name="defaultRefreshCheckDelay" value="2"></property>
</bean>

The “defaultRefreshCheckDelay” parameter sets the delay in seconds between checks for modifications of the script. and the groovy script:

public class MockServiceImpl implements Service {
ProductsReturn returnCase1 = new ProductsReturn(fetchDate:Calendar.getInstance(),products:[new Product(id:1,name:"good")])
ProductsReturn emptyReturn = new ProductsReturn(fetchDate:Calendar.getInstance(),products:[])
ReturnObject listProductsForUser(String userId) {
return returnCase1
}

I see many benefits in this solution:

  • hot-swapping implementations without redeployment.
  • returned objects can be dynamically generated. For instance if you want to return objects depending only one a given parameter it can be done easily.
  • more concise than XML (see xmlstubs a XML based mocking solution).

On a side note, groovy requires ASM 2.2.2 library so if you use hibernate use the cglib with no dependency library which includes asm classes in renamed packages. Also use Spring 2.0.3+ if you use AspectJ pointcut declarations or you can expect errors.With maven profiles it ‘s easy to build a mock and non-mocked service layer of an EAR.Note that you can still inject the real implementations if you want to delegate work to it.

<bean id="MockServiceImpl" class="org.springframework.scripting.groovy.GroovyScriptFactory">
<constructor-arg value="${mocks.path}/MockServiceImpl.groovy"/>
<constructor-arg value="ServiceImpl"/>
</bean>

On an other side note, I like both Groovy and JRuby but now tend to prefer Groovy because it leverages my knowledge of Java API. With Ruby i spend too much time finding the reference web site how to achieve things that i do almost naturally in Java. OTH, Ruby has its core API use closures. Closures are tightly integrated and tend to favor loose coupling.

Spring and Lingo = Easy JMS

With Lingo from codeHaus, Spring remoting can be extended to support JMS.Here’s a great article on Saniv Jivan’s blog that shows some of its capabilities (synchronous calls over JMS and asynchronous callbacks).

One feature really seducing is asynchronous callbacks over JMSwith POJOS (without a single line of JMS code).The Lingo site does not provide much documentation on itso thanks for the author of this nice article.

We applied this technique for our build system to distribute loadon different machines to speed up the process (we only have mono processor build machines) and gets informed when tasks are done via callbacks.We used Spring 2.0M4 and ActiveMQ 3.2.2 in standalone mode.

Note that I had troubles to make it run with Websphere MQ 5.3First, recent MQ JMS 1.1 compliant Jars must be used anda misinterpretation of the JMS specs by Websphere seems to breakthe Lingo Spring JMS service exporter seehttp://opensource.atlassian.com/projects/spring/browse/SPR-1324which is for JMS templates but can also be applied to lingo.

Here’s the diff of org.logicblaze.lingo.jms.JmsServiceExporter between unpatched and patched version for Websphere MQ:

diff -aur lingo-1.1/src/java/org/logicblaze/lingo/jms/JmsServiceExporter.java li
ngo-1.1-patch/src/java/org/logicblaze/lingo/jms/JmsServiceExporter.java
--- lingo-1.1/src/java/org/logicblaze/lingo/jms/JmsServiceExporter.java 2006-06-
13 13:45:12.716722400 +0200
+++ lingo-1.1-patch/src/java/org/logicblaze/lingo/jms/JmsServiceExporter.java200
6-06-13 13:44:49.899847100 +0200
@@ -180,7 +180,7 @@
}
else {
- return session.createConsumer(destination, messageSelector, noLocal
);
+ return session.createConsumer(destination, messageSelector);
}
}

Spring AOP and MVC authorization

With Spring and a bunch of AOP I’ll show how it’s easy to add protectionsof your business components and notify the view that the user is not authorizedto perform a specific action.This example relies on Spring 2.0 and Spring MVC for the presentation layer.Let’s take an example of a service that executes jobs whose class is named JobExecutorService.This service has methods to add jobs in a Job queue, remove a job from the queueor stop a running job. We would like to authorize only owners of a job to remove the job or stop it. The jobs are persistent (to recover from failure).

1) Defining the authorization aspect
Let’s define in Spring’s application context a Job authorization advice and inject it a Job DAO to access persistent jobs.

<bean id="jobAuthorizationAspect" class="security.JobAuthorizationAspect">
<property name="jobDAO">
<ref bean="jobDAO" />
</property>
</bean>

Here’s below the simplified code of the bean advice which is just a POJOwhich benefits from injection.When the user doesn’t own the Job an AuthorizationException is thrown.We’ll see later how to deal with the exception.
public class JobAuthorizationAspect {
JobDAO jobDAO;
protected static final Log LOG =LogFactory.getLog(JobAuthorizationAspect.class);
public void setJobDAO(JobDAO jobDAO) {
this.jobDAO= jobDAO;
}
public void checkForAuthorization(Job job) {
boolean authorized = false;
UserContext userCtx = ContextMgr.getUserContext();
if (null != userCtx) {
Job job = jobDAO.getJobById(job.getId());
// If user launched Job, he's allowed to perform operations on it
if ((job.getState() == Job.STATE.RUNNING || job.getState() == Job.STATE.STOPPED || job.getState() == job.getState().ENDED) && job.getOwner().equals(userCtx.getPrincipal().getName())) authorized =true;
}
}
else {
LOG.warn("user context or job context have not been found");
}
if (! authorized ) {
LOG.warn("user not authorized");
throw new AuthorizationException("jobaction.notauthorized",new Object[]{},"this action is not allowed");
}
}

N.B
I used Spring to bind user’s context (which stores user information) to the current Thread via a ThreadLocal to easily retrieve user’s data stored in memory and avoid being tied to the Servlet API. ContextMgr classhas a static method to retrieve user’s context.Actually binding is done with a Spring MVC interceptor on controllers in the Spring Web Application Context(you could also use a Servlet filter):
<bean id="authurlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/jobs.htm">JobMultiActionController</prop>
<!-- Add additional URL mappings here -->
</props>
</property>
<property name="interceptors">
<list>
<ref bean="ContextInterceptor"/>
</list>
</property>
</bean>

The ContextInterceptor bean just retrieves user’s data from the HTTP session
and binds it to the current thread

2) Declaring the poincuts

Then we add pointcuts to execute the aspect. Here the pointcuts are defined with AspectJ expressions

<aop:config proxyTargetClass="true">
<aop:aspect id="beforeAdviceJobAuth" ref="jobAuthorizationAspect">
<aop:advice
kind="before"
method="checkForAuthorization" arg-names="job"
pointcut="(execution(* jobqueue.JobExecutorService.stopJob(..)) and args (job)) || ( execution(* jobqueue.JobExecutorService.removeJob(..)) and args(job)) "/>
</aop:aspect>
</aop:config>

So here we are weaving our jobAuthorizationAspect advice with the JobExecutorService bean (not detailed here).The proxyTargetClass attribute is here because the JobExecutorService is declared elsewehere in Spring’s applicationContext and injected and used directly in Spring MVC controllers not via its interfaces. But the bean’s class implements multiple interfaces (infrastructure interfaces like Observer )Spring’s default behaviour is when it detects that the class implements interfaces it to use Java dynamic proxies. So here we set this attribute to force CGLib proxying.The arg-names attribute is here to be as explicit as possible and make sure that our “before” advice is executed for the proper methods of JobExecutorService and that the Job argument is passed (by reference) to the “checkForAuthorization” method of our advice.

3) Dealing with the AuthorizationException

Spring has a mechanism that allows to intercept exceptions and deal with them.We could catch the error and redirects to a page displaying a generic authorization message,we’ll choose to extend this concept to return to the submitting view to display the message.Here’s the declaration of the AuthorizedExceptionResolver

<bean id="AuthorizedExceptionResolver" class="web.AuthorizedExceptionResolver">
<property name="order"><value>1</value></property>
</bean>

And a simplified version of the code (we’ll suppose that all our controllersare SimpleFormController ). :

public class RecoverableExceptionResolver implements HandlerExceptionResolver,Ordered,ApplicationContextAware {
private int order;
public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception e) {
if (e instanceof RecoverableException ) {
Map<Object,Object> messages = new HashMap<Object,Object>();
if (handler != null && handler instanceof AbstractController ) {
AbstractController controller = (AbstractController)handler;
messages.put("errormessage",controller.getApplicationContext().getMessage(((AuthorizedException)e).getMessageKey(),"not authorized",((AuthorizedException)e).getMessage(),request.getLocale()));
request.setAttribute("messages",messages);
}
// If SimpleFormController return internally to its view
if (null != handler && handler instanceof SimpleFormController) {
return new ModelAndView(controller.getFormView());
}
}
return null;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}

Here I made the assumption that the command (object that maps the HTTP submitted parameters)has been bound to user’s session in the controller (Spring has mechanism to do this)and that the form’s view first check that if the form’s command is in the user’s sessionit uses it to populate the form’s fields.We’ll also suppose that the controller’s form view has a box that displays messages whenfound in the request context under the messages attribute (like flash boxes of ROR).

Conclusion:
AOP is the perfect tool to protect business components in a non-intrusive way.Thanks to Spring MVC framework techniques we can create a very flexible and genericway to handle authorizations and report authorization exceptions in our web layer. (using many of the Java EE cool buzz technos)

N.B: Sorry for my poor English…

Article on Spring and AOP

An excellent article on Spring, AOP, EJBs and testing has been published on dev2dev.bea.com from Eugene Kuleshov. It’s intended for Spring newcomers and intermediate users. I have just read it and highly recommand it.

It deals with:

  • Simplifying usage of EJB (SSB here) by delegating to Spring beans and how to inject Spring beans in EJBs
  • Weaving application logic in Spring beans without modifying them using AOP
  • Testing techniques by mocking beans which rely on infrastructure components with Junit and JMock

I wasn’t aware of using Spring’s BeanPostProcessor to switch beans at runtime which prevents from writing another applicationContext.xml file for testing.

Persistent Quartz Jobs with Spring

I developped a small web Spring MVC application for the company I work for that allowed with other things to schedule executions of Ant scripts (reinventing the wheel…)

Quartz is the natural choice in the J2EE world to schedule tasks and allows to express the schedule time (or period) using a Unix CRON pattern. And also Quartz can persist schedule jobs to database.

A Quartz job has to implement the Job interface and for persistant jobs the StatefulJob interface. The jobs are scheduled using a Scheduler implementation. Spring provides a Scheduler factory (org.springframework.scheduling.quartz.SchedulerFactoryBean) and here I’ll show how to declare the declare a persistent scheduler in Spring’s application context that will store jobs to database (and allow all CRUD operations).

Before that Quartz provide DDL scripts that create the necessary tables for many RDBMS, so you need to apply them on your database.

Let’s declare below the Scheduler using Spring’s factory (SchedulerFactoryBean). Note that the properties are set here for MySQL and some optimized versions of the declared classes exist for other RDBMS

Update: the job store class JobStoreTX handles transactions by itself. Sousing it with a Spring transactional proxy like I did was useless and the schedulertarget could have been used directly. Instead use the JobStoreCMT with a Spring JTAtransaction manager and a JTA aware datasource (see below).

Quartz doc says:

If you need Quartz to work along with other transactions (i.e. within a J2EE application server), then you should use JobStoreCMT - in which case Quartz will let the app server container manage the transactions.

<bean id="schedulertarget" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="quartzProperties">
<props>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreCMT</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
</props>
</property>
<property name="dataSource"><ref bean="${datasource}"/></property>
</bean>

Then make methods of the scheduler transactional with a JTA transaction manager.

<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/myds</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="dataSource" ref="${datasource}"/>
</bean>
<bean id="scheduler" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="schedulertarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

Then you can inject directly the scheduler to a Spring MVC controller and programmatically have it doing CRUD operations on Job schedules (or use a cleaner approach with a DAO),etc.