August 09, 2004EJB 3 callbacksWe are currently trying to figure out how callbacks should be implemented with EJB 3. So far, we have identified five different techniques and I'd like to get some feedback from readers about them. Here is a quick rundown, edited from messages sent by Marc Fleury and Craig Russell, along with their respective pros and cons:
Can you think of other options? Which one would you favor? Posted by cedric at August 9, 2004 10:19 AM Comments
Please go with 2 and 3, an interface and default implementation. Users can reuse the default implementation through inheritance or AOP introduction. The small benefits of the other options don't outweigh the familiarity and intuitiveness of the interface approach. However, the 2.x interfaces could use some serious restructuring to alleviate unnecessary methods, dual purposed or ambiguous methods, etc. Posted by: Bob Lee at August 9, 2004 11:21 AMIt seems to me that (3) is just as breakable as (1) is. If I misspell "ejbPassivate" I get no diagnostics, just a new method that will probably never be called. You didn't list a negative for Annotations (4). An obvious limitation is that EJB3 would require Java 1.5 or later. That's a big limitation for me, at least. Option (5) is ugly. Isn't EJB code already ugly enough? :-) I'm with Crazy Bob. Interfaces (2) are the way to go. But break them up, make them independent. Let each EJB explicitly implement the callback interface(s) that it needs and ignore the rest. The container certainly should be able to do an instanceOf to see if the bean code wants a callback. Posted by: Doug at August 9, 2004 01:04 PMHi, I would go with (2). Easier, simple, instanceof-able. Cheers, Thierry Posted by: Thierry at August 9, 2004 02:04 PMI go with option 2. Break the actual interface in many. Using well know names for methods is easy to maintain than looking for different tag names. Posted by: Hernan at August 9, 2004 03:14 PMAll of these suggestions seem to gel with rearchitecting the interfaces part of Ganesh Prasad
Option 2 (interfaces) seems to give the most flexability. If you go with option 2, then you can provide base classes (3) if people want to use them or you can pull it off with mix-ins. Posted by: Dan Countryman at August 9, 2004 04:13 PMIt seems that the responders above have a different idea of (2) than Cedric suggested. My reading of what Cedric suggested is that they be defined in the SessionBean interface, requiring all implementations to provide them whether they do anything or not. The other responders seem to be thinking of using interfaces in a different way; having a EjbPassivatible interface that defines ejbPassivate, so if you don't want to supply a passivate method, don't implement EjbPassivatable. This seems different from any of the five choice enumerated. Posted by: Brian Goetz at August 9, 2004 08:57 PMWhat about making the bean abstract AND using interface ? I thought of using Magic callbacks (1) with interfaces (2)...in modern IDEs, just write implements interface, choose methods to implement, then remove the interface from the implements list (if you still have some methods not implemented). This way you are sure not to mistype it. I think, it should be 2 and 4. Why not Why So, generally, for all EJB 3.0 techniques, I want have 2 + 4. Posted by: Dmitriy Kiriy at August 10, 2004 09:39 AMA couple of comments: - All the whining about having empty implementations of methods because there is only one interface (i.e. SessionBean), rather than an interface per method (i.e. ejbRemovable, ejbActivatable, ejbPassivatable, etc.) is a little bit ludicrous. The people that actually make use of most of the defined methods could just as easily argue that they shouldn't have to implement three interfaces, rather than just one. - Options 2 and 3 are more complementary than exclusive. It is very easy to provide an interface, as well as a default empty implementation for those who want it, a la MouseListener / MouseAdapter. - The serious contenders seem to me to be 1, (2 + 3) and 4. Magic callbacks are only a serious contender in my mind because that's what was in the draft spec. Otherwise, I don't know why you would pick it. Magic callbacks are something of a midpoint between interfaces / base classes and annotations. The draft spec says they want to move away from explicit dependencies on the container (interfaces / base classes) and torward POJOs with annotations that have meaning only within the context of the container. That being the direction, my money is on annotations. Posted by: Daniel Gredler at August 10, 2004 09:50 AMMy vote would be for annotations, they are not breakable and they allow you to specify only the callbacks you need without having to implement dummy methods, or get default implementations through inheritance (option 3), implement several interfaces or resort to AOP which is non-standard. Posted by: Aramis at August 10, 2004 09:52 AMI'd say interfaces, but differently from what you seem to mean, Cedric. In Xwork, we have many optional interfaces which an Action can implement. If it implements these interfaces, it gets those extra callbacks and extra services, if not that part is skipped. We also have a default implementation which implements most of the optional interfaces and has default behavior for them, which makes it easy for a user to just extend that class and get the default behavior for those interfaces. So, I guess I'd say have different interfaces for the different lifecycle scopes (i.e. not one per method, but one per lifecycle), and make them optional, with the container providing those callbacks for classes which implement them and just skipping those which don't. Posted by: Jason Carreira at August 10, 2004 10:53 AMTo me number 5 seems to be the best. It gives the flexibility to use another class to listen for events, but It allows a developer to say that the EJB itself is going to be the listener. So developers that like to address cross cutting concerns in a few utility classes can put their callback logic in the utility classes and register them as listeners. While developers that like to have their call back logic in their beans can make the beans listeners. The cool thing about this is that developers would be able to add listeners for only the callbacks they were interested in. This would mean that an inheritance structure of listener interfaces would need to be developed, that would contain different types of listeners, similar to the swing callback mechanism for events. We could have an interface for a certain callback that is implemented by an abstract adapter. Developers could either extend the adapter for that event interface (so they wouldn't have to implement all of the methods) or they could implement the interface(if they wanted to extend something else). We would be able to achieve all of the positive aspects of 2, 3, and 5. I agree with annotations, I think that after developers get their head wrapped around annotations, they will be everywhere. I think there should be support for them, but maybe only in the EJB, not in a pojo. I can’t think of a way to annotate a pojo and add it as a listener without violating type safety. So I would support annotations, but only in the EJB themselves. Then under the covers (not seen to the developers), when the annotation runs, we can automatically make the EJB a listener for whatever the annotation is and then using our derived callback in the interface, we can call the method that had the original annotation. With the annotations working, we could have 2-5 working excluding Magic Callbacks. I agree with the comments that developers will type the wrong magic callback and then spend hours wondering why their callback didn't work. That is the only one that I really disagreed with. Jay :) Posted by: Jay Howell at August 10, 2004 12:42 PMI vote for (2) where you may implement the interface, and only do if you want the notifications - exactly the same thing as with the EJB 2.x-interface SessionSychronization. Posted by: Rasmus Lund at August 10, 2004 03:46 PMIf you want to continue with the idea that this is persisting POJOs, the only option is 5. 1 is just braindead - you'll have no idea until runtime if it's even vaguely correct. 3 pushes into the object model in a very intrusive way. 4 is like 2, except it's using brand new technology for which there is no understanding of good practice and patterns in the Java community and further allows awful things like annotating the wrong or a misleading method, like indicating you want init() called on removal. 5, IMO, is the only one that's consistent with the idea that you are persisting PLAIN OLD Java objects, because you don't need to modify the POJO source to use or reuse in the persistence framework. Every other option is just a different way of creating a component, and not a POJO. I also think that the concern that "it's not OO" doesn't stand up, because you aren't violating the encapsulation of the object, and the notion of lifecycle is outside of the POJO (because it's a POJO!). My $0.02 -geir Posted by: Geir Magnusson Jr at August 11, 2004 02:49 AMClean, well separated interfaces, like Spring, XWork, new life for EJB, and many others have shown, is to me, the best solution. #1: is a flawed contract. would you trust in developers? I won't. In some hidden place of our pride, we are still humans. Fernando Posted by: Fernando Racca at August 11, 2004 11:21 AMI prefer 5 because its familiar and POJO-friendly. But as it stands now, the listener registers for all events on all entities of the specified class. So if an entity itself registered it would hear call-backs from all the other instances of the class! Secondly, EntityManager is currently an interface, so before registering you need to get an EntityManager instance. I dont like the sound of an entity bean having access to its em - far too self-referential (can it detach itself? remove itself?). I think this is similar to the problem for SessionBeans. I guess the issue is that callbacks to a bean instance have to be treated differently to callbacks to something else. One solution: have a LifeCycleListener interface as proposed, with a single method. If the bean implements the interface, all events on the instance are delivered through that method. It could be fairly trivial for the bean to filter out uninteresting events. This seems to be very flexible. For example the bean could delegate the event handling to a helper (or superclass) that then called the appropriate methods in the bean. And if you really want to, you can define these latter bean methods in an interface - or use the ejb2 interfaces. Nick Posted by: Nick at August 26, 2004 05:20 AMWhere can I find someone to email? Posted by: Jonathan at November 4, 2004 07:51 PMPost a comment
|