Monday, October 31, 2005

Spring Web Flow

I will be presenting on Spring Web Flow on Wednesday, 9 November at Montréal Java Users Group. Following is the official announcement

LA PROCHAINE RENCONTRE SERA LE MERCREDI 9 NOVEMBRE AU CRIM.

Le Groupe d'Utilisateurs Java de Montréal (GUJM) vous invite
à participer à la prochaine rencontre qui sera le mercredi
9 novembre 2005.

TITRE : "Introduction au Spring Web Flow"
par Omar Irbouh.

Spring Web Flow (SWF) est un sous projet du célèbre Spring
Framework. Il a pour objectif de palier aux nombreuses lacunes
introduites par l'approche de développement Web MVC classique.
SWF permet d'implémenter, facilement, des flux de pages en
terme d'actions et de vues ce qui renforce la modularité et
améliore la réutilisation. SWF peut être utilisé avec Apache
Struts, Spring MVC et JSF

Plan de la présentation :
Introduction
Bref rappel sur Spring Framework
Spring Web Flow
- Pourquoi utiliser des Flows dans des applications Web?
- Architecture
- L'implémentation SWF
- Fonctions avancées de SWF
Q&A

À propos du présentateur :

Omar Irbouh est conseiller de chez Compuware inc. Il
travaille actuellement sur un projet J2EE pour le compte
d'une institution financière internationale située à New York.
________________________________________________________________

Heure : 17h30 - 19h30.

Lieu : CRIM (Salle B, ouverte à 17h00).
550, rue Sherbrooke Ouest, Bureau 100
Montréal (Québec), Canada H3A 1B9
http://web.crim.ca/oxygene/pages/contactez-nous.epl

Horaire : 17h30 - 17h40, Mot de bienvenue.
17h40 - 19h00, Présentation
19h00 - 19h30, Discussion libre.

I hope to meet you there.

Monday, October 24, 2005

Hibernate Generic Dao

Christian Bauer blogged sometime before about a Generic Hibernate Dao pattern with JDK 5. This pattern has the advantage of simplifying the dao construction, It also allows for direct access to the underlying Hibernate session witch makes it possible to use the Hibernate powerfull API for data manipulation. The only issue I can think of, as a Spring Framework user, is intergation with Spring Framework declarative services, mainly transaction demarcation.

I updated Christian code to make the Generic Dao easily advisable by Spring Framework ProxyFactories to provide transactions management and other enterprise services.

/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.adam.dao.hibernate;

import java.io.Serializable;
import java.util.List;

import org.adam.dao.GenericDao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.util.Assert;

/**
* GenericHibernateDao that should be extended by HibernateDaos.
* @author Omar Irbouh
* @since 2005.09.12
*/
public abstract class GenericHibernateDao implements GenericDao, InitializingBean {

protected transient Log logger = LogFactory.getLog(getClass());

private Class persistentClass;
private SessionFactory sessionFactory;

public GenericHibernateDao() {
}

public GenericHibernateDao(SessionFactory sessionFactory, Class persistentClass) {
this.persistentClass = persistentClass;
this.sessionFactory = sessionFactory;
}

protected SessionFactory getSessionFactory() {
return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

private Class getPersistentClass() {
return persistentClass;
}

public void setPersistentClass(Class persistentClass) {
this.persistentClass = persistentClass;
}

public void afterPropertiesSet() throws Exception {
Assert.notNull(getSessionFactory(), "sessionFactory is required");
Assert.notNull(getPersistentClass(), "persistentClass is required");
}

@SuppressWarnings({"unchecked"})
public T findById(ID id, boolean lock) throws DataAccessException {
return (T) getSession().load(getPersistentClass(), id, (lock) ? LockMode.UPGRADE : LockMode.NONE);
}

public List findByExample(T exampleInstance) throws DataAccessException {
return findByCriteria(Example.create(exampleInstance));
}

@SuppressWarnings({"unchecked"})
public T store(T entity) throws DataAccessException {
return (T) getSession().merge(entity);
}

public void delete(T entity) throws DataAccessException {
getSession().delete(entity);
}

@SuppressWarnings({"unchecked"})
public List findAll() throws DataAccessException {
return findByCriteria();
}

@SuppressWarnings({"unchecked"})
protected List findByCriteria(Criterion... criterion) {
Criteria criteria = getSession().createCriteria(getPersistentClass());
for (Criterion c : criterion) {
criteria.add(c);
}
return criteria.list();
}

protected Session getSession() {
return SessionFactoryUtils.getSession(sessionFactory, true);
}

}

This abstract class can be subclassed as follows:

/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.adam.dao.hibernate;

import org.adam.dao.RoleDao;
import org.adam.model.Role;
import org.hibernate.Query;
import org.springframework.dao.DataAccessException;

/**
* Hibernate implmentation of the RoleDao business interface.
* @author Omar Irbouh
* @since 2005.08.29
*/
public class HibernateRoleDao extends GenericHibernateDao implements RoleDao {

/**
* Hibernate named query used to retrieve a Role by its name.
*/
private static final String QUERY_ROLE_BY_NAME = "role.by.name";

public Role findByName(final String name) throws DataAccessException {
Query query = getSession().getNamedQuery(QUERY_ROLE_BY_NAME);
query.setParameter("name", name);
return (Role) query.uniqueResult();
}

}

GenericHibernateDao delegates to SessionFactoryUtils for Hibernate session creation / synchronisation.