Home

News: Featured Article: A Critique of EJB 3

  1. Featured Article: A Critique of EJB 3 (67 messages)

    Hani Suleiman has written critique of the EJB 3 spec; he looks at the gaps and flaws in the draft as it stands currently and zooms in on three areas that he felt needed a lot more thought: Descriptors, the EntityManager, and 'magic' methods.

    Read A Critique of EJB 3

    Threaded Messages (67)

  2. I liked the unedited version better :)

    http://www.freeroller.net/page/fate/20040706#ejb3_what_childish_examples_don
  3. Better Version[ Go to top ]

    Ah yes, the polite, politically correct version for "the spastic TSS metoo opensores penis grabbing pondscum", and then what he REALLY thinks on the bileblog.
  4. Hani's AOP comment:

    "Oh and bad news for all of you who think that AOP will make your life easier. You still need to be a skilled and competent designer to nail down what aspects you need, how to write them, when to apply them, and when not to. Bummer!"

    Just replace "AOP" with "EJB"! Hani. I promise to get more involved with telling everybody how wonderful life is with J2EE...

    I really just don't understand Rod Johnson and Bruce Tate. What's with the "J2EE without EJB" and elephants? If you don't like or can't comprehend EJB technology that's fine with me. But, don't tell me what I'm capable of. EJB 2.0 technology provides an elegant foundation for our business objects. These business objects provide the base for our Web applications, Web Services, Messaging and CORBA all at the same time. And you what? All I did was to provide a competent object design to serve Use Cases. Then presto, EJB provided transaction, security, concurrency, persistence and deployment services from the get go!

    Look, guys, I don't go around telling people they better use EJB, thus why are we having people telling us not to use EJB.

    Business idea, open a Pizzeria with this logo: "Pizza without Cheese"

    Nothing personal folks, just an observation...
  5. ...I really just don't understand Rod Johnson and Bruce Tate. What's with the "J2EE without EJB" and elephants? If you don't like or can't comprehend EJB technology that's fine with me. But, don't tell me what I'm capable of. EJB 2.0 technology provides an elegant foundation for our business objects. These business objects provide the base for our Web applications, Web Services, Messaging and CORBA all at the same time. And you what? All I did was to provide a competent object design to serve Use Cases. Then presto, EJB provided transaction, security, concurrency, persistence and deployment services from the get go! Look, guys, I don't go around telling people they better use EJB, thus why are we having people telling us not to use EJB.Business idea, open a Pizzeria with this logo: "Pizza without Cheese"Nothing personal folks, just an observation...
    I agree that EJB solves problems that were previously unaddressed, as transaction management or access control. I think stateless SLSB, SFSB, and MDB in the 2.x fashion still have their use, but imho the biggest problem with EJB was Entity Beans. Remove entity beans and you'll end up with a cleaner, simpler and probably more efficient solution.

    Whether you like it or not, using EJB adds complexity and makes testing a pain (have you tried unit testing enterprise beans, it's not funny at all) ? I think that you should use EJB only if you have to, because they are light alternatives for tx management and security. The concurrency thing is only valid for SFSB, but I am not fan of a statefull architecture anyway. EJB still have a domain where their crown is not threatened (yet): distribution. For distributed transaction, distributed security or ws endpoint, I'd go for EJB unless I am forced not to, but for the rest, there are simpler (and IMHO more elegant) alternative.

    Don't want to sound too JBOSSy, but I agree with Marc Fleury when he says that middleware is about aspects. So why, instead of having the full power of aspect oriented programming using Spring (with baked solutions for most commons problems) ; should you restrict yourself to a limited set of aspect limited in functionnality ? (the security model in EJB is very limited and does not add real business value in complex cases)

    To conclude, the problem is not about whether using EJB or not, but about overrusing it and not indentifying cases where it adds real value.
  6. EJB isn't about AOP[ Go to top ]

    Hi,
    Event so, I'm a great AOP proponent I don't think that "pure" AOP will solve the problem EJB is trying to solve. AOP gives too much freedom for users and not everybody is able to handle it.
  7. EJB isn't about AOP[ Go to top ]

    Hi,Event so, I'm a great AOP proponent I don't think that "pure" AOP will solve the problem EJB is trying to solve. AOP gives too much freedom for users and not everybody is able to handle it.
    Yes "pure" AOP can not solve this problem, aspect implementation can (I have used both).
  8. I really just don't understand Rod Johnson and Bruce Tate. What's with the "J2EE without EJB" and elephants? If you don't like or can't comprehend EJB technology that's fine with me. But, don't tell me what I'm capable of. EJB 2.0 technology provides an elegant foundation for our business objects.
    Yes, I agree with you! We use EJB's (including entity) to develop large financial applications and we benefit from automatic transactions and persistence. I know that EJB's were misused very often, but it's not a technology problem.

    Lately a lot of folks have written articles with critique of everything. Instead of that they could do something useful, like writing some review of, let's say, Java Studio Creator.

    And that article about elephant... yes, it was funny, but I think it wasnt meant to take it seriously.

    best regards,
    Maris Orbidans
  9. Yes, I agree with you! We use EJB's (including entity) to develop large financial applications and we benefit from automatic transactions and persistence. I know that EJB's were misused very often, but it's not a technology problem.
    As I understand you are happy with EJB and you do not need EJB 3 too, do you ?
  10. Yes, I agree with you! We use EJB's (including entity) to develop large financial applications and we benefit from automatic transactions and persistence. I know that EJB's were misused very often, but it's not a technology problem.
    As I understand you are happy with EJB and you do not need EJB 3 too, do you ?
    No, I like EJB 3.0, but I don't predict that I will be able to use it as soon as it gets implemented. Customers are not very diligent to upgrade to latest EJB containers very often.

    Actually the article was good, too. Many good points and constructive suggestions. Not 'elephant' type story.
  11. Yes, I agree with you! We use EJB's (including entity) to develop large financial applications and we benefit from automatic transactions and persistence. I know that EJB's were misused very often, but it's not a technology problem.
    Yes, I agree with you! We use elephants for all our order fulfilment needs and we benefit from getting our products from A to B without hard manual labour. I know that elephants were misused very often, but it's not a technology problem.

    Hmmm... it'll work I guess, but I'd build my business around chickens^H^H^H^H^H^H^H^Htrucks for my order fulfilment.

    Of course this is a deliberate exaggeration. I don't think anyone is trying to argue that EJBs have been superseded in all domains (come to think of it, there are probably still places where elephants are a good form of transport if you look hard enough). The point is that for the majority of problems there are simply better solutions out there. Better as in simpler to write, easier to understand, straightforward to test, more flexible, higher performance.
  12. What's with the "J2EE without EJB" and elephants? If you don't like or can't comprehend EJB technology that's fine with me. But, don't tell me what I'm capable of. ... I don't go around telling people they better use EJB, thus why are we having people telling us not to use EJB...Nothing personal folks, just an observation...
     
    They're not telling you not to use EJB, they're telling you not to use EJB all the time. Specifically, they're telling you to use EJB only when it makes sense.

    They're not telling you 'what you're capable of', they're telling you to make a decision first as to whether EJB is an appropriate choice for a given application instead of using the technology as a Golden Hammer for every J2EE application.

    And accusing people that guard against the overuse of a given technology, of not being capable to 'comprehend' that same technology is a fallacious argument, argumentum ad hominem.

    Nothing personal here either, just an observation..
  13. I liked the unedited version better :)http://www.freeroller.net/page/fate/20040706#ejb3_what_childish_examples_don
  14. Sure is fun to watch Hani being polite...
  15. deployment descriptors[ Go to top ]

    On descriptors:

    XML deployment descriptors will be available for the new EJB3 model if you want to override existing annotations, or not use annotations at all. The expert group was just trying to nail down annotations and the new Entity model first.

    On EntityManager:
    A lot of the semantics you are worrying about are already solved/handled by similar implementations like Hibernate and Oracle's Toplink. Both Hibernate and Toplink are represented on the committee. It is just a matter of getting the language in the spec.

    On "Magic" values:
    The reason "magic" was added was to allow people to mix and match callbacks they were interested in. Maybe annotations would be a good replacement for this? Provides some type-saftey, yet allows you to mix-and-match what you're interested in. Stateful session bean has something around this already in the @Remove annotation.

    I also do not like any of the implicit code generation stuff(ie the business interface code generation). I don't have a problem with having Local be the default type for those beans who do not implement an interface explicitly tagged as @Remote or @Local.



    Bill

    P.S. I'm on expert group BTW.
  16. deployment descriptors[ Go to top ]

    On "Magic" values:
    <br/>
    The reason "magic" was added was to allow people to mix and match callbacks they were interested in. Maybe annotations would be a good replacement for this?
    Why not simpler things, like implementing an interface, like Removable for ejbRemove(), and similar methods?
  17. callback interfaces[ Go to top ]

    On "Magic" values:<br/>The reason "magic" was added was to allow people to mix and match callbacks they were interested in. Maybe annotations would be a good replacement for this?
    Why not simpler things, like implementing an interface, like Removable for ejbRemove(), and similar methods?
    Hmm, that's not an entirely bad idea. A similar thing was done with the SessionSynchronization interface. Care to get the ball rolling by posting interface definitions for all the callbacks? I and other spec members are lurking on the thread.
  18. callback interfaces[ Go to top ]

    Hmm, that's not an entirely bad idea. A similar thing was done with the SessionSynchronization interface. Care to get the ball rolling by posting interface definitions for all the callbacks?
    Sure, but mind the copyright :-)

    public interface EJBCreateHandler {
      void ejbCreate()
        throws EJBException, RemoteException;
    }

    public interface EJBPostCreateHandler {
      void ejbPostCreate()
        throws EJBException, RemoteException;
    }

    public interface EJBRemoveHandler {
      void ejbRemove()
        throws EJBException, RemoteException, RemoveException;
    }

    public interface EJBActivateHandler {
      void ejbActivate()
        throws EJBException, RemoteException;
    }

    public interface EJBPassivateHandler {
      void ejbPassivate()
        throws EJBException, RemoteException;
    }

    public interface EJBLoadHandler {
      void ejbLoad()
        throws EJBException, RemoteException;
    }

    public interface EJBStoreHandler {
      void ejbStore()
        throws EJBException, RemoteException;
    }

    public interface EJBMergeHandler {
      void ejbMerge()
        throws EJBException, RemoteException;
    }

    public interface EJBDetachHandler {
      void ejbDetach()
        throws EJBException, RemoteException;
    }

    Naming sound kinda clumsy, but is coherent at least. The other option was to have names like EJBDetachmentHandler, EJBActivationHandler and EJBLoadingHandler side by side.

    Cheers,
    Lars
  19. Callback interfaces[ Go to top ]

    Hmm, that's not an entirely bad idea. A similar thing was done with the SessionSynchronization interface. Care to get the ball rolling by posting interface definitions for all the callbacks?
    Sure, but mind the c
    Hmm, that's not an entirely bad idea. A similar thing was done with the SessionSynchronization interface. Care to get the ball rolling by posting interface definitions for all the callbacks?
    Sure, but mind the copyright :-)
    I am not sure we need to go to such a level of granularity. One method per interface? Yikes.

    Instead, we can probably split these callbacks in categories:

    Lifecycle: create, postCreate, remove, activate, passivate
    Persistence: load, store
    EntityManagement: merge, detach

    An example of naming:

    public interface PersistenceCallbacks {
      public void onLoad() throws EJBException, RemoteException;
      public void onStore() throws EJBException, RemoteException;
    }

    Or maybe wrapping callbacks would be preferable?

    public interface PersistenceCallbacks {
      public void beforeLoad() throws EJBException, RemoteException;
      public void afterLoad() throws EJBException, RemoteException;
      public void beforeStore() throws EJBException, RemoteException;
      public void afterStore() throws EJBException, RemoteException;
    }

    --
    Cedric
    http://beust.com/weblog

    opyright :-)
    I am not sure we need to go to such a level of granularity. One method per interface? Yikes.

    Instead, we can probably split these callbacks in categories:

    - Lifec


    public interface EJBCreateHandler { void ejbCreate() throws EJBException, RemoteException;}public interface EJBPostCreateHandler { void ejbPostCreate() throws EJBException, RemoteException;}public interface EJBRemoveHandler { void ejbRemove() throws EJBException, RemoteException, RemoveException;}public interface EJBActivateHandler { void ejbActivate() throws EJBException, RemoteException;}public interface EJBPassivateHandler { void ejbPassivate() throws EJBException, RemoteException;}public interface EJBLoadHandler { void ejbLoad() throws EJBException, RemoteException;}public interface EJBStoreHandler { void ejbStore() throws EJBException, RemoteException;}public interface EJBMergeHandler { void ejbMerge() throws EJBException, RemoteException;}public interface EJBDetachHandler { void ejbDetach() throws EJBException, RemoteException;}Naming sound kinda clumsy, but is coherent at least. The other option was to have names like EJBDetachmentHandler, EJBActivationHandler and EJBLoadingHandler side by side. Cheers,Lars
  20. Callback interfaces[ Go to top ]

    Ouch, bad formatting. Reposting
    Sure, but mind the copyright :-)
    I am not sure we need to go to such a level of granularity. One method per interface? Yikes.

    Instead, we can probably split these callbacks in categories:

    Lifecycle: create, postCreate, remove, activate, passivate
    Persistence: load, store
    EntityManagement: merge, detach

    An example of naming:

    public interface PersistenceCallbacks {
      public void onLoad() throws EJBException, RemoteException;
      public void onStore() throws EJBException, RemoteException;
    }

    Or maybe wrapping callbacks would be preferable?

    public interface PersistenceCallbacks {
      public void beforeLoad() throws EJBException, RemoteException;
      public void afterLoad() throws EJBException, RemoteException;
      public void beforeStore() throws EJBException, RemoteException;
      public void afterStore() throws EJBException, RemoteException;
    }

    --
    Cedric
    http://beust.com/weblog
  21. Callback interfaces[ Go to top ]

    I am not sure we need to go to such a level of granularity. One method per interface? Yikes.
    I often find that the good thing about interfaces is that you can have lots :)

    Your PersistenceCallbacks interface would force me to implement a method I do not need. That's bad and violates SOLID principles.

    On the other hand, I have no problem with grouping my fine-grained interfaces for convenience:
    public interface LifeCycleHandler
      extends EJBCreateHandler,
        EJBPostCreateHandler,
        EJBRemoveHandler,
        EJBActivateHandler,
        EJBPassivateHandler {
    }

    public interface PersistenceHandler
      extends EJBLoadHandler,
        EJBStoreHandler {
    }

    public interface EntityManagementHandler
      extends EJBMergeHandler,
        EJBDetachHandler {
    }

    Just my 2 cents,
    Lars
  22. Callback interfaces[ Go to top ]

    I think it is necessary to have pre/post hooks for ejbXXX operations. Also probably makes sense to throw some type of VetoException if we explicitly don't want to proceed with operation?

    so generic sequence will be

    preAction --> action --> postAction

    Also maybe registering event listeners won't be bad idea , it can be expressed in descriptor or metadata , gives you ability to chain listeners , dynamic register/de register (I kinda like it very much) and also can make latte in spare time :) (I got carried away, you can skip latte)

    if you use aspects than this is no brainer to implement, not that is harder without aspects. In fact we are using something like this in our EJB/SOA framework and it works well for us. YMMV ;D
  23. Callback interfaces[ Go to top ]

    Instead, we can probably split these callbacks in categories:
    Lifecycle: create, postCreate, remove, activate, passivate
    This makes perfect sense to group callback methods. But is there a need for postCreate ? Also activate/passivate probably will be useless for stateless beans.
    Persistence: load, store
    EntityManagement: merge, detach
    public interface PersistenceCallbacks {
      public void beforeLoad() throws EJBException, RemoteException;
      public void afterLoad() throws EJBException, RemoteException;
      public void beforeStore() throws EJBException, RemoteException;
      public void afterStore() throws EJBException, RemoteException;
    }
    I like the before/after scheme. I guess we can drop RemoteException from the signature. However, for entity beans I would prefer one interface for all callbacks, something like:
    public interface EntityLifecycle{
      public void beforeCreate() throws EJBException;
      public void afterCreate() throws EJBException;
      public void beforeLoad() throws EJBException;
      public void afterLoad() throws EJBException;
      public void beforeStore() throws EJBException;
      public void afterStore() throws EJBException;
      public void beforeRemove() throws EJBException;
      public void afterRemove() throws EJBException;
      public void onMerge() throws EJBException;
      public void onDetach() throws EJBException;
    }

    Then I am thinking what would be typical use of these callbacks ?
  24. callback interfaces[ Go to top ]

    EJBCreateHandler,EJBPostCreateHandler,EJBActivateHandler ...

    Spontaneous explosion of ejb api :))
  25. callback interfaces[ Go to top ]

    EJBCreateHandler,EJBPostCreateHandler,EJBActivateHandler ...Spontaneous explosion of ejb api :))
    Actually, the API will be as big as before, but the implementing classes have the chance to be smaller, as they are less cluttered by empty implementations such as

    public void ejbPassivate() throws EJBException, RemoteException {
      // do nothing
    }

    At least that is how I perceive it. :)
  26. callback interfaces[ Go to top ]

    Actually, the API will be as big as before, but the implementing classes have the chance to be smaller, as they are less cluttered by empty implementations such aspublic void ejbPassivate() throws EJBException, RemoteException {  // do nothing}At least that is how I perceive it. :)
    What about making beans become abstract (like EJB2.0 entities are) ? No need to override the methods you get from the interfaces you implement if you don't feel like, and the container should provide a default implementation for those methods you did not feel like implementing...

    Some of you are shocked by the "intrusivity" of implementing interfaces. Are you also shocked when you make a class Serializable (providing the readObject and the writeObject methods only if you feel like) ?
  27. callback interfaces[ Go to top ]

    What about making beans become abstract (like EJB2.0 entities are) ? No need to override the methods you get from the interfaces you implement if you don't feel like, and the container should provide a default implementation for those methods you did not feel like implementing...Some of you are shocked by the "intrusivity" of implementing interfaces. Are you also shocked when you make a class Serializable (providing the readObject and the writeObject methods only if you feel like) ?
    Abstract classes is not a good idea.

    abstract class Calculator extends AbstractBean{

    int calcutate()throws RemoteExeption,EJBException{
      return 2*2;
    }

    }

    You will need complex container or some evil code generation library to test this trivial method.
  28. callback interfaces[ Go to top ]

    What about making beans become abstract (like EJB2.0 entities are)? No need to override the methods you get from the interfaces you implement if you don't feel like, and the container should provide a default implementation for those methods you did not feel like implementing...
    Actually, I think this is a good idea and a great alternative. This way, being forced to implement a coarse-grained interface would be made convenient enough and it would be clear that components are not supposed to function stand-alone.
    Some of you are shocked by the "intrusivity" of implementing interfaces. Are you also shocked when you make a class Serializable (providing the readObject and the writeObject methods only if you feel like)?
    Serializable is a bad example because it does not force you to implement any methods you do not need. But take java.awt.event.MouseListener for instance and supposed you just want to react on a simple mouse-click: You have to implement four methods that are not needed at all!

    Of course, that's the only reason why java.awt.event.MouseAdapter was introduced -- an abstract class that inherits an empty implementation of all five methods to its descendant. Now, its only too bad that Java does not support multiple inheritance, since you only can inherit either MouseAdapter or a class actually providing functionality... (But this is actually not so bad since we always have been told to favor composition over inheritance ;-)

    What I'm getting at, in a lot of words, is that implementing an interface is actually a good idea, but not if it forces you to implement unneccessary methods. Google for Interface Segregation Principle for more info on this topic.

    Now, back to the magic methods of Serializable: I personally think they are an ugly hack and tend to avoid them. If I want to customize the way Serialization is done, I override Externalizable where possible. Depending on methods that may or may not be contained in a class is evil (in my book), as it introduces hidden dependencies that you may be aware of, but your co-worker maintaining the code is not.

    As always, just my 2 cents,
    Lars
  29. callback interfaces[ Go to top ]

    What about making beans become abstract (like EJB2.0 entities are) ? No need to override the methods you get from the interfaces you implement if you don't feel like, and the container should provide a default implementation for those methods you did not feel like implementing
    I too like this idea. Having an abstract base class, like AbstractSessionBean or AbstractEntityBean, will satisfy both sides :)
    All the callback methods can be in base class, so no need for many interfaces and my class can remain clean without empty methods if I don't need those.
     
    Serializable interface .. a classic example of "magic" methods.
  30. Magic methods[ Go to top ]

    On "Magic" values:The reason "magic" was added was to allow people to mix and match callbacks they were interested in. Maybe annotations would be a good replacement for this? Provides some type-saftey, yet allows you to mix-and-match what you're interested in. Stateful session bean has something around this already in the @Remove annotation.
    From 3.1.3 or 4.1.3 what I understood, there will be three choices for callback methods:
    1. Implement SessionBean interface, and business as usual for callback.
    ( but you still need to annotate with @Stateless or @Stateful to distinguish between two types of session beans, no? )
    2. Annotate with @Stateless or @Stateful. No SessionBean interface and no "magic" methods, hence no callback for those.
    3. Annotate with @Stateless or @Stateful, and "may optionally implement the setSessionContext, ejbCreate and/or ejbRemove method" for Stateless or "selectively implement methods of the SessionBean interface" for Stateful.

    Why can't we live with just choice #1 and #2 ? I can always selectively implement a few methods of SessionBean interface and leave out the rest as empty methods. Why that is a problem ?

    Ohh .. SessionBean interface does not have ejbCreate(), so at least magic for ejbCreate() is justified ;) ..nahh.. add that to SessionBean interface.
  31. deployment descriptors[ Go to top ]

    On "Magic" values:The reason "magic" was added was to allow people to mix and match callbacks they were interested in. Maybe annotations would be a good replacement for this? Provides some type-saftey, yet allows you to mix-and-match what you're interested in. Stateful session bean has something around this already in the @Remove annotation.
    I second the motion to use nothing but simple, fine-grained interfaces for implementing callbacks. Why make things more complicated than they need to be by adding yet another vector of information? Interfaces are the way of mix-and-match Java programmers are already accustomed to, and they can be inherited, plus providing all other features of annotations already (that is, pre-Java 5.0). And EJB 3 would not rely on a technology that is -- at most -- half-baked at its current state, and (keeping the JCP's track record in mind) might have some certain flaws in its initial revision.

    That said, let me emphasize again that I am not opposed to annotations per se, and think they will be a good way of getting rid of some of those pesky deployment descriptors in EJB 3 (hopefully, the ejb-jar.xml completely). But when it comes to declaring the functionality a given class implements, in my opinion interfaces are the better way.

    Just my two cents,
    Lars
  32. Great Article[ Go to top ]

    Great article, thanks for posting it.

    I'm not a huge fan of specifiying too much with attributes inside more source. If for example I wanted to add support for another app server, I'd rather not be forced to go back and annotate my code further and rerun the compiler or xdoclet or whaterver to produce descriptors just to support a new app server. Afrer all, nothing funtional changed in the source!
  33. EJB3 prototype[ Go to top ]

    JBoss has implemented an EJB3.0 prototype that we demoed at JavaOne.

    I blog about it here:

    http://jboss.org/jbossBlog/blog/bburke/?permalink=EJB3%2C+Petstore%2C+and+JavaOne.html

    We'll have a distribution ready when JBoss 4.0 beta goes out next week. We hope to have a solid implementation of whatever is in the EJB3.0 spec sometime in September.

    Bill

    --
    Chief Architect
    JBoss Inc.
  34. EJB3 prototype[ Go to top ]

    After all the unflattering things Hani has to say about JBoss, you post that!

    Now thats just looking for trouble.
  35. I'm sorry, Bill, but without intending the smallest disrespect, the juxtaposition in your post of the words "whatever" and "September" is just completely daft.

    I mean, what with today being July, and all.

    Just saying.

    FW
    .
  36. too many things in one spec[ Go to top ]

    I think that ejb3 does not address the "too many things in one spec" fault of the previous specs. Persistence should be delegated to jdo, which is specialized to it. IoC and AOP should be delegated to a separate spec which should target all java platforms from j2me to j2ee.

    Carlo.
  37. I also stumbled on this feature in the EJB 3.0 spec and had the same feeling of too much magic here. In fact I don't see a good reason for that: in all EJB projects I was involved in the past, we derived our implementation classes from an abstract base class, providing empty implementations of all callback methods. Derived EJBs could then simply override only those callback methods they were interested in. This approach is simple, robust and very easy to understand and much closer to what people are used to (e.g. from Swing and other J2SE APIs). And it is usually required anyway, when you build up you own project-specific or company-specific application framework on top of EJB. Or is anybody here really doing 'naked' EJB programming? ;-)
  38. I think that implicit code generation for session beans is usefull only for vendors who need to sell development environment that automatically generate that code. It should be much better if session beans are not required to implement any interface at all.
  39. the Manchurian coder[ Go to top ]

    Several messages in this thread are along the line of "EJB is fine and dandy when used appropriately."

    I think this is fundamentally wrong. Before using EJB, I've rolled my own transactions and security and written custom code to handle concurrency. It seems to me that even for its intended use, EJB 2.0 is a clumsy, intrusive package that makes things harder than they need to be.

    I think that many EJB developers succumb to the Stockholm syndrome: after being held hostage and abused for a long time, they begin to identify with the abuser.

    Certainly hard working, clever programmers can write effective applications using EJB. What is doubtful is that apps are delivered quicker and are more robust than if an alternative to EJB had been used.
  40. the Manchurian coder[ Go to top ]

    Coming from a CORBA world, I found EJBs easy to work with, performant, and easy to maintain. I think it is fundamentally wrong to assume that people use EJBs because they were "held hostage".

    Cheers
    Ray
  41. EJB3[ Go to top ]

    Thanks, Hani, for the consutructive criticism.

    A number of points:

    (1) Everyone agrees that there will be support for XML descriptors, and, even better, maybe support for "annotation overriding". Its not in the draft spec because we are waiting for a unified strategy for all of J2EE platform. The JSR-220 group is not supposed to solve all problems by itself ;-)

    (2) I'm not at all convinced that (for example) column names typically change at deployment time. I think that is the *uncommon case*, and that we should solve the common case -first-, then ask about the uncommon cases. In most environments database schemas change MUCH less frequently than Java source code, so I'm not at all uncomfortable with embedding ORM metadata in the Java code. Indeed, many Hibernate users are doing this today using XDoclet, with great success. We *do* need code folding support in the IDEs, however.

    (3) One of the fantastic things about having "stuff" in annotations is that your code has access to a really natural metamodel at runtime: you can get all your mapping information via the reflection API. This is *very* useful.

    (4) Hani makes two criticisms of EntityManager. One is that create() doesn't throw an exception if a row with the persistent identity already exists. Well, that's because most ORM solutions implement transactional write behind, so you get the exception at flush time. The other is that merge() works by value. (He says create(), but I'm quite sure he means merge(), create() works by reference!) Well, this was done after a *lot* of consideration (some people even wanted even create() to work by value) and there is a Good Reason for it. Merge by reference (as in Hibernate saveOrUpdate()) can fail at runtime due to an object with the same persistent identity already existing in the persistence context. Since EJB defines transparent persistence context propagation, this is a really fragile behavior: it could show up when two different components are "assembled". Well, we put a LOT of thought into the semantics of these operations, and I am happy that they are very correct. I'll try to write up an article explaining in further detail at some stage.

    (5) You *can* tell if an entity is managed, by calling EntityManager.contains()

    (6) Guys, an interface with *one* operation?? What the hell does that buy you? Well, I suppose it stops you from misspelling the method name, but I really don't see misspelled method names as a major source of problems in Java development. C'mon, interfaces are really supposed to define a "role" in which a class can appear, what role is defined by EJBRemoveable? This is an interface with incredibly weak semantics.

    But anyway, very useful discussion, thanks everyone.

    Cheers!
  42. EJB3[ Go to top ]

    (6) Guys, an interface with *one* operation?? What the hell does that buy you? Well, I suppose it stops you from misspelling the method name, but I really don't see misspelled method names as a major source of problems in Java development. C'mon, interfaces are really supposed to define a "role" in which a class can appear, what role is defined by EJBRemoveable? This is an interface with incredibly weak semantics.
    I can't say I disagree with you there. But we are talking about interfaces that define callback methods, which have no real semantic at all. This fact does not change if you group many of those callback methods into one interface (as done in javax.ejb.SessionBean) -- the only effect is that the interface becomes more unwieldy when being implemented.

    An EJBRemoveable interface would act as the interface of an event handler that is being notified upon the event of the removal of an EJB. The role of the event handler is, specifically, to handle the event -- no more, no less. The same thing is up with java.awt.event.ActionListener. (I never thought I would reference the AWT library as an example while discussing a design question.) Now I most of the time want to handle a specific event, so I should be able to select. Doing this via implementing an interface is compile-time safe.

    As for the misspellings: The last time I checked, my IDE was not able to read my thoughts and write ejbPassivate instead of ejbPasivate for me. Perhaps it's time to integrate that spellchecker into Eclipse now... :)

    Cheers,
    Lars
  43. Configuration via annotations[ Go to top ]

    (2) I'm not at all convinced that (for example) column names typically change at deployment time. I think that is the *uncommon case*, and that we should solve the common case -first-, then ask about the uncommon cases. In most environments database schemas change MUCH less frequently than Java source code, so I'm not at all uncomfortable with embedding ORM metadata in the Java code. Indeed, many Hibernate users are doing this today using XDoclet, with great success. We *do* need code folding support in the IDEs, however.
    Let's take the example in 10.1.1
    @Entity
    @Table(name="CUST", schema="RECORDS")
    public class Customer { ... }

    So my Customer class became tied to CUST table for it's entire life. If I want to use the same class in another place where the table is "my_loyal_customer", I have no choice but make another version of the Customer class.
    maybe support for "annotation overriding"
    I think this is a must. But it can be something better than clumsy XML descriptors, a simple properties file may serve the purpose very well.
  44. The Common Case[ Go to top ]

    (2) I'm not at all convinced that (for example) column names typically change at deployment time. I think that is the *uncommon case*, and that we should solve the common case -first-, then ask about the uncommon cases. In most environments database schemas change MUCH less frequently than Java source code, so I'm not at all uncomfortable with embedding ORM metadata in the Java code. Indeed, many Hibernate users are doing this today using XDoclet, with great success. We *do* need code folding support in the IDEs, however.
    Let's take the example in 10.1.1@Entity@Table(name="CUST", schema="RECORDS")public class Customer { ... }So my Customer class became tied to CUST table for it's entire life. If I want to use the same class in another place where the table is "my_loyal_customer", I have no choice but make another version of the Customer class.
    A class that is mapped to multiple tables is also clearly the uncommon case. Good API design revolves around considering the 80% usecases *first*, optimizing for them, and after that, thinking about the more exotic cases.

    In fact, one of the major causes of "J2EE complexity" is standards that solve difficult, uncommon cases, without considering the importance of the common case.
  45. The Common Case[ Go to top ]

    A class that is mapped to multiple tables is also clearly the uncommon case. Good API design revolves around considering the 80% usecases *first*, optimizing for them, and after that, thinking about the more exotic cases.In fact, one of the major causes of "J2EE complexity" is standards that solve difficult, uncommon cases, without considering the importance of the common case.
    I agree that we should focus on solving 80% usecases *first*, but if you don't have a solution for rest 20% usecases (at least for most of them) this might come back and haunt us in future when people would actually start using it.
    In fact, it is not that simple a problem as you might think. For example, the table may not change, but the schema might be different in multiple deployment environments. Same applies to security annotations.

    In short, hard coding any configuration value in source may be good for some things, e.g. transaction declaration, but may be a problem for other things. Hence, I am stressing on the need for a standard mechanism of overriding annotation values.
  46. The Common Case[ Go to top ]

    I think it is not a good idea do have schema name in meta data, but there is no problems with "table". As I understand you are talking about views, "projection" must solve this problem (my favorite feature).
  47. annotations[ Go to top ]

    Hence, I am stressing on the need for a standard mechanism of overriding annotation values.
    Which is exactly why this needs to be solved at the J2EE platform level. The J2EE 1.5 spec group is looking at this. Seriously, I'm getting bit bored of this topic. *No-one* is arguing that we don't need to be able to override annotations some of the time. Indeed, no-one ever has. You are arguing with a great big straw man.

    Can we please discuss some other parts of the spec, which have =not= been done to death?
  48. annotations[ Go to top ]

    Can we please discuss some other parts of the spec, which have =not= been done to death?
    Now about those interfaces for callbacks ... ;-)

    SCNR,
    Lars
  49. The Common Case[ Go to top ]

    (2) I'm not at all convinced that (for example) column names typically change at deployment time. I think that is the *uncommon case*, and that we should solve the common case -first-, then ask about the uncommon cases. In most environments database schemas change MUCH less frequently than Java source code, so I'm not at all uncomfortable with embedding ORM metadata in the Java code. Indeed, many Hibernate users are doing this today using XDoclet, with great success. We *do* need code folding support in the IDEs, however.
    Let's take the example in 10.1.1@Entity@Table(name="CUST", schema="RECORDS")public class Customer { ... }So my Customer class became tied to CUST table for it's entire life. If I want to use the same class in another place where the table is "my_loyal_customer", I have no choice but make another version of the Customer class.
    A class that is mapped to multiple tables is also clearly the uncommon case. Good API design revolves around considering the 80% usecases *first*, optimizing for them, and after that, thinking about the more exotic cases.In fact, one of the major causes of "J2EE complexity" is standards that solve difficult, uncommon cases, without considering the importance of the common case.
    it is common to have multiple schemas for same tables for different stages of development process (production,test,stage....) some of them running on same DB instance

    as it is now you have choice of moving all schemas to one (kinda hard to do) , or recompile for each environment after you readjust ALL metadata to fit your current schema (not something I'd like to do ever)

    IMHO in general you shouldn't care (or try to care less) where data goes (schema,table,RDBMS,ODBMS,filesystem etc..) but just what's gonna be persisted (fields/properties,relationships...) that leaves space for persistence domain expert to optimize actual persistence better than average java developer can do.

    My 0.2 c
  50. The Common Case[ Go to top ]

    I totally agree with many posts in this thread. In a world where we are moving towards loosely coupled systems, adding tight coupling through code annotations seems like a step back.

    There are a number of common patterns that do not seem to be solved with many persistence layers out there, and I can't see how EJB 3.0 can help either:

    1) Read from DS1 write to DS2 (for data migration, etc)
    2) Read from a view, write to multiple tables
    3) Read from a table, write through stored procedures

    Any ideas how these things can be addressed.
  51. coupling[ Go to top ]

    I totally agree with many posts in this thread. In a world where we are moving towards loosely coupled systems, adding tight coupling through code annotations seems like a step back.
    You are confusing loose coupling *between different* systems, with coupling *within* a system.

    The Java domain model, and the relational schema are by nature tightly coupled. And there is Nothing Wrong With That.
    There are a number of common patterns that do not seem to be solved with many persistence layers out there, and I can't see how EJB 3.0 can help either:1) Read from DS1 write to DS2 (for data migration, etc)2) Read from a view, write to multiple tables3) Read from a table, write through stored proceduresAny ideas how these things can be addressed.
    JDBC, or stored procedures, or RDBMS toolset are really excellent solutions to these problems. There is nothing object-oriented about these problems, so object-oriented persistence solutions don't really need to address them. In some cases, Java is simply inappropriate.

    Square pegs/round holes.
  52. coupling[ Go to top ]

    There is nothing object-oriented about these problems, so object-oriented persistence solutions don't really need to address them. In some cases, Java is simply inappropriate.Square pegs/round holes.
    I'm not sure I 100% agree with this statement. In my application I simply want to work with JavaBeans (OK, POJOs). Move them from the web tier to the back end, use them in the business tier, send them through JMS / web services etc. What I shouldn't have to care about is how they are persisted. This is the goal of transparent persistence.

    If my DBA has mandated stored procedures for database writes, or if I'm writing a new frontend to a legacy database that shouldn't be a problem. I should't have to resort to writing JDBC code directly, my persistence layer should handle that. In the end I will have to create my own framework to deal with such issues that eventually becomes open sourced as yet another persistence mechanism. Round holes still need filling and I don't want to have to carve the peg by hand every time.
  53. coupling[ Go to top ]

    If my DBA has mandated stored procedures for database writes, or if I'm writing a new frontend to a legacy database that shouldn't be a problem. I should't have to resort to writing JDBC code directly, my persistence layer should handle that. In the end I will have to create my own framework to deal with such issues that eventually becomes open sourced as yet another persistence mechanism. Round holes still need filling and I don't want to have to carve the peg by hand every time.
    I found object persistence and data access are two very different things and probably it is better to have two ways than everything in the same framework and with compromises, I know how JDBC ir error prone and I think there is nothing bad to maintain some trivial home made library to solve domain specific problems, it is better than to maintain JDBC code. If you will make it public then probably it will increase quality, so it must be nothing wrong to have "yet another persistence mechanism" too.
  54. Stored Procedures?[ Go to top ]

    If my DBA has mandated stored procedures for database writes, or if I'm writing a new frontend to a legacy database that shouldn't be a problem. I should't have to resort to writing JDBC code directly, my persistence layer should handle that. In the end I will have to create my own framework to deal with such issues that eventually becomes open sourced as yet another persistence mechanism. Round holes still need filling and I don't want to have to carve the peg by hand every time.
    Check out the PriDE ORM toolkit if you need some kind of support for stored procedures in your persistence managed :-)
    But away from that, it's a bit symptomatic for the discussion around EJB 3.0, I think. The spec contains a lot of ideas to simplify component development as far as possible. In the most extreme case you can now just provide a single implementation class rather than multiple interfaces, implementation, and descriptor. I think that's just fine for beginners as long as we don't loose approved features of EJB 2.1 like e.g. separation of code and configuration. If both mechanisms co-exist, they are worth to be compared *in practice*.
  55. I just posted a few thoughts on this problem on my weblog. In a nutshell, interfaces should be replaced with annotations to flag whether a method is a no-op or not. Much cleaner this way : this kind of concern should *not* leak into your object domain and much less modify the types of your objects.

    --
    Cedric
    http://beust.com/weblog
  56. I just posted a few thoughts on this problem on my weblog. In a nutshell, interfaces should be replaced with annotations to flag whether a method is a no-op or not. Much cleaner this way : this kind of concern should *not* leak into your object domain and much less modify the types of your objects.-- Cedrichttp://beust.com/weblog
    Putting a "no-op" annotation looks like a leak into your object domain too... Besides, it allows incoherence (and what are you going to do if you find a "no-op" tagged method which is actually not a no-op ?).
    IMO, if the no-op feature had to be supported by something, it should be by the Java API directly (what about adding a "boolean isNoOp()" into the java.lang.reflect.Method class ?)
  57. Putting a "no-op" annotation looks like a leak into your object domain too...
    No, since it is defined in the adapter that your appserver vendor will provide for you. As a user, you know nothing about it.
    Besides, it allows incoherence (and what are you going to do if you find a "no-op" tagged method which is actually not a no-op ?)
    Not invoke it, but this is a user error, there's not much else we can do about that.

    And the user could do that same error with the interface approach (implement the interface with an empty method).
    if the no-op feature had to be supported by something, it should be by the Java API directly (what about adding a "boolean isNoOp()" into the java.lang.reflect.Method class ?)
    Mmmh... interesting. I have the feeling Sun would be very hostile to this idea, though (and I'm not quite sure what to think of it either).

    --
    Cedric
  58. Putting a "no-op" annotation looks like a leak into your object domain too...
    No, since it is defined in the adapter that your appserver vendor will provide for you. As a user, you know nothing about it.-- Cedric
    And my bean should extend that adapter, shouldn't it?
    If so, well, first, it would "waste" its only inheritance, and that would look like a leak into my object domain too.
  59. I think callback method per interface is a good idea, but if we are talking about components then old component programming style is more usefull for component:

    component.onRemove().add( new MyCallback() );

    or component.onRemove( new MyCallback() );

    It is usefull for component user. It component wants to know about container events, then it regesters event handler for container:

    container.onRemoveComponent().add(this);

    But component oriented programming is useless for data access code any way. It is usefull for objects with long life cycle only, data loaded from database is not this kind of object.
  60. I don't really see the benefits of this approach. You replace an interface by a concrete base class which reduces flexibility a lot because MyClass cannot handle other things anymore e.g. StoreCallbackAdapter. This essentially means that you go from "MyClass is-a ILoadCallback" to "MyClass is-a LoadCallbackAdapter", both stating clearly that the object is an object that is interested in load events.
    And a much cleaner way to avoid calling no-ops is what Benjamin suggested: having a function Method#isEmpty() or something similar.

    As a side note, I think this road will lead to annotation hell in which all kinds of things require annotations. This IMO is even worse (less readable and maintable) than javadoc/xdoclet tags.
  61. I don't really see the benefits of this approach. You replace an interface by a concrete base class which reduces flexibility a lot because MyClass cannot handle other things anymore e.g. StoreCallbackAdapter.
    The whole point is to avoid interface explosion. In this case, we would use the callbak interfaces I defined above and which contain several methods (or even, all of them):

    public class CallbackAdapter {
      @NoOp
      public void onLoad() {}

      @NoOp
      public void onStore() {}

      ...
    }

    --
    Cedric
  62. Surely a personal preference, but I'd rather have multiple fine-grained interfaces (e.g. like the listeners in AWT) than this annotation style. This way I can use glue code (i.e. anonymous classes) or aspects or whatnot to connect MyClass to the event providers.
  63. Let's not throw the baby out with the bathwater. I think Lars was on the right track here with all the separate per-method interfaces, even though there are a lot of them.

    I framed the argument in my mind from a language perspective. Interfaces are used for typing purposes. Annotations are used to provide other useful information. Just as marker interfaces are bad (and properly replaced with annotations) because they misuse a language construct in the name of convenience, it would likewise be bad to misuse annotations in the way proposed.

    What is needed in callbacks is typing information. If this class implements a set of methods (in this case a set of one), then cast the object to that type, and safely call a method in that set. Basic object typing.

    Obviously if we just had one or two callback methods there wouldn't be any controversy. Yes, having a larger number makes it feel somewhat awkward, but that doesn't mean its not the right thing to do.
    Using interfaces here is straightforward and immediately understandable; the only problem in the "explosion" of interfaces is in documentation.

    Though I wouldn't agree with the suggestion of creating interfaces that extend all the other interfaces because it again misuses the 'interface' language construct, it does provide a logical grouping in code that helps. I would just implement it differently - packages are the language construct used for grouping purposes, so why not just create a separate package for "lifecycle", "persistence", "entitymgmt", etc. and place the micro-interfaces there?
  64. it can be important for the container to determine if the callback it is about to invoke is a no-op or if it contains an implementation written by the user, because the container might have some potentially expensive work to do before invoking the said callback.
    Cedric, can you explain by an example what the container would do if it can determine the callback method is empty ?
    And what it would do if the same method is *not* empty ?
  65. The Common Case[ Go to top ]

    I totally agree with many posts in this thread. In a world where we are moving towards loosely coupled systems, adding tight coupling through code annotations seems like a step back.There are a number of common patterns that do not seem to be solved with many persistence layers out there, and I can't see how EJB 3.0 can help either:1) Read from DS1 write to DS2 (for data migration, etc)2) Read from a view, write to multiple tables3) Read from a table, write through stored proceduresAny ideas how these things can be addressed.
    Number 2 IMO is big. That caused some headaches back in the EJB 1.1 days. I thought I heard that Oracle9i now allows writing through views to multiple tables. I haven't tested this though! :-)
  66. The Common Case[ Go to top ]

    In fact, one of the major causes of "J2EE complexity" is standards that solve difficult, uncommon cases, without considering the importance of the common case.
    That's of course true.
    But other true fact is that there is a big differnce between that what's good
    and what people want. EJB was early attempt to bring CBSE to mainstream
    enterprise devlopment. It is and was far away from being perfect and cleary some improvment are needed as some lessons were learned but I do feel
    that people who were behind early EJB had better understanding of what components are. Most of the people still dislikes very idea of having container thus they dislike the idea of components. They don't want to use components and integrate them in different environment but they want to write the code themslves. EJB 3.0 is trying to pleased those people. Anything which collapses metadata to java code is a step back. Nobody is yet selling say user managment system which can be integrated smoothly and deeply (e.g. transacions should be propagated between independently developped componenets) with othe components in large enterprise application. And this is not going to happen soon. But to make it possible one surly needs to be able to configure components coming from third party vendors in order to use them. Probably industry is not yet ready for such things.

    Michal
  67. EJB3[ Go to top ]

    (2) I'm not at all convinced that (for example) column names typically change at deployment time. I think that is the *uncommon case*, and that we should solve the common case -first-, then ask about the uncommon cases. In most environments database schemas change MUCH less frequently than Java source code, so I'm not at all uncomfortable with embedding ORM metadata in the Java code. Indeed, many Hibernate users are doing this today using XDoclet, with great success. We *do* need code folding support in the IDEs, however.
    One point to this is where 3rd party software people deploy at a customers and the schema is totally different and considerable mapping work needs to be done.
  68. JPA entityManager has a persist() method that throws an exception if the object is already persisted and the POJO is persistent at that point (no duplicate is created).