Archive Page 2

02
Nov
10

Android Adapters

I’ve been fooling around with Android for a couple of weeks.Android.. I bought a Motorola Milestone, downloaded the ADT plugin, a few device images and started reading and coding…
I have to admit that the Android Architecture has some ingenious points, one example is the idea of having one process (a Dalvik VM instance) hosting both application activities and also its services but this will be subject for another post (android.os.Looper and Handler are worth mentioning too).
Getting back to the reason for the post…

Android Adapter vs Swing TableModel

Having once used Java Swing Toolkit my first impression when I saw Android SimpleAdapter was that I was seeing a DefaultTableModel sibling but the reality was that I couldn’t be more wrong!
Android Adapters and ListViews are more similar to Java’s c:forEach tag (Yeah, I know… probably you thought I would use a Swing metaphor but I couldn’t think of one) since it does not impose a resulting Widget, it is up to the Adapter getView method to determine which will be the rendered View instance. Swing’s TableModel only determines the content that will be displayed but it can’t redefine the UI component JTable uses. This responsibility on Swing is delegated to JTable getDefaultRenderer method.

Android SimpleAdapter

Android’s SimpleAdapter employs a rather simple yet smart strategy: you handle it Composite component ID that will be displayed for each row of a List of HashMaps. The mapping of each subcomponent from the composite component is performed by two Arrays that are also passed at SimpleAdapter construct time. These arrays maps the Keys from the HashMap into the subcomponent IDs.

SimpleAdapter drawback

What I sincerely miss with the SimpleAdapter approach is a more direct mapping between domain objects and the ListView. The developer ends up coding a plumbing code that moves data from Domain Objects into the HashMap and this code easily violates the DRY principle.
Although reflection poses a performance penalty I’ll try to see if a ReflectionAdapter based on SimpleAdapter is a valid alternative.

Advertisements
07
Aug
10

Fluent Interfaces for Searching Hibernate Entities

Recently I changed my job, I am now at my previous employee… the reasons are out of scope for this post so let’s get back to the real point… in the process of developing the software that is scope of this new project a colleague suggested that we should adopt fluent interfaces for the creation of our entities. Sincerely, the term fluent interfaces was new to me but I’ve been a Hibernate user since two dot something (a long time ago) and since Hibernate makes extensive usage of fluent interfaces it turned out not to be that much news. In fact I have to admit that fluent interfaces increase code readability a lot!

Fluent Interfaces for POJOs

The code for the POJOs fluent interfaces was based on a post on Code Monkeyism blog. After adopting this code we started to think about further improvements to that class that made this handle collections, direct access for public fields whenever possible and we crafted an extension to JavaBeans style that let us hide the setter for collections, make the getter return an immutable list and added an addSomething method (all following further good practices that were also on Code Monkeyism).
Project development went on then we hit the point in where we needed to develop our entity search infrastructure. Our first conclusion was that we would probably need a counting facility for our queries and this would probably rule out the usage of NamedQueries since we would need two for each of them (one for counting and one for returning the data – anyways we are still considering if we’ll ever use counting queries for pagination), next obvious point: pagination. But the key point for our search infrastructure was that we had DAOs and we weren’t willing to expose HibernateSession or EntityManagers and we are going to have predefined searches that could have different parameters (some mandatory, some optional). This predefined search scenario is one of the ideal applications for something similar to the fluent interface idea for creating POJOs except that if we resorted to dynamically creating queries this could turn to a huge effort (not to mention a huge wheel reinvention since Hibernate has the incredible Criteria API).

The Solution for Searching Hibernate Entities

The trick for having fluent interfaces on top of hibernate criterias is based around two things:

  1. Basing the solution on top of Criteria ability of expressing constraints and the most important part: creating subcriterias upon entity association navigation
  2. Providing an way of composing the fluent interfaces for expressing collections and integrating this with the concept of the subcriteria

The first point is to implement the InvocationHandler class and making it able to store a Criteria instance which will be responsible for storing the Root Criteria instance and also the SubCriterias (see Subcriteria class) when InvocationHandlers are created for the entity associations.

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
	try {
		String name = m.getName();
      		if ("list".equals(name)) {
        		return criteria.list();
		}
		else if ("count".equals(name)) {
			return criteria.setProjection(Projections.rowCount());
		}
		else {
			if (args == null || args.length == 0) {
				Criteria subCriteria = criteria.createCriteria(name);
				//create another InvocationHandler instance enclosing the newly created subCriteria and pass it to Proxy.newProxyInstance	and return the just created proxy
			}
			else {
				criteria.add(Restrictions.eq(name, args[0]));
			}
		}
    return proxy;
}

The next step is to develop the interfaces, in order to make it easier to understand the idea I’ll provide a sample domain model to make things clearer.

Sample Domain Model

We are going to use the well known Order, OrderItem, Product model in order to make things clearer. Below is a class diagram for our model:

Sample Domain Model

Sample Domain Model


Our fluent interfaces for those classes would (hugely simplified) be:

public interface OrderFluentSearch {
	OrderFluentSearch code(String code);
	OrderItemFluentSearch items();
	List<Order> list();
	long count();
}

The OrderItemFluentSearch would be as follows:

public interface OrderItemFluentSearch {
	OrderItemFluentSearch quantity(int quantity);
	ProductFluentSearch product();
	List<OrderItem> list();
	long count();
}

And finally our ProductFluentSearch interface would be similar to the one below:

public interface ProductFluentSearch {
	ProductFluentSearch code(String code);
	List<Product> list();
	long count();
}

Suppose now that you had a with() method in your Order DAO similar to the one on the Code Monkeyism blog post a search for Orders with an item that references a product with code “10” would be as easy as:

	OrderFluentSearch search = orderDAO.with();
	search.items().product().code("10");
	search.list();

Pretty readable isn’t it? But it still has some drawbacks…
One obvious is that it isn’t possible to express it into a single line. The other one is that we still have an extra interface that wont get automatically renamed when we rename the entity class but I feel like there is one way of fixing this.

Future improvements

Although this idea presents a great improvement regarding code readability of Criteria queries expressed in an application it is still vulnerable to renames on classes attributes. One possibility that I’ll give a try is to use a DSL similar to the one employed on JMock that uses a combination of custom crafted CGLIB classes based on entity classes and a ThreadLocal composition process that allows methods that have no linking between them to share context.

15
Jul
10

JBoss Seam application blueprint

I am a JBoss Seam user since its v2.0 alpha something (back in 2007). I still remember the hard decision in picking up the alpha and later beta version instead of sticking with the stable but feature missing 1.2.
Seam is an incredible framework for web applications, it covers the majority of the requirements you have in such applications. But this tremendous power comes with a price, it is often hard to find the best combination in the first application you develop. Its variety of contexts combined with the possibilities of handling the page data through injection and outjection results in a challenge for the Seam newbie, not to mention the possibilities of handling the flow between pages…

That’s the reason I thought about developing a blueprint for Seam applications… I know that for now SeamGen generated applications are considered blueprints for Seam applications but I really feel like there are plenty of missing parts. SeamGen applications don’t use Conversation scopes (only to give an example cause the list of Seam features that are not explored by a SeamGen application are enormous). I am also sure that I won’t develop THE blueprint for a Seam application but at least I’ll try to document all the knowledge I’ve gathered from a few projects and a few POCs.

Managing page flow and conversation demarcation

Seam has a neat feature for specifying page flow: pages.xml and view-id.page.xml files. The first one is able to specify navigation rules for every view in the application and should be used for specifying global rules as when Exceptions are thrown or for actions that have the same result independent of the current view. This post presents good practices for defining page flows using Seam. There is even one thing covered in this post that I recommend: specifying conversation demarcation on view-id.page.xml files but there is one thing suggested on this post that I need to investigate carefully: the impact of joining conversations instead of spawning new ones. I agree with the post that not joining may spawn unwanted conversations and thus increase memory usage but I cant say beforehand which are the drawbacks of joining a conversation.
A good way of redirecting the user to a new view with total control over conversation propagation is by using the s:button tag. This tag has one property named view that specifies the target view-id and another one called propagation in which you can specify the conversation propagation. The following example redirects to a view named “newUser.xhtml” and suspending the current conversation scope:

<s:button value="New User" view="/newUSer.xhtml" propagation="none"/>

And if this view required a conversation scope this could be specified on newUser.page.xml with the <begin-conversation> tag.

Authentication and authorization

Everytime that you are developing an application targeting a deploy on a full fledged J2EE application server and if possible, prefer to delegate authentication and authorization to the Application Server JAAS. The following code when configured on Seam components.xml delegates to the specified JAAS domain:

<security:identity jaas-config-name="myJAASDomainName" remember-me="true"/>

This avoids the rather limited approach of specifying an authenticator method on an application Seam component since a JAAS authenticated user will be propagated all the way down the EJB container (in case you are using it).

That’s all for now I’ll try to update this post as soon as I format more knowledge around JBoss Seam.

27
Jun
10

Hibernate Isolater.doIsolatedWork WebSphere compliant implementation based on UOWManager.runUnderUOW

Recently I decided to deepen my investigation upon Spring WebSphereUowTransactionManager. I always thought it was a shame Hibernate wasn’t fully supported under WebSphere and decided to investigate it a little more since I had the impression that after my first investigation that resulted in my first attempt of extending current hibernate transaction lookup for WebSphere it would take only a little more effort.

Considerations for the Implementation

The first decision taken for the implementation was that it should have no compile-time dependency upon WebSphere as Hibernate original TransactionManager and TransactionManagerLookup. This resulted in having all the calls to UOWManager and UOWSynchronizationRegistry using reflection and hence we needed to pass a UOWAction instance to UOWManager.runUnderUOW I chose to use a Java Dynamic Proxy.

Changes to Hibernate and Implementation

Since I didn’t want to embed another inner class into Isolater.java I made the Delegate interface public instead of private. The last trick was to return my delegate in place of JtaDelegate when configured for WebSphere. I sincerely feel like a factory was a better option over here but I didn’t take any time to investigate where to plug it. The resulting code for Isolater is show below:

	public static void doIsolatedWork(IsolatedWork work, SessionImplementor session) throws HibernateException {
		boolean isJta = session.getFactory().getTransactionManager() != null;
		if ( isJta ) {
			if (session.getFactory().getTransactionManager() instanceof UOWTransactionManagerAdapter)
				new WebSphereUOWDelegate(session).delegateWork(work, true);
			else
				new JtaDelegate( session ).delegateWork( work, true );
		}
		else {
			new JdbcDelegate( session ).delegateWork( work, true );
		}
	}

	public static void doNonTransactedWork(IsolatedWork work, SessionImplementor session) throws HibernateException {
		boolean isJta = session.getFactory().getTransactionManager() != null;
		if ( isJta ) {
			if (session.getFactory().getTransactionManager() instanceof UOWTransactionManagerAdapter)
				new WebSphereUOWDelegate(session).delegateWork(work, false);
			else
				new JtaDelegate( session ).delegateWork( work, false );
		}
		else {
			new JdbcDelegate( session ).delegateWork( work, false );
		}
	}

	public static interface Delegate {
		public void delegateWork(IsolatedWork work, boolean transacted) throws HibernateException;
	}

The resulting Isolater.Delegate implementation for WebSphere delegates the doTheWork to a method on UOWTransactionManagerAdapter that creates the UOWAction proxy and carries it on to UOWManager.

	private void doTheWork(IsolatedWork work, UOWTransactionManagerAdapter transactionManager, boolean transacted) {
		try {
			// obtain our isolated connection
			Connection connection = session.getFactory().getConnectionProvider().getConnection();
			try {
				// do the actual work
				if (transacted)
					transactionManager.doIsolatedWork(work, connection, false, true);
				else
					transactionManager.doIsolatedWork(work, connection, false, false);
			}
			catch ( HibernateException e ) {
				throw e;
			}
			catch ( Exception e ) {
				throw new HibernateException( "Unable to perform isolated work", e );
			}
			finally {
				try {
					// no matter what, release the connection (handle)
					session.getFactory().getConnectionProvider().closeConnection( connection );
				}
				catch ( Throwable ignore ) {
					log.info( "Unable to release isolated connection [" + ignore + "]" );
				}
			}
		}
		catch ( SQLException sqle ) {
			throw JDBCExceptionHelper.convert(
					sqlExceptionConverter(),
					sqle,
					"unable to obtain isolated JDBC connection"
			);
		}
	}

A class implementing InvocationHandler is responsible for delegating the UOWAction implementation to the Hibernate IsolatedWork

static class UOWInvocationHandler implements InvocationHandler {

private IsolatedWork work;
private Connection connection;

public UOWInvocationHandler(IsolatedWork work, Connection connection) {
super();
this.work = work;
this.connection = connection;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
work.doWork(connection);
return void.class;
}

}

Finally we have the doIsolatedWork method on UOWTransactionManagerAdapter

		public void doIsolatedWork(IsolatedWork work, Connection conn, boolean join, boolean global) throws SystemException, InvalidTransactionException, IllegalStateException {
			Object p = Proxy.newProxyInstance
	          (uowActionClass.getClassLoader(),
	                new Class[] { uowActionClass }, new UOWInvocationHandler(work, conn));
			try {
				runUnderUOWMethod.invoke(uowManager, new Object[]{global ? UOW_TYPE_GLOBAL_TRANSACTION : UOW_TYPE_LOCAL_TRANSACTION, Boolean.FALSE.booleanValue(),p});
			} catch (IllegalArgumentException e) {
				throw new HibernateException(e);
			} catch (IllegalAccessException e) {
				throw new HibernateException(e);
			} catch (InvocationTargetException e) {
				throw (HibernateException) e.getTargetException().getCause();
			}
		}

I still need to develop a test application for the Isolater.doNonTransactedWork method… if anyone knows how Hibernate triggers that flow and is willing to give a try, please let me know on the comments.
With a patched Hibernate you only need to configure the hibernate.cfg.xml with the following transaction.manager_lookup_class:

		   <property name="hibernate.transaction.manager_lookup_class">
		       org.hibernate.transaction.WebSphereUOWTransactionLookup
           </property>

I am providing a Diff for anyone willing to patch Hibernate and testing this implementation.

diff -r -d -N src/org/hibernate/engine/transaction/Isolater.java ..\..\hib-orig\src/org/hibernate/engine/transaction/Isolater.java
40d39
< import org.hibernate.transaction.WebSphereUOWTransactionLookup.UOWTransactionManagerAdapter;
68,71c67
< 			if (session.getFactory().getTransactionManager() instanceof UOWTransactionManagerAdapter)
< 				new WebSphereUOWDelegate(session).delegateWork(work, true);
< 			else
< 				new JtaDelegate( session ).delegateWork( work, true );
---
> 			new JtaDelegate( session ).delegateWork( work, true );
89,92c85
< 			if (session.getFactory().getTransactionManager() instanceof UOWTransactionManagerAdapter)
< 				new WebSphereUOWDelegate(session).delegateWork(work, false);
< 			else
< 				new JtaDelegate( session ).delegateWork( work, false );
---
> 			new JtaDelegate( session ).delegateWork( work, false );
103c96
< 	public static interface Delegate {
---
> 	private static interface Delegate {
diff -r -d -N src/org/hibernate/engine/transaction/WebSphereUOWDelegate.java ..\..\hib-orig\src/org/hibernate/engine/transaction/WebSphereUOWDelegate.java
1,89d0
< package org.hibernate.engine.transaction;
<
< import java.sql.Connection;
< import java.sql.SQLException;
<
< import org.hibernate.HibernateException;
< import org.hibernate.engine.SessionImplementor;
< import org.hibernate.engine.transaction.Isolater.Delegate;
< import org.hibernate.exception.JDBCExceptionHelper;
< import org.hibernate.exception.SQLExceptionConverter;
< import org.hibernate.transaction.WebSphereUOWTransactionLookup.UOWTransactionManagerAdapter;
< import org.slf4j.Logger;
< import org.slf4j.LoggerFactory;
<
< /**
<  * An isolation delegate for WebSphere UOW-based transactions.  Essentially calls UOW for
<  * suspending any current transaction, does the work in a new transaction, and then
<  * resumes the initial transaction (if there was one).
<  */
< public class WebSphereUOWDelegate implements Delegate {
< 	private static final Logger log = LoggerFactory.getLogger( Isolater.class );
<
< 	private final SessionImplementor session;
<
< 	public WebSphereUOWDelegate(SessionImplementor session) {
< 		this.session = session;
< 	}
<
< 	public void delegateWork(IsolatedWork work, boolean transacted) throws HibernateException {
< 		UOWTransactionManagerAdapter transactionManager = (UOWTransactionManagerAdapter) session.getFactory().getTransactionManager();
<
< 		// then peform the requested work
< 		if ( transacted ) {
< 			doTheWorkInNewTransaction( work, transactionManager );
< 		}
< 		else {
< 			doTheWorkInNoTransaction( work,  transactionManager);
< 		}
< 	}
<
< 	private void doTheWorkInNewTransaction(IsolatedWork work, UOWTransactionManagerAdapter transactionManager) {
< 		doTheWork( work , transactionManager, true);
< 	}
<
< 	private void doTheWorkInNoTransaction(IsolatedWork work, UOWTransactionManagerAdapter transactionManager) {
< 		doTheWork( work , transactionManager, false);
< 	}
<
< 	private void doTheWork(IsolatedWork work, UOWTransactionManagerAdapter transactionManager, boolean transacted) {
< 		try {
< 			// obtain our isolated connection
< 			Connection connection = session.getFactory().getConnectionProvider().getConnection();
< 			try {
< 				// do the actual work
< 				if (transacted)
< 					transactionManager.doIsolatedWork(work, connection, false, true);
< 				else
< 					transactionManager.doIsolatedWork(work, connection, false, false);
< 			}
< 			catch ( HibernateException e ) {
< 				throw e;
< 			}
< 			catch ( Exception e ) {
< 				throw new HibernateException( "Unable to perform isolated work", e );
< 			}
< 			finally {
< 				try {
< 					// no matter what, release the connection (handle)
< 					session.getFactory().getConnectionProvider().closeConnection( connection );
< 				}
< 				catch ( Throwable ignore ) {
< 					log.info( "Unable to release isolated connection [" + ignore + "]" );
< 				}
< 			}
< 		}
< 		catch ( SQLException sqle ) {
< 			throw JDBCExceptionHelper.convert(
< 					sqlExceptionConverter(),
< 					sqle,
< 					"unable to obtain isolated JDBC connection"
< 			);
< 		}
< 	}
<
< 	private SQLExceptionConverter sqlExceptionConverter() {
< 		return session.getFactory().getSQLExceptionConverter();
< 	}
<
< }
diff -r -d -N src/org/hibernate/transaction/WebSphereUOWTransactionLookup.java ..\..\hib-orig\src/org/hibernate/transaction/WebSphereUOWTransactionLookup.java
1,304d0
< package org.hibernate.transaction;
<
< import java.lang.reflect.InvocationHandler;
< import java.lang.reflect.InvocationTargetException;
< import java.lang.reflect.Method;
< import java.lang.reflect.Proxy;
< import java.sql.Connection;
< import java.util.Properties;
<
< import javax.naming.NamingException;
< import javax.transaction.HeuristicMixedException;
< import javax.transaction.HeuristicRollbackException;
< import javax.transaction.InvalidTransactionException;
< import javax.transaction.NotSupportedException;
< import javax.transaction.RollbackException;
< import javax.transaction.Status;
< import javax.transaction.Synchronization;
< import javax.transaction.SystemException;
< import javax.transaction.Transaction;
< import javax.transaction.TransactionManager;
< import javax.transaction.xa.XAResource;
<
< import org.hibernate.HibernateException;
< import org.hibernate.engine.transaction.IsolatedWork;
< import org.hibernate.transaction.WebSphereUOWTransactionLookup.UOWTransactionManagerAdapter.UOWTransactionAdapter;
< import org.hibernate.util.NamingHelper;
<
< /**
<  * @author rafaelri Support for proprietary interfaces for registering
<  *         synchronizations in WebSphere 6.1+
<  */
< public class WebSphereUOWTransactionLookup implements TransactionManagerLookup {
<
< 	private static final String UOW_MANAGER_JNDI = "java:comp/websphere/UOWManager";
< 	private static final String UOW_SYNCHRONIZATION_MANAGER_JNDI = "java:comp/websphere/UOWSynchronizationRegistry";
<
< 	public TransactionManager getTransactionManager(Properties props)
< 			throws HibernateException {
< 		return new UOWTransactionManagerAdapter(props);
< 	}
<
< 	public String getUserTransactionName() {
< 		return "java:comp/UserTransaction";
< 	}
<
< 	public static class UOWTransactionManagerAdapter implements TransactionManager {
< 		private final Object uowManager;
< 		private final Class uowManagerClass;
< 		private final Object uowSynchronizationRegistry;
< 		private final Class uowSynchronizationRegistryClass;
< 		private final Class uowActionClass;
< 		private final Method registerSynchronizationMethod;
< 		private final Method setRollbackOnlyMethod;
< 		private final Method setUOWTimeoutMethod;
< 		private final Method getUOWTimeoutMethod;
< 		private final Method runUnderUOWMethod;
< 		public final int UOW_TYPE_GLOBAL_TRANSACTION;
< 		public final int UOW_TYPE_LOCAL_TRANSACTION;
<
< 		private final Properties properties;
< 		private final Method getLocalIdMethod;
<
< 		private UOWTransactionManagerAdapter(Properties props) {
< 			this.properties = props;
< 			try {
< 				uowManager = NamingHelper.getInitialContext(props).lookup(
< 						UOW_MANAGER_JNDI);
< 				uowManagerClass = Class.forName("com.ibm.wsspi.uow.UOWManager");
< 				setRollbackOnlyMethod = uowManagerClass.getMethod(
< 						"setRollbackOnly", new Class[] {});
< 				uowActionClass = Class.forName("com.ibm.wsspi.uow.UOWAction");
< 				runUnderUOWMethod = uowManagerClass.getMethod("runUnderUOW",
< 						new Class[] {int.class, boolean.class, uowActionClass});
< 				setUOWTimeoutMethod = uowManagerClass.getMethod(
< 						"setUOWTimeout", new Class[] { int.class, int.class });
< 				getUOWTimeoutMethod = uowManagerClass.getMethod(
< 						"getUOWTimeout", new Class[] {});
<
< 				uowSynchronizationRegistry = NamingHelper.getInitialContext(
< 						props).lookup(UOW_SYNCHRONIZATION_MANAGER_JNDI);
< 				uowSynchronizationRegistryClass = Class
< 						.forName("com.ibm.websphere.uow.UOWSynchronizationRegistry");
<
< 				UOW_TYPE_LOCAL_TRANSACTION = uowSynchronizationRegistryClass.getDeclaredField("UOW_TYPE_LOCAL_TRANSACTION").getInt(null);
<
< 				UOW_TYPE_GLOBAL_TRANSACTION = uowSynchronizationRegistryClass.getDeclaredField("UOW_TYPE_GLOBAL_TRANSACTION").getInt(null);
<
< 				registerSynchronizationMethod = uowSynchronizationRegistryClass
< 						.getMethod("registerInterposedSynchronization",
< 								new Class[] { Synchronization.class });
< 				getLocalIdMethod = uowSynchronizationRegistryClass.getMethod(
< 						"getLocalUOWId", new Class[] {});
<
< 			} catch (ClassNotFoundException cnfe) {
< 				throw new HibernateException(cnfe);
< 			} catch (NoSuchMethodException nsme) {
< 				throw new HibernateException(nsme);
< 			} catch (NamingException ne) {
< 				throw new HibernateException(ne);
< 			} catch (IllegalArgumentException e) {
< 				throw new HibernateException(e);
< 			} catch (SecurityException e) {
< 				throw new HibernateException(e);
< 			} catch (IllegalAccessException e) {
< 				throw new HibernateException(e);
< 			} catch (NoSuchFieldException e) {
< 				throw new HibernateException(e);
< 			}
< 		}
<
< 		public void doIsolatedWork(IsolatedWork work, Connection conn, boolean join, boolean global) throws SystemException, InvalidTransactionException, IllegalStateException {
< 			Object p = Proxy.newProxyInstance
< 	          (uowActionClass.getClassLoader(),
< 	                new Class[] { uowActionClass }, new UOWInvocationHandler(work, conn));
< 			try {
< 				runUnderUOWMethod.invoke(uowManager, new Object[]{global ? UOW_TYPE_GLOBAL_TRANSACTION : UOW_TYPE_LOCAL_TRANSACTION, Boolean.FALSE.booleanValue(),p});
< 			} catch (IllegalArgumentException e) {
< 				throw new HibernateException(e);
< 			} catch (IllegalAccessException e) {
< 				throw new HibernateException(e);
< 			} catch (InvocationTargetException e) {
< 				throw (HibernateException) e.getTargetException().getCause();
< 			}
< 		}
<
< 		public void begin() throws NotSupportedException, SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public void commit() throws RollbackException, HeuristicMixedException,
< 				HeuristicRollbackException, SecurityException,
< 				IllegalStateException, SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public int getStatus() throws SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public Transaction getTransaction() throws SystemException {
< 			return new UOWTransactionAdapter(properties);
< 		}
<
< 		public void resume(Transaction txn) throws InvalidTransactionException,
< 				IllegalStateException, SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public void rollback() throws IllegalStateException, SecurityException,
< 				SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public void setRollbackOnly() throws IllegalStateException,
< 				SystemException {
< 			try {
< 				setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
< 			} catch (IllegalArgumentException e) {
< 				throw new RuntimeException(e);
< 			} catch (IllegalAccessException e) {
< 				throw new RuntimeException(e);
< 			} catch (InvocationTargetException e) {
< 				// is there any way to better handle this???
< 				if (e.getTargetException() instanceof IllegalStateException)
< 					throw ((IllegalStateException) e.getTargetException());
< 				else if (e.getTargetException() instanceof SystemException)
< 					throw ((SystemException) e.getTargetException());
< 				else
< 					throw new RuntimeException(e.getTargetException());
< 			}
< 		}
<
< 		public void setTransactionTimeout(int i) throws SystemException {
< 			try {
< 				setUOWTimeoutMethod.invoke(uowManager, new Object[] {
< 						UOW_TYPE_GLOBAL_TRANSACTION,
< 						i });
< 			} catch (IllegalArgumentException e) {
< 				throw new RuntimeException(e);
< 			} catch (IllegalAccessException e) {
< 				throw new RuntimeException(e);
< 			} catch (InvocationTargetException e) {
< 				// is there any way to better handle this???
< 				if (e.getTargetException() instanceof IllegalStateException)
< 					throw ((IllegalStateException) e.getTargetException());
< 				else if (e.getTargetException() instanceof SystemException)
< 					throw ((SystemException) e.getTargetException());
< 				else
< 					throw new RuntimeException(e.getTargetException());
< 			}
< 		}
<
< 		public Transaction suspend() throws SystemException {
< 			throw new UnsupportedOperationException();
< 		}
<
< 		public class UOWTransactionAdapter implements Transaction {
<
< 			private Object localId;
<
< 			private UOWTransactionAdapter(Properties props) {
< 				try {
< 					localId = getLocalIdMethod.invoke(
< 							uowSynchronizationRegistry, new Object[] {});
< 				} catch (Exception e) {
< 					throw new HibernateException(e);
< 				}
< 			}
<
< 			public void registerSynchronization(
< 					final Synchronization synchronization)
< 					throws RollbackException, IllegalStateException,
< 					SystemException {
<
< 				try {
< 					registerSynchronizationMethod.invoke(
< 							uowSynchronizationRegistry,
< 							new Object[] { synchronization });
< 				} catch (Exception e) {
< 					throw new HibernateException(e);
< 				}
<
< 			}
<
< 			public int hashCode() {
< 				return getLocalId().hashCode();
< 			}
<
< 			public boolean equals(Object other) {
< 				if (!(other instanceof UOWTransactionAdapter))
< 					return false;
< 				UOWTransactionAdapter that = (UOWTransactionAdapter) other;
< 				return getLocalId().equals(that.getLocalId());
< 			}
<
< 			private Object getLocalId() {
< 				return localId;
< 			}
<
< 			public void commit() throws RollbackException,
< 					HeuristicMixedException, HeuristicRollbackException,
< 					SecurityException, IllegalStateException, SystemException {
< 				throw new UnsupportedOperationException();
< 			}
<
< 			public boolean delistResource(XAResource resource, int i)
< 					throws IllegalStateException, SystemException {
< 				throw new UnsupportedOperationException();
< 			}
<
< 			public boolean enlistResource(XAResource resource)
< 					throws RollbackException, IllegalStateException,
< 					SystemException {
< 				throw new UnsupportedOperationException();
< 			}
<
< 			public int getStatus() throws SystemException {
< 				return new Integer(0).equals(getLocalId()) ? Status.STATUS_NO_TRANSACTION
< 						: Status.STATUS_ACTIVE;
< 			}
<
< 			public void rollback() throws IllegalStateException,
< 					SystemException {
< 				throw new UnsupportedOperationException();
< 			}
<
< 			public void setRollbackOnly() throws IllegalStateException,
< 					SystemException {
< 				try {
< 					setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
< 				} catch (Exception e) {
< 					throw new HibernateException(e);
< 				}
< 			}
< 		}
<
< 	}
<
< 	public Object getTransactionIdentifier(Transaction txn) {
< 		if (!(txn instanceof UOWTransactionAdapter))
< 			throw new IllegalStateException("Invalid Transaction class");
< 		UOWTransactionAdapter tx = (UOWTransactionAdapter) txn;
< 		return tx.localId;
< 	}
<
< 	static class UOWInvocationHandler implements InvocationHandler {
<
< 		private IsolatedWork work;
< 		private Connection connection;
<
< 		public UOWInvocationHandler(IsolatedWork work, Connection connection) {
< 			super();
< 			this.work = work;
< 			this.connection = connection;
< 		}
< 		public Object invoke(Object proxy, Method method, Object[] args)
< 				throws Throwable {
< 			work.doWork(connection);
< 			return void.class;
< 		}
<
< 	}
<
< }
24
May
10

Instrumentation and Monitoring as means of problem detection and resolution

While designing the last big project I worked on we chose to place some monitoring code in specific points of the application. Those metrics were meant for emitting information targeted at business users but also to technical users, this information was then split according to audience through the respective JMX agents used (was it a Tivoli ITCAM agent or a JOPR agent).
At first we were expecting only that this could provide us valuable information for live environment such as when we had anything abnormal on the legacy software we were integrating with but we ended up noticing that this could also provide us valuable informal of the operation behaviour of our software and the best part: on live environment. And in fact it turns out that this is so common that we can find others pointing into this direction as well.
The picture below presents an overview of the application in question as well as the instrumentation points.

Application overview with instrumentation points

Application overview with instrumentation points

The instrumentation points gathered the following information:

  • The instrumentation point on the left of the OuterMDB collected the sum of the messages processed in the current and last hour as well as the messages per second.
  • The instrumentation point on depicted in the top of the OuterMDB collected the sum of the time spent in pre-processing as well as the number of times pre-processing was invoked.
  • The instrumentation point on top of the InnerMDB collected the sum of messages processed in the current and last hour as well as the messages per second.
  • And finally, the instrumentation point on the bottom of the InnerMDB collected the sum of time spent in the communication with the legacy system as well as the average of processing time per request in the current and last hour, the minimum and maximum times of processing for current and last hour and the amount of request processed as well as the timeouts.

The comparison between the number of messages processed in the InnerMDB and OuterMDB could provide us means of comparing how we should size the Thread pools for each of these components. This is such an information that would be harder to obtain by any other means. We also used those metrics for detecting misfunction on the pre-processing legacy software that was invoked by our PreProcessing component, this way we could switch off pre-processing and avoid a negative impact on overall system performance.
But this monitoring was key to the detection of a misbehavior of our JCA connector. A misimplementation of the equals/hashcode method pair for the ManagedConnection lead to a huge performance degradation after a few hours of software operation. By using our monitoring infrastructure we could isolate the problematic code area. Sure it did not point towards the equals/hashcode pair but it was clear that it was related to connection acquisition code.
Finally, the monitoring in our application provided us an effective way of monitoring the legacy application we were communicating with since it did not provide any native way of monitoring its operation. We were then able to instantly respond to outages on the legacy application through metrics collected on our software.

20
May
10

Designing for Extreme Transaction Processing – Memento Pattern

Applications with huge transaction processing requirements or tight response times always result in a careful architecture design. Special care has to be taken on how to partition data in order to be able to better parallelize load. This task can be even trickier if some of the data isn’t suitable for proper partitioning. Being ableto partition data is an essential requirement for some of the elastic frameworks around – some of them even demand that data is local to the node processing the request while others may still work but with a significant performance drop if it is not. This negative impact due to difficulties in the proper partitioning and grouping of data can be mitigated at the cost of increased memory usage as it is always possible to increase replication forcing data to be in multiple nodes to avoid serialization upon request as there isn’t the concept of gravitation on such tools as there was on previous distributed caches.
Billy Newport (the mind behind IBM eXtreme Scale) proposed a classification scheme for the different styles of Extreme Transaction Processing (XTP) systems he identified:

  • Type 1: Non partitionable data models – Applications in this category usually perform adhoc queries that can span an unpartitionable amount of data which leaves scaling up as the only scaling possibility.
  • Type 2a: Partitionable data models with limited needs for scaling out – Applications in this category already present means of partitioning data and thus load but still on a limited fashion. Hence those applications can still be built using regular application servers backed by Sharded Databases, elastic NoSQL databases or IMDGs but still won’t use a Map/Reduce pattern for processing requests.
  • Type 2b: Partitionable data models with huge needs for scaling out – Finally this category is composed of applications that presents means of partitioning data as on Type 2a but instead of being exposed to limited load, Type 2b are applications are pushed to the limit. Type 2b applications usually evolved from Type 2a and were faced with the scalability limits of traditional architectures moving from regular application servers to Map/Reduce frameworks. It is worth noting that it is possible to scale to similar load requirements with traditional architectures based on regular application servers but they’ll usually require more human resources for administration as well as more hardware infrastructure.

Among the list of common items on a classic Transaction Processing (TP) system that must be avoided on an XTP system are two phase commit resources. Note that it is not that you can’t have a two phase commit resource as part of an XTP but they must be carefully evaluated and excess will certainly compromise system performance.
Billy presented (at the eXtreme Scale meet the experts session@IBM Impact 2010) an excellent example scenario on where an excess of two phase commit resources could undermine the performance of an e-commerce solution. In his example, the checkout process of the referred e-commerce site would, as part of a single transaction, scan the whole shopping cart and for each product in the cart it would then perform an update on a fictional inventory database as well as updating a few other two phase commit databases from other departments. If any of the items were out of stock transaction would be rolled back and an error would be presented to the user. It is obvious that this hypothetical system wouldn’t be able to scale much since the cost related to the long time span of this transaction combined with the number of resources involved would be tremendous. Not to mention that there would be a huge load on the transaction manager.
Instead of using this rather obvious approach, Billy suggested that these updates could be chained and combined with the Memento design pattern – the updates would then be sequentially applied and if any of them failed the Memento pattern would then be used to revert the changes that have already been applied. Using this approach the contention on all the databases involved would be minimal and the application requirement would still be fulfilled.
This is one of the many examples we can point that need to be carefully observed when designing XTP systems.

19
May
10

distributed version control systems

About 2 years ago I first read something about distributed version control. It was a post in a friend’s blog (portuguese), I never used or tried any distributed version control alternative, but the name (and idea seems to give much power to developers and it) doesn´t sounds good for me.

More than a year latter I find a (excelent and funny) mercurial tutorial by Joel Spolsky. Since this day I can’t wait to get into a good project to begin using Mercurial in my company. It isn’t an easy task because only CVS (yes, some crazy people still use that) and SVN (recently updated to 1.6, only a few months ago our server version was still 1.4!!!) are currently (officialy) suported in my company servers.

If you have any experience with a migration from SVN or CVS to Mercurial (or any other dvcs), please send us your feedback.

I’ll report my experiences as soon as possible.




ClustrMaps

Blog Stats

  • 359,408 hits since aug'08

%d bloggers like this: