Extending EJBHome and ValueObjects

From the EJB 2.1 spec (final draft)

10.6.10 (from the spec)

--:: This clause allows inheritance for interfaces ::--

The remote home interface is allowed to have superinterfaces. Use of interface inheritance is subject to the RMI-IIOP rules for the definition of remote interfaces.

--:: And this practically takes it away ::--

The return type for a find<METHOD> method must be the entity bean's remote interface type (for a single-object finder), or a collection thereof (for a multi-object finder).

And here's an example demonstrating an extremely powerful extension to ValueObject pattern:

public interface MyLocalHome extends EJBLocalHome

{

public MyLocalObject create(ValueObject data) throws CreateException;

public MyLocalObject findByPrimaryKey(int pk) throws FinderException;

}

What is so powerful about this? For some applications it makes perfect sense for all EntityBeans to offer these four basic services: create, load, store and delete. Since all these EntityBeans use DAO's to do the actual database magic, they (the entity beans) are - in fact identical!

You need only to create a class which delegates the operations to DAO's and implements the EntityBean interface and then all your Bean implementations just extend this basic class. (We are not extending EJB from EJB, that would be against the spec.)

In order to fully benefit from this pattern, you need to extend the EJB(Local)Home and EJB(Local)Object to offer these methods and design your value objects so that they inherit from common base, maybe just as simple as getId() method and/or maybe some common serialnumber pattern functionality.

Now, whenever you need a new EJB, you just create empty implementation class, home and remote(local) interfaces extending those from the base classes. The only thing you need to actually write is the DAO for the new EJB (and of course the valueobject)

The big question: Is this against the current spec, and if it is, will this change in the future? Remember that we are not inheriting from the EJB's but from ordinary java classes and interfaces and I don't see that this kind of functionality would break anything?!

I've implemented this kind of a system using JBOSS (had to tweak the code a bit to make it work correctly with extended homeinterfaces) but after the "fix" it worked perfectly. Saves me about 300 lines of code/bean.

Please tell me what you think about this. I can post more sample code if this doesn't make any sense.

[2581 byte] By [javaguyaimfi] at [2007-9-27 16:54:15]
# 1
that is kind of nice, but you could probably have done the same before by using composition
kajaherink at 2007-7-6 1:11:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

Could you please be more elaborate? How can u achieve the same using composition? I'm all ears ;-)

And please - could somebody who knows more about the specification tell whether it's legal to extend your entity bean's local interface from another interface which is extended from EJBLocalObject.

javaguyaimfi at 2007-7-6 1:11:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

you are saying that you are saving about 300 lines of code per bean .. well inheritance is not the only way of cutting down on common code - you could have used composition/agregation to store the common code in an object that all the beans agregate and then just delegate the calls from the beans to that object .. it is not quite as sleek but does pretty much the same thing - something like inheritance emulation :).

kajaherink at 2007-7-6 1:11:50 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

I see your point. I've used that technique with my valueobjects to implement some interfaces by delegating calls to aggregate objects to do the actual processing.

Here's an example of the things you can accomplish if you use interface inheritance with your ejbs (warning: oversimplified example to keep it short)

List beanList = new ArrayList();

beanList.add("MyBean1");

beanList.add("MyBean2");

beanList.add("MyBean3");

for (Iterator itr = beanList.iterator(); itr.hasNext(); )

{

myBeanHome = (MyBeanHome)initCtx.lookup((String)itr.next());

myBeanHome.doSomeCommonOp();

}

Basically all my entitybeans have zero code in implementation (extended from common class) zero code in home interface (extended from common interface) and zero code in local interface (also extended) But not only that, my session beans are also more simple because the interface to all entity beans is the same.

And BTW: I found proof that this technique is possible JDJ article:

http://www.sys-con.com/java/articlea.cfm?id=1557

and picture:

http://www.sys-con.com/java/picture.cfm?pic=http://www.sys-con.com/java/archives3/0708/musser/fig4.jpg

I'm not a subscriber so I cannot access the article itself, but the picture is quite clear. Two beans one interface...

Hopefully some sun guy would comment about the specification!

javaguyaimfi at 2007-7-6 1:11:50 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

More confusion...

From the Developer's guide to Enterprise JavaBeans (Sun One document, version 7 beta)

Location: Using EntityBeans -> Developing Entity Beans -> Providing Interfaces:

-- snip --

The home interface defines the methods that enable a client accessing an

application to create and remove entity objects. A home interface always extends javax.ejb.EJBHome.

-

always extends EJBHome, but must it extend it directly or via some other interface extended from it? If it must extend it directly, could someone with enough knowledge explain why?

javaguyaimfi at 2007-7-6 1:11:50 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

first at all, to save lines & lines of code ... the inheritance is the best of solution. With delegation, you will have 2 instances in your JVM for just one reuse, btw a object that inherits (with all inherits relationships you want ...) will have just one instance.

Concerning EJB Home interface inheritance... it's just an interface ... and there is no problem for the interface and reusing. remember that the class that implements the Home interface (create(VO) findByPK()...)is the class who implements SessionBean or EntityBean interface...

read carefully the spec, when there is a call on the EJB Home, the EJB container uses a free instance of the EJB in a pool ( the EJB instance at this moment represents nothing) to invoke one of the Home method

So the inheritance could be use ... but just for reusing. the JNDI couldnt cast with polymorphism a "super" home factory into a "concrete" home factory ... you can just have the concrete ones

ValueObjects are just data structures (Serializable). you can make it extending. do not forget to distribute the bytecode of the value objects on client layer ...

please send me a email if you want the JDJ with the article...

gui at 2007-7-6 1:11:50 > top of Java-index,Other Topics,Patterns & OO Design...
# 7
JDJ is 6Mo sized
gui at 2007-7-6 1:11:50 > top of Java-index,Other Topics,Patterns & OO Design...