Tuesday, July 26, 2005

Case for a POJO MicroContainer

People who are familiar with J2EE realize that it is a complicated/bloated and cumbersome world. How easy it would be if we could deal with Plain Old Java Objects [POJOs]? Remember writing a "Hello World" program with EJB 2.1

Pundits will tell you that EJBs are not for Hello World kind of programs. I agree. It was just an example.

J2EE provides you a container and as a component running in the container, you get all the services the container is capable of - naming via JNDI, Security, Transactions (Yummy), EIS Integration via JCA (includes good old JDBC connections), caching, pooling etc etc.

Consider the case where I have a POJO. Lets call it the Employee POJO. Nothing fancy about it. Now as an Employee POJO, I want database access, transactions to update my salary (ha ha), security controls (so that only my Manager Pojo) updates my salary etc etc.

To get all this, I would go J2EE. I would write an EJB and cry a lot because to test my business logic, I would need a container. AND the container takes a hell lot of time to start (Paradigm changed by JBoss of course - fast startup).

Now since you have read this much on my blog, lets cut to the chase.

Since I mentioned I want to deal with POJOs and POJOs alone, lets do POJOs only. But what about the services I need from the container? Gawd, I will have to instrument my code to lookup the service, implement the EJB container callbacks etc.

Here is my code:


public class Employee
{
String name;
float salary;

public void updateSalary(float addAmount)
{salary += addAmount;}

}


Damn, simple POJO. Now I want to implement this as a stateless session bean and I want the container to provide the "REQUIRED" transactional isolation. Only the "Manager" roled user cannot invoke the updateSalary method. All this is possible by making the POJO implement javax.ejb.SessionBean interface and add dummy container callback methods. Go to the f***ing deployment descriptor, set the security and transactional semantics. Excellent work, Joe. I said I wanna deal with POJOs alone. Now you made me do SLSB. What if I want my POJO to be a servlet, a Web Service endpoint. Sweet Jesus, you are asking too much.

Don't despair! There is help on the way. With the introduction of JDK5 annotations, life will be simpler for developers. Plus less XML deployment descriptor hell. With J2EE5 and EJB3, annotations will do all the work AND THE CONTAINER WILL iNjEcT the services you need.

Lets look at the same POJO.


public class Employee
{
@Inject EntityManager manager;
String name;
float salary;

public void updateSalary(float addAmount)
{salary += addAmount;}

}


Don't go with the syntax. I am just trying to get the message across. Now the @Inject annotation will tell the container that I need this POJO to be persistent. Wow!! I got the entity bean capability for my POJO.

Now how about if my bean needs transactions. I will need the services of a transaction manager. Let the container inject it.


public class Employee
{
@Inject TransactionManager manager;
String name;
float salary;

@Transaction (type=required)
@Security (role=Manager)
public void updateSalary(float addAmount)
{salary += addAmount;}

}


Now I explicitly asked my method to have the REQUIRED semantics. If I do not specify, just because the container injected a TM, it can choose the default transaction semantics.

I am not done. Where are you going? Now I want to expose this bean as a web service. Thanks to JSR 181 annotations, all I need to do to the pojo is the @WebService annotation.


@WebService
public class Employee
{
String name;
float salary;

public void updateSalary(float addAmount)
{salary += addAmount;}
}


So having a POJO container, server or microcontainer or whatever you wanna call it, is going to be good. The container will be lightweight, can help in testing and will be mostly driven by annotations or some form of a xml dd. The idea is not the declarative descriptors in xml to drive the pojos.

The things you need to derive from this blog post are:
1) POJO based development is easier.
2) POJOs running in a container when annotated appropriately, can run an enterprise.
3) The POJO container can inject services into the POJO at runtime. As a POJO, you can specify which services you will need and the container will inject them. Instead of the gazillion default services that an EJB undergoes prior to J2EE5.
4) Take a POJO, add annotations and drop it in a container - it will become an EJB or a Servlet or a Web Service based on the services that are injected.

Now what if my team mate is a dumb ass and he does not know which annotations to use. Just specify the annotation and do not provide a type for the annotation. Let the container inject the default service [Eg: By default, the transaction type that is injected is "REQUIRED"]. Now if my dumbass team mate annotates @Transaction(type=never), the container will run the pojo method with no transaction.Now you know why he is a dumbass.

No comments: