17-Jul-04 (Created: 17-Jul-04) | More in 'OSCON-2004'

Tier-less computing pattern: Code Examples

Let us start with a need

Given a user name, userid and an email address create a user. We can call this "createUser" transaction with three parameters name, id, and email.

Let us see how a client can invoke this horizontally

Conceptual horizontal invocation using key value pairs


client -> calls -> execTransaction(requestName="createUser",name="", id="", email="")

For example this is how a web browser will invoke a transaction. The equivalnet programmatic invocation will be


SomeClass.createUser(name, id, email);

Let us see how we can provide an implementation using horizontal parts


request.createUser.classname=com.ai.db.DBRequestExecutor2
request.createUser.db=database-name
request.createUser.stmt=\
insert into user_table values({name.quote},{id.quote},{email.quote})

Purrists will quickly point out that CreateUser can be more complex. Well Horizontal parts can still solve the problem pretty decently a good number of times. Let us attempt it.


request.createUser.classname=com.ai.db.MultiExec
request.createUser.db=database-name
request.createUser.query_type=update

request.createUser.request.1=VerifyDuplicateId
request.createUser.request.2=AsyncSendVerificationEmail
request.createUser.request.3=InsertUser

request.InsertUser.classname=com.ai.db.DBRequestExecutor2
request.InsertUser.stmt=\
insert into user_table values({name.quote},{id.quote},{email.quote},'N')

So we used a transactional pipeline to do the job

Let use solve it using a vertical part

Unconvinced purists still nod their heads horizontally. So we now proceed to solve the problem using an unfettered java class


package com.mypkg;
public class CreateUser extends AbstractCreateUser
{
	void createUser(String name, String id, String email)
		throws RequestExecutionException
	{
		//write code to hearts content
	}
}

Now change the config file to


request.createUser.classname=com.mypkg.CreateUser

No addtional configuration entries are required

How can we run CreateUser on a remote computer?


request.application-factory.classname=com.pkg.DelegateEnabledFactory
request.application-factory.delegates=RemoteDelegate

request.RemoteDelegate.className=com.pkg.RemoteFactoryDelegate
request.RemoteDelegate.requestNames=CreateUser,AnotherRequest,etc
request.RemoteDeleget.remote-http-url=http://www.someothermachine.com/webapp

The magic of invoking the transaction is carried out by an implementation of IFactory. So the factory itself is bootstrapped using its own features allowing us to replace various implementations for it. We can go from a simple factory to filtered factory to IOCFactory to a DelegateEnabledFactory. Assuming we are using the last this is what it does. It checks to see if there are any delegates that can handle the "CreateUser", if there is it hands over the request to them. In this case there is a delegate called "RemoteDelegate" that is configured to handle "CreateUser". That is how "CreateUser" is transferred to a remote machine. If we don't want this, just delete the "createuser" from that delegate's list.

Why is this tier-less computing

Because by flipping a switch we are able to run CreateUser on a different box other than the local. Development can take place with this switch set to local and deployment can use static or dynamic strategies to deploy these components

References

1. General Introduction to other Server side Patterns in this series

2. OSCON 2004 Summary page for Server side patterns session