For the past two months, we have been having our weekly T3 (Tuesday Tech Talk) sessions. It’s a 30-minute discussion about any technical topic the presenter would like to discuss. Presenters are randomly selected from the development group.

So far, we have received nothing but benefits from this activity. Here are some of its benefits and advantages:

  1. The presenters get an opportunity to talk, express themselves and practice their presentation skills. More importantly, they steer away from the developer mindset for a while, get out of their shells, and think of good topics to discuss.
  2. The attendees learn something new. Everybody seems to know something others don’t.
  3. Everyone begins to understand the specialization and span of knowledge of their colleagues. In this way, it becomes easier to know who to ask regarding particular topics. Subsequently, the developers become experts and specialists in their own way.
  4. This builds camaraderie within the team. Everyone relaxes and opens up their minds for new knowledge.
  5. The topics discussed are usually not something we do or use in our daily routine at work. So, everyone gets to learn more than the usual stuff.
  6. Everyone realizes the things that they do not know and starts to seek for more information about it.
  7. The organization strengthens its corporate IQ as people share their ideas and knowledge with each other.
  8. After a couple of sessions, everyone began appreciating the activity and now looks forward for new things to learn.
Here are some of the topics we have discussed so far:
  • Tips on improving website performance (as recommended by Yahoo Exceptional Performance)
  • Programing with Grails
  • Reverse Ajax via DWR
  • jMaki
  • Integration testing with TestNG
  • Image Manipulation / Photo retouching
  • Javascript Programming
In the end, I believe the concept of T3 sessions is very much aligned with our core values - Leadership, Execution, Agility and Passion.

Spring transactions After two days of debugging our codes on transaction handling, I’m writing this post to share my experience so others don’t have to undergo the same pain and torture. However, this post assumes that you’ve setup your Spring transactions - either via AOP or annotations. If you haven’t done so, here are some good references:

  1. Spring Framework - Transaction Management
  2. On Java - Wire Hibernate Transactions in Spring

So, once you’ve setup or tried to setup transactions and failed - here are some tips how to debug your transaction management.

Enable logging. In log4j.properties, add log4j.logger.org.springframework.orm.jpa=DEBUG to enable logging of JPA transactions. This will allow you to trace the activities behind the Spring transaction processes. The logs provide detailed information about new, reused and active transactions, transaction modes, transaction commits and more. This is the best way to understand how transaction behaves on your application and gives you an insight how to fix your transactional problems.

Check your database and dialect. Dialects affect transaction handling so be sure to use the appropriate dialect for your database. Note that there are 2 dialects to define - JPA Dialect and Hibernate Dialect. JPA dialect is defined in the EntityManagerFactory while Hibernate is defined in Hibernate properties.

JPADialect is defined in EntityManagerFactory as shown below:


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="persistenceUnitName">
<value>hibernateConfig</value>
</property>
</bean>

While Hibernate Dialect is defined via persistence.xml.

Watch out for listeners, they could mess up your transactions. A couple of examples about listeners (especially ApplicationListener) found online doesn’t consider transaction handling. Most of them performs data updates within the listener. This should not be the case because in doing so, you could be creating a transaction on the listener which forces all other operations to reuse that transaction. The better way of doing it is to call a service or business layer to perform transactional operations. This way, transaction is created only when the service is invoked.

Declare your transaction as readOnly whenever possible. Read-only transactions run faster so enable this on non-writing functions - (e.g. load, read, find, etc). Also, this avoid transaction commits on binded-data. One specific scenario is when Spring validation throws an error and data is still saved despite the validation error, this means that the data was loaded on a non-readOnly transaction and Spring transaction is committing it.

Reduce your transactional method calls. Put all your business logic function calls in one method marked with @Transactional and avoid calling other methods with their own transaction declarations. For example, if your transactions are declared on service layer, avoid calling another service method because this will trigger transactional checks which unnecessarily slows down the system. Call the DAO method directly instead. This way all your operation are contained in a single transaction declaration.

Understand propagation. Transaction propagation is hard to understand because the effects cannot be easily seen in your application… until you start performance tuning or having problems on saved data. Take note that if your transaction propagation is default, it will try to reuse existing transactions. This means that you could lose your transaction settings (e.g. readOnly), because new transaction was not created instead an existing was reused.

audit security A common requirement in developing enterprise applications is to ensure audit logs are available for data security and traceability–who made the changes, when they were made, and what files or sections were changed. This requirement is not only dictated by corporate IT policies, but also required by government laws. Considering that most enterprise applications have at least 50 domain objects, implementing audit logs on each of them can be time-consuming. So, a generic solution must be established to minimize coding when creating audit logs.

The Solution

  • Use Hibernate interceptors to trigger change events.
  • Use Java reflections to retrieve old and new data.
  • Create an interface to switch logging on or off for every data object.
In summary, here are the steps needed to be performed to accomplish this.
  1. Create an Auditable interface as a marker on the data that needs to be audited. Any data object that needs to be audited must implement this Auditable interface.
  2. Create an AuditLog to store log information. This contains the date (when), user (who), class name, object id and the audit message (what).
  3. Create an AuditLogInterceptor that will keep track of all data change events and store all the  changes performed.
  4. Create a utility that can retrieve object values using Java reflections to process generic data retrieval.
  5. Create sample usage of auditing.
The Implementation
The Auditable interface has 4 method declarations.
public interface Auditable {
	/**
	 * Retrieve the primary key
	 * @return
	 */
	public Long getId();

	/**
	 * Returns the list of fields that should be audited.
	 * @return
	 */
	public List getAuditableFields();

	/**
	 * Returns the field of the primary identifier (e.g. title).
	 * This field is used to uniquely identify the record.
	 * @return
	 */
	public String getPrimaryField();

	/**
	 * Returns customized audit log message. When empty, audit logging
	 * uses standard audit message.
	 * @return
	 */
	public String getAuditMessage();
}

The AuditLog entity must be able to store who, when, what:

package com.ideyatech.core.bean;

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

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.ideyatech.core.bean.user.BaseUser;
import com.ideyatech.core.persistence.listener.AuditLogListener;
import com.ideyatech.core.util.CrudUtil;

/**
 * This class is responsible for handling all audit functions
 * needed to be attached to the classes.
 *
 * @author allantan
 */
@Entity
@Table(name=”HISTORY_LOG”)
public class AuditLog implements Serializable {
	private static final long serialVersionUID = 269168041517643087L;
	@Column(name = “ENTITY_ID”,nullable=false,updatable=false)
	private Long entityId;
	@SuppressWarnings(”unchecked”)
	@Column(name = “ENTITY_CLASS”,nullable=false,updatable=false)
	private Class entityClass;
	@Column(name = “REFERENCE”)
	private String reference;
        @Column(name = “CREATE_DATE”)
        @Temporal(TemporalType.TIMESTAMP)
        private Date createDate;
	@Lob
	@Column(name = “MESSAGE”,nullable=false,updatable=false)
	private String message;
	@Column(name = “USER_ID”,nullable=false,updatable=false)
	private Long userId;
	@Transient
	private transient Object object;
	@Transient
	private transient BaseUser user;

	public AuditLog() {
	};
	@SuppressWarnings(”unchecked”)
	public AuditLog(String message, Long entityId, Class entityClass, Long userId) {
		this.message = message;
		this.entityId = entityId;
		this.entityClass = entityClass;
		this.userId = userId;
		this.setCreateDate(new Date());
	}

	/**
	 * @return the entityId
	 */
	public Long getEntityId() {
		return entityId;
	}

	/**
	 * @param entityId the entityId to set
	 */
	public final void setEntityId(Long entityId) {
		this.entityId = entityId;
	}

	/**
	 * @return the entityClass
	 */
	@SuppressWarnings(”unchecked”)
	public Class getEntityClass() {
		return entityClass;
	}

	/**
	 * @param entityClass the entityClass to set
	 */
	public final void setEntityClass(Class entityClass) {
		this.entityClass = entityClass;
	}

	/**
	 * @return the message
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * @return the userId
	 */
	public Long getUserId() {
		return userId;
	}

	/**
	 * @param userId the userId to set
	 */
	public void setUserId(Long userId) {
		this.userId = userId;
	}

	/**
	 * @return the object
	 */
	public Object getObject() {
		return object;
	}

	/**
	 * @param object the object to set
	 */
	public void setObject(Object object) {
		this.object = object;
	}

	/**
	 * @return the user
	 */
	public BaseUser getUser() {
		return user;
	}

	/**
	 * @param user the user to set
	 */
	public void setUser(BaseUser user) {
		this.user = user;
	}
}

The AuditLogInterceptor is responsible in tracking the changes and creating necessary Audit logs. Notice that session is created from a separate HibernateUtils session so that the original(unchanged) data can be retrieved for comparison.

package com.ideyatech.core.persistence.interceptor;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Session;
import org.hibernate.type.Type;

import com.ideyatech.core.bean.Auditable;
import com.ideyatech.core.persistence.impl.AuditLogDAOImpl;
import com.ideyatech.core.util.CrudUtil;
import com.ideyatech.core.util.HibernateUtil;
import com.ideyatech.core.util.StringUtil;

/**
 * This is the interceptor responsible in tracking audit trails.
 * Source is patterned after the book “Java Persistence with Hibernate” - page 546 onwards
 * and merged with http://www.hibernate.org/318.html
 *
 * @author allantan
 */
public class AuditLogInterceptor extends EmptyInterceptor {
	private static final long serialVersionUID = 582549003254963262L;

	private static Logger _log = Logger.getLogger(AuditLogInterceptor.class);

    private Set inserts    = new HashSet();
    private Set updates    = new HashSet();
    private Set deletes    = new HashSet();
    private Map oldies     = new HashMap(); 

    @Override
    public boolean onSave(Object entity,
                          Serializable id,
                          Object[] state,
                          String[] propertyNames,
                          Type[] types)
            throws CallbackException {
        if (entity instanceof Auditable)
            inserts.add((Auditable)entity);
        return false;
    } 

	/* (non-Javadoc)
	 * @see org.hibernate.EmptyInterceptor#onDelete(java.lang.Object, java.io.Serializable, java.lang.Object[], java.lang.String[], org.hibernate.type.Type[])
	 */
	@Override
	public void onDelete(Object entity, Serializable id, Object[] state,
			String[] propertyNames, Type[] types) {
        if (entity instanceof Auditable)
            deletes.add((Auditable)entity);
	}

    @Override
    public boolean onFlushDirty(Object entity,
                                Serializable id,
                                Object[] currentState,
                                Object[] previousState,
                                String[] propertyNames,
                                Type[] types)
            throws CallbackException {
        if (entity instanceof Auditable) {
        	try {
	        	// Use the id and class to get the pre-update state from the database
	        	Session tempSession =
	                HibernateUtil.getSessionFactory().openSession();
	        	Auditable old = (Auditable) tempSession.get(entity.getClass(), ((Auditable) entity).getId());
	            oldies.put(old.getId(), old);
	        	updates.add((Auditable)entity);
        	} catch (Throwable e) {
        		_log.error(e,e);
        	}
        }
        return false;
    } 

    @Override
    public void postFlush(Iterator iterator)
                    throws CallbackException {
        try {
        	for (Auditable entity:inserts) {
        		if (!entity.skipAudit()) {
        			if (StringUtil.isEmpty(entity.getAuditMessage()))
        				AuditLogDAOImpl.logEvent(
        						CrudUtil.buildCreateMessage(entity), entity);
        			else
        				AuditLogDAOImpl.logEvent(
        						entity.getAuditMessage(), entity);
        		}
        	}
        	for (Auditable entity:deletes) {
        		if (!entity.skipAudit()) {
        			if (StringUtil.isEmpty(entity.getAuditMessage()))
        				AuditLogDAOImpl.logEvent(
        						CrudUtil.buildDeleteMessage(entity), entity);
        			else
        				AuditLogDAOImpl.logEvent(
        						entity.getAuditMessage(), entity);
        		}
        	}
        	for (Auditable entity:updates) {
        		if (!entity.skipAudit()) {
        			if (StringUtil.isEmpty(entity.getAuditMessage())) {
		        		Auditable old = oldies.get(entity.getId());
		        		AuditLogDAOImpl.logEvent(CrudUtil.buildUpdateMessage(old, entity), entity);
        			} else
        				AuditLogDAOImpl.logEvent(
        						entity.getAuditMessage(), entity);
        		}
        	}
        } catch (Throwable e) {
    		_log.error(e,e);
    	} finally {
            inserts.clear();
            updates.clear();
            deletes.clear();
            oldies.clear();
        }
    }
}



This is a continuation of the post “Audit Logging via Hibernate Interceptor“.

Other helper functions are shown below:

CrudUtil is the class responsible for retrieving object values using Java reflections:

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.ideyatech.core.InvalidImplementationException;
import com.ideyatech.core.bean.Auditable;
import com.ideyatech.core.bean.BaseCriteria;
import com.ideyatech.core.bean.BaseEntity;

/**
 * @author allanctan
 *
 */
public class CrudUtil {

    private static Logger _log = Logger.getLogger(CrudUtil.class);

	private static final String SQL_PARAM = “:([^\\s]+)”;
	private static final Pattern SQL_PARAM_PATTERN = Pattern.compile(
			SQL_PARAM, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Creates the logging message for new audit logs
     * @param obj
     * @return
     */
    public static String buildCreateMessage(Auditable obj) {
    	StringBuffer message = new StringBuffer(”Added “);
    	message.append(obj.getClass().getSimpleName())  // class name
    		.append(” “)
    		.append(obj.getPrimaryField())
    		.append(”:”);
    	Object value = retrieveObjectValue(obj, obj.getPrimaryField());
    	if (value!=null)
    		message.append(value.toString())
    		.append(” - “);
    	// loop through the fields list
		List auditFields = obj.getAuditableFields();
		int count = 0;
		for (String property:auditFields) {
			Object ret = retrieveObjectValue(obj, property);
			if (ret!=null && ret.toString().trim().length()>0) {
				if (count > 0)
					message.append(” and “);
				message.append(property)
					.append(”=”)
					.append(ret.toString());
				count++;
			}
		}

    	return message.toString();
    }

    /**
     * Creates the logging message for update audit logs
     * @param obj
     * @return
     */
    public static String buildUpdateMessage(Auditable oldObject, Auditable newObject) {

    	StringBuffer message = new StringBuffer(”Changed “);
    	message.append(oldObject.getClass().getSimpleName())  // class name
    		.append(” “)
    		.append(oldObject.getPrimaryField())
    		.append(”:”);
    	Object value = retrieveObjectValue(oldObject, oldObject.getPrimaryField());
    	if (value!=null)
    		message.append(value.toString())
    		.append(” - “);
    	// loop through the fields list
		List auditFields = oldObject.getAuditableFields();
		int count = 0;
		for (String property:auditFields) {
			Object oldValue = retrieveObjectValue(oldObject, property);
			Object newValue = retrieveObjectValue(newObject, property);
			if (oldValue == null) oldValue = new String(”");
			if (newValue == null) newValue = new String(”");
			if (!oldValue.equals(newValue)) {
				if (count > 0)
					message.append(” and “);
				message.append(property)
					.append(” from ‘”)
					.append(oldValue.toString())
					.append(”‘ to ‘”)
					.append(newValue.toString())
					.append(”‘”);
				count++;
			}
		}

    	return message.toString();
    }

    /**
     * Creates the logging message for new audit logs
     * @param obj
     * @return
     */
    public static String buildDeleteMessage(Auditable obj) {
    	StringBuffer message = new StringBuffer(”Deleted “);
    	message.append(obj.getClass().getSimpleName())  // class name
    		.append(” “)
    		.append(obj.getPrimaryField())
    		.append(”:”);
    	Object value = retrieveObjectValue(obj, obj.getPrimaryField());
    	if (value!=null)
    		message.append(value.toString());
    	return message.toString();
    }

    /**
     * Retrieves the property name for a method name.
     * (e.g. getName will return name)
     * @param methodName
     * @return
     */
    public static String getPropertyName(String methodName) {
    	if (StringUtil.isEmpty(methodName) || methodName.length()<=3)
    		return null;
    	if (methodName.startsWith(”get”) || methodName.startsWith(”set”)) {
    		String prop = methodName.substring(4);
    		char c = Character.toLowerCase(methodName.charAt(3));
    		return c+prop;
    	} else
    		return null;
    }
    /**
     * Retrieves the getter method name for a given property.
     * (e.g. name will return getName)
     * @param propertyName
     * @return
     */
    public static String getGetterMethodName(String propertyName) {
    	if (StringUtil.isEmpty(propertyName) || propertyName.length()<=0)
    		return null;
    	char c = Character.toUpperCase(propertyName.charAt(0));
    	return “get”+c+propertyName.substring(1);
    }

	/**
	 * This method retrieves the object value that corresponds to the property specified.
	 * This method can recurse inner classes until specified property is reached.
	 *
	 * For example:
	 * obj.firstName
	 * obj.address.Zipcode
	 *
	 * @param obj
	 * @param property
	 * @return
	 */
	public static Object retrieveObjectValue(Object obj, String property) {
		if (property.contains(”.”)) {
			// we need to recurse down to final object
			String props[] = property.split(”\\.”);
			try {
				Method method = obj.getClass().getMethod(getGetterMethodName(props[0]));
				Object ivalue = method.invoke(obj);
				if (ivalue==null)
					return null;
				return retrieveObjectValue(ivalue,property.substring(props[0].length()+1));
			} catch (Exception e) {
				_log.error(”Failed to retrieve value for “+property);
				throw new InvalidImplementationException(”CrudUtil”,”retrieveObjectValue”,null,”", e);
			}
		} else {
			// let’s get the object value directly
			try {
				Method method = obj.getClass().getMethod(getGetterMethodName(property));
				return method.invoke(obj);
			} catch (Exception e) {
				_log.error(”Failed to retrieve value for “+property);
				throw new InvalidImplementationException(”CrudUtil”,”retrieveObjectValue”,null,”", e);
			}
		}
	}

	/**
	 * This method retrieves the object type that corresponds to the property specified.
	 * This method can recurse inner classes until specified property is reached.
	 *
	 * For example:
	 * obj.firstName
	 * obj.address.Zipcode
	 *
	 * @param obj
	 * @param property
	 * @return
	 */
	public static Class retrieveObjectType(Object obj, String property) {
		if (property.contains(”.”)) {
			// we need to recurse down to final object
			String props[] = property.split(”\\.”);
			try {
				Method method = obj.getClass().getMethod(getGetterMethodName(props[0]));
				Object ivalue = method.invoke(obj);
				return retrieveObjectType(ivalue,property.substring(props[0].length()+1));
			} catch (Exception e) {
				_log.error(”Failed to retrieve value for “+property);
				throw new InvalidImplementationException(”CrudUtil”,”retrieveObjectValue”,null,”", e);
			}
		} else {
			// let’s get the object value directly
			try {
				Method method = obj.getClass().getMethod(getGetterMethodName(property));
				return method.getReturnType();
			} catch (Exception e) {
				_log.error(”Failed to retrieve value for “+property);
				throw new InvalidImplementationException(”CrudUtil”,”retrieveObjectValue”,null,”", e);
			}
		}
	}
}

HibernateUtil is a utility to retrieve hibernate session separate from the usual EntityManager.

import java.net.URL;
import java.util.Set;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.scannotation.AnnotationDB;
import org.scannotation.ClasspathUrlFinder;

/**
 * This utility allows creation of Hibernate session directly.
 * Used for logging purposes.
 *
 * @author allantan
 */
public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    static {
        try {
        	URL[] urls = ClasspathUrlFinder.findResourceBases(”META-INF/persistence.xml”);
        	AnnotationDB db = new AnnotationDB();
        	db.scanArchives(urls);
        	Set entityClasses = db.getAnnotationIndex().get(javax.persistence.Entity.class.getName());
            // Create the SessionFactory
        	AnnotationConfiguration ac =  new AnnotationConfiguration();
            ac.setProperty(”hibernate.connection.datasource”, “java:comp/env/jdbc/ideyatech”);
            ac.setProperty(”hibernate.dialect”, “org.hibernate.dialect.MySQLDialect”);
            for (String clazz:entityClasses) {
            	ac.addAnnotatedClass(Class.forName(clazz));
            }
            sessionFactory = ac.buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println(”Initial SessionFactory creation failed.” + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

And finally, the sample implementation of an Auditable class:

public class InboundDocument implements Auditable {
	private static final long serialVersionUID = -7019861759834380358L;

	@Column(name = “DATE_RECEIVED”)
	@Field(index = Index.UN_TOKENIZED, store = Store.YES)
	@DateBridge(resolution = Resolution.DAY)
	private Date dateReceived;

	@Column(name = “NUMBER_OF_DAYS”)
	private Integer numberOfDays;

	@Column(name = “DATE_DUE”)
	@Field(index = Index.UN_TOKENIZED, store = Store.YES)
	@DateBridge(resolution = Resolution.DAY)
	private Date dateDue;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = “ACTION_NEEDED”)
	@Field(index = Index.TOKENIZED)
	@FieldBridge(impl = SystemCodesBridge.class)
	private SystemCodes actionNeeded;

        …
        …

	public List getAuditableFields() {
		List props = new ArrayList();
		props.add(”documentType”);
		props.add(”actionNeeded”);
		props.add(”dateReceived”);
		props.add(”dateDue”);
		props.add(”summary”);
		return props;
	}

	public String getPrimaryField() {
		return “barcodeNumber”;
	}
}

That’s it! Just implement all your auditable classes with Auditable interface. All the codes above are extracted from open-tides - an open-source web-foundation framework that can be used to quickly setup an enterprise project.



My team member has a requirement to implement JMS. I was able to dig up some stuff about JMS in my blog. I’m re-posting it here since it might be useful. For this example, I used IBM Websphere Community Edition(IBM WAS CE), which is synonymous to Geronimo(at least for the first version).

Here are the simple steps:

1. Run Geronimo or IBM WAS CE
2. Compile these two classes. Take note that you need the ff. jar files to compile and run these successfully. Here’s the list:

- geronimo-j2ee_1.4_spec.jar
- commons-logging-1.0.4.jar
- concurrent-1.3.4.jar

Note : Some jars might have new versions so be sure to use the latest one.

You’ll find it somewhere under the Geronimo or WAS CE installation directory.

3. Run the clients.

The receiver class

import java.util.logging.Logger;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.activemq.ActiveMQConnectionFactory;

public class JMSReceiver {
    protected Queue queue;

    protected String queueName = “SendReceiveQueue”;
    protected String url = “tcp://localhost:61616″;

    Logger logger = Logger.getAnonymousLogger();

    protected int ackMode = Session.AUTO_ACKNOWLEDGE;

    public static void main(String[] args) {
        JMSReceiver msgReceiver = new JMSReceiver();
        msgReceiver.run();
    }

    public void run() {
        QueueConnection connection;
        QueueSesion session;
        MessageConsumer consumer;
        try {
            ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
            onnection = (QueueConnection)connectionFactory.createConnection();
            connection.start();
            consumer = null;
            session = connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
            queue = session.createQueue(queueName);
            consumer = session.createReceiver(queue);
            logger.info(”Waiting for message (max 5)”);
            for (int i = 0; i < 5; i++) {
                Message message = consumer.receive();
                processMessage(message);
            }
            logger.info(”Closing connection”);
            } catch (Exception e) {
                logger.error(”Caught: ”,e);
            } finally {
                consumer.close();
                session.close();
                connection.close();
            }
        }
    }
    public void processMessage(Message message) {
         try {
            TextMessage txtMsg = (TextMessage) message;
            logger.info(”Received a message: ” + txtMsg.getText());
         } catch (Exception e) {
            logger.error(”Caught: ” , e);
         }
    }
}

The sender class

import java.util.logging.Logger;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage

import org.activemq.ActiveMQConnectionFactory;

public class JMSSender {

    private Queue receiveQueue = null;
    protected String queueName = “SendReceiveQueue”;
    protected String url = “tcp://localhost:61616″;
    Logger logger = Logger.getAnonymousLogger();

    public static void main(String[] args) {
        JMSSender msgSender = new JMSSender();
        msgSender.run();
    }

    public void run() {
        QueueConnection queueConn = null;
        QueueSession queueSess = null;
        TextMessage myMessage = null;
        QueueSender queueSender = null;

        try {
            ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);

            queueConn = factory.createQueueConnection();
            queueSess = queueConn.createQueueSession(false,Session.AUTO_ACKNOWLEDGE)
            receiveQueue = queueSess.createQueue(queueName);
            queueSender = queueSess.createSender(receiveQueue);
            myMessage = queueSess.createTextMessage();

            myMessage.setText(”test from JMS client 2″);
            queueSender.send(myMessage);

        } catch (Exception e) {
            logger.info(”Caught: ”, e);
        } finally {
            queueSender.close();
            queueSess.close();
            queueConn.close();
        }
    }
}


Why develop Java applications on Mac? Well, why not? Aside from the coolness factor, here are some business and technical reasons to do so.

  • Macbooks are faster and more stable than any other Vista machine.
  • Macbooks can run multiple OS - Linux, Windows and Leopard. With VMWare or Parallels, you can even run Windows within your Mac environment.
  • You have a better brand than any other outsoucing or software development company. Imagine sending 5 consultants to your clients each carrying a Macbook.
  • They have the tools needed for Java development - including Eclipse, MySQL, Xcode and any other Java IDE.
  • The graphics interface is inspiring. Who says developers don’t need inspiration?
  • Prices of software (e.g. iWorks, etc.) is cheaper than its Microsoft counterparts. Besides, most of the tools are open source.
  • Prices of Macbooks are competitive if not cheaper than other laptop brands.
  • It’s secure… it’s built on top of BSD.
  • Did I mention NO virus?
  • The coolness and intuitiveness of Time Machine encourages data backup. The video below is available now in Leopard and it works!


Mac OS X Leopard - Time Machine

Ivy Dependency Manager

Like most of us often hear, “its another framework or dependency management tool”. But what exactly differentiates Ivy from Maven?

Ivy is much easier to use. The library is simpler since it doesn’t do so much. It only focuses on dependency management and use the already famous and powerful ant to build the application. In short, ant and ivy is used side by side.

Why I Choose Ivy?

The main thing I like about Ivy is its simplicity. You can use Ivy with only ant installed on your system (and of course, java). This means that you don’t need to download any Ivy related libraries or when using eclipse, no plug-in is needed. You can run everything using ant, from installing the ivy library to downloading the dependencies.

Ivy is a dependency management tool that can use other repository such as maven repository.

Installing Ivy

Before continuing, I’ll assume that you are using ant version 1.7. You can choose to run the ant script in either console or from inside eclipse (It depends on your preference).

Here is a build.xml file that contains several targets that will be used in this post:

<?xml version="1.0" encoding="UTF-8"?>

<project name="ivytest" basedir="." default="usage" xmlns:ivy="antlib:org.apache.ivy.ant">

<property name="lib.dir" value="lib" />
<property name="build.dir" value="build" />
<property name="src.dir" value="src" />

<path id="lib.path.id">
<fileset dir="${lib.dir}" />
</path>

<path id="run.path.id">
<path refid="lib.path.id" />
<path location="${build.dir}" />
</path>

<property name="ivy.install.version" value="2.0.0-beta1" />
<property name="ivy.jar.dir" value="${basedir}/ivy" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />

<target name="usage" description="Displays the command used with this build script">
<echo message="Usage" />
<echo message="-------------------------------------------" />
<echo message="Available targets are:" />
<echo message="download-ivy --> Download ivy library" />
<echo message="install-ivy --> Install ivy library" />
<echo message="clean-libs --> Delete lib files" />
<echo message="clean-ivy --> Delete the ivy files" />
<echo message="resolve --> Resolve/Download ivy dependencies" />
</target>

<target name="download-ivy" unless="skip.download" description="Download ivy.jar">
<mkdir dir="${ivy.jar.dir}"/>
<echo message="installing ivy..."/>
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/ ${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>

<target name="install-ivy" depends="download-ivy" description="Install ivy library">
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>

<target name="clean-libs" description="Delete all libraries/dependencies">
<echo message="Deleting ${lib.dir}" />
<delete dir="${lib.dir}" />
</target>

<target name="clean-ivy" depends="clean-libs" description="Delete the all folders/files that was generated by ivy">
<echo message="Deleting ${ivy.jar.dir}" />
<delete dir="${ivy.jar.dir}" />
</target>

<target name="resolve" depends="install-ivy" description="Resolve the dependencies">
<ivy:retrieve/>
</target>

<target name="run" depends="resolve" description="Compile and run the project">
<mkdir dir="${build.dir}" />
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="lib.path.id" />
<java classpathref="run.path.id" classname="Main"/>
</target>

</project>

Invoke “ant install-ivy” and the ivy jars will be downloaded. A new folder named “ivy” will be created with the ivy.jar in it.

Dowloading Dependencies

By default ivy uses maven 2 repository but you can certainly define other repository (It will be covered on later post).

The build.xml above contains a target named “resolve”. Running the target will cause the Ivy to download defined dependencies on ivy.xml (ivy.xml is needed since all the dependencies are defined on that file). Here is an example of ivy.xml:

<?xml version="1.0" encoding="UTF-8"?>

<ivy-module version="2.0">
<info organisation="ideyatech" module="ivytest"/>
<dependencies>
<dependency org="log4j" name="log4j" rev="1.2.8"/>
</dependencies>
</ivy-module>

The code above downloads the log4j and its dependencies from the defined repository (in our case, maven repo). I chose to use log4j because in the next section, I’ll be demonstrating to compile a simple java class that uses a Ivy managed library. Invoke “ant resolve” now and you will see a message saying that the library is being downloaded.

Compiling The Application

Main.java:

import org.apache.log4j.Logger;
public class Main {
    private static final Logger log = Logger.getLogger(Main.class);
    public static void main(String[] args) {
        System.out.println(”Printed using system.out.println”);
        log.info(”Printed using log4j logger”);
     }
}

The sample java file won’t really print the message being logged. The purpose of this example is to test compiling the application with the Ivy libraries being referenced. The idea is to simply add the “lib” dir to the classpath on compilation.

Try invoking “ant run” and the application will be compiled and executed. Note that invoking the “ant clean-libs” and removing the “resolve” dependency on run target will cause the compilation to throw some error.

References:

http://ant.apache.org/ivy/index.html

Note:

  • Ivy logo is property of Apache Ivy and is not connected with Ideyatech.



Today, we attended the Sun Tech Days Conference at the Makati Shangrila. Aside from the great food and freebies, I enjoyed the whole experience. There were several things I learned during the second day of the 3-day conference. Here’s to recap what I learned and observed:

Sun Tech Days

  • Java 6 has some nice features including Scripting Language Support (JSR 223) and Web Service Integration. I agree that these 2 features are very common and should be part of the standard Java. I’m not sure about JDBC 4.0; with the success of JPA, JDBC might not be that useful anymore.
  • Grails is cool, but not necessarily great. I think it still needs improvement to be able to compete in the enterprise, if at all possible. My main concern with template codes is “customizability”. But it’s still cool.
  • Sun admitted their problems with Java 6, such as slow start-up and large codebase. I think this is a good sign for the future of Java.
  • Netbeans has improved since I switched to Eclipse three years ago. It supports a ton of platforms/frameworks and has a lot of productivity tools. I believe Netbeans is probably worth revisiting.
  • Half of the conference attendees are going to the Enterprise track, which means there is more demand for web applications development rather than desktop (Swing, SWT) or system administration.
  • The “new” technologies that the speakers discussed were the same technologies two years ago. We have been already using these technologies (such as Ajaz, JPA, and ESB) in our projects. Either Sun didn’t do a good job in looking for resource persons, or Ideyatech is just updated with the latest technology! (The latter is most probably true… hehe) Anything else new?
  • Open-source is confusing - everyone else wanted to be the best platform/framework, and developers are confused which one to use. Even Sun promotes several conflicting/competing technologies - Seam vs. Grails vs. JSF, JDBC vs. JPA, GlassFish vs. JWS. With the myriad of platforms available, which one works best?
The conference was way too crowded, it took me 30 minutes in line to get lunch and coffee. There weren’t enough seats on some rooms because most people seem to be more interested on Enterprise Track (Grails, JPA, etc), rather than Solaris. And what’s even worse is that some of the speakers can’t even speak English very well. I guess these events were meant more for marketing and networking, rather than sharing and obtaining new technologies.

As recommended by Yahoo on YSlow - tip #1: Make fewer HTTP request and tip #10: Minify javascript- we aim to implement these tips on all our projects with minimal head-ache. While these recommendations are truly useful, implementing them can be quite tedious and challenging. Consider having to maintain multiple min versions of the javascript and the files that links to them! So to alleviate the problem, we created a tool called low-tides (as part of open-tides) that helps automate the merging and minification of css and js files.

So what is the rationale behind the the tool?

  • Maintenance of minified js and css is a nightmare. Keeping separate js and css files for development and production can be very confusing. Some developers might change the production version without syncing with the development version. So eventually, changes to different files becomes a mess — Which one has the latest code?
  • Maintenance of html files that links to proper javascript and css is another problem. Since minified versions are likely to have different filename (e.g. basic-min.js), html codes that reference the scripts need to be changed. This leads to having multiple copies of html files… again.
  • Versioning of html, css, and js files introduce a whole new set of configuration items. Imagine bullets #1 and #2 getting multiplied across a number of version releases!
  • At the time of this writing, there are no tools available that can merge multiple javascripts. The development version of javascript needs to be logically separated while the production version needs to be merged (for lesser http request). Moreover, merging javascript is not straightforward. Some javascripts need to be pre-loaded while others can be postponed.

I suppose by now you get the picture. The solution we propose to this configuration problem is simple:  Always change from the development version and have a deployment script automatically create the production version. As such, files are always maintained from the development version - but the key to this approach is to ensure that the script for creating production versions is quick and easy-to-use.

Now here comes Low-tides. Low-tides is a Java-based program that automatically analyzes html files for javascript and css includes. It will merge includes that are in sequence into a single file and minify it. In summary, it automatically solves all the problems mentioned above.

You can download it here: http://code.google.com/p/open-tides/downloads/list

Usage instructions are available here: http://code.google.com/p/open-tides/wiki/LowTides

Has anyone ever tried looking at OSWorkflow recently? It is unfortunate that this OpenSymphony project has been shelved. However, I found value in this lightweight workflow tool — for one, being lightweight makes it simple and easy to work with, plus, integration with Spring and Hibernate is readily available.

However, since OSWorkflow stopped development, there had been no support for JPA-based applications anymore. Fortunate for those interested in making JPA work on OSWorkflow via Spring, I was able to tweak some of the OSWorkflow classes and integrate it with JPA Session.

The primary problem in integrating OSWorkflow with JPA is the Session. The original session used by OSWorkflow (SpringHibernateOSWorkflowStore) is a sessionFactory injected via Spring. Since JPA uses EntityManager, the sessionFactory and EntityManager are on different transactions.

The solution is to extend AbstractHibernateWorkflowStore and use session from EntityManager. Here’s the code:

public class JPAHibernateWorkflowStore extends AbstractHibernateWorkflowStore {
    @PersistenceContext
    private EntityManager em;

	@Override
	protected Object execute(InternalCallback action) throws StoreException {
        try {
    		return action.doInHibernate((Session)em.getDelegate());
        } catch (StoreException e) {
            throw new RuntimeException(e);
        }
	}

	public void init(Map arg0) throws StoreException {
		// TODO Auto-generated method stub
	}

	/**
	 * @param em the em to set
	 */
	public void setEntityManager(EntityManager em) {
		this.em = em;
	}
}

Afterwards, use JPAHibernateWorkflowStore instead of SpringHibernateWorkflowStore as your workflow store. You will also need to copy HibernateCurrentStep.hbm.xml, HibernateHistoryStep.hbm.xml and HibernateWorkflowEntry.hbm.xml (under com.opensymphony.workflow.spi.hibernate3) to META-INF (along with persistence.xml). This will ensure that hbm mappings are recognized by the EntityManager.

Well, that’s basically it. If you are having a hard time following my instructions, try getting the standard SpringHibernateWorkflowStore to work first. Afterwards, change implementation to JPA-based approach.

Ciao!