Discussions

EJB design: How can we really perform validation?

  1. How can we really perform validation? (30 messages)

    OK, here is a fairly interesting design question that surfaces when you begin to design non-trivial EJBs. Unfortunately, I will have to trivialize the example to make it easily presentable. The major assumption that you will have to make is an EJB cannot always validate itself. Sometimes the validation of an entity bean (a row in the database) can only be determined by another method external to the entity bean.

    Trivial Example
    ============
    A bank allows its customers to have multiple accounts, but the balance in all accounts combined, cannot be less than $100.

    Design
    ======
    Logically, we would create a stateless session bean Teller, that directly manipulates Account entity beans. Our database is set to read-uncommitted, a common and default setting of most databases. The withdrawal method in Teller
    performs the following pseudocode logic:

    1. Teller.withdrawal (String accountPK, BigDecimal amount) {
    2. // do the dirty work
    3. Account account = accountHome.findByPrimaryKey(pk);
    4. account.withdrawal(amount);
    5. // make sure account balances didn't drop below limit
    6. performLimitCheck();
    7. }

    Now the code in performLimitCheck() would determine all of the account beans that apply to this customer, and invoke methods on all of these beans to determine the sum of all balances. The sum would be compared to the minimum limit and a rollback would be issued if there is a business rule violation.

    Undesirable Performance
    =======================
    Given the trivial example, this seems like a reasonable request, but imagine if you will that there are thousands of accounts assigned to this customer, or perhaps an account can have sub-accounts, or any situation that further makes this operation a performance nightmare.

    In reality there are many validation scenarios where it would make more sense going directly to the database and issuing an aggregate query. This can sometimes mean that a database validation routine can operate 500x faster than a comparable EJB validation routine. Nothing to sneeze at.

    So what's the big deal, just use JDBC and validate. Not so fast...

    The Design Problem
    ===============
    The flaw with the above logic has to do with the order that the EJB container performs its operations. Line 4 above causes the ejbContainer to perform an ejbLoad() on our Account bean. Next the withdrawal() method is invoked and the bean's attributes reflect the new amount. Note: No data has been written to the database yet! By the time line 6 performs its validation of the current state of the database, the database hasn't changed one bit. Assuming the database was in a valid state before our withdrawal, it will always pass validation checks.

    It isn't until line 7 that the ejbContainer invokes ejbStore() and the Account bean writes the data to the database. At this time, the database may be in an invalid state, and we will never get an opportunity to validate the state of the database.

    The Workaround
    =============
    A poor workaround is to call ejbStore() before validating the bean, or in a worse case, invoke it at the end of the withdrawal() method. This shouldn't cause any integrity problems that I can see, although most entity beans would suffer performance slowdowns due to multiple ejbStore() calls.

    There is also a possibility that a Stateful Session Bean (SFSB) can be enlisted during an entity bean's ejbStore() event. If this SFSB implements the SessionSynchronization interface, its beforeCompletion() method will actually be called after all entity bean's ejbStore() events. The validation code would actually be invoked in the beforeCompletion() request. This may work with some EJB containers.

    The Solution
    ==========
    The EJB spec authors should give us a way to execute methods after all of the uncommited database writes occur, but before the TransactionManager commits.

    One way of doing this would be to add SessionSynchronization support to the Stateless Session Bean and issue the beforeCompletion() callback *after* the ejbStore(s) and before the TransactionManager.prepare(). This would be the only time that the state of the database could be truly ascertained, and a rollback request could be requested.

    As always, I am interested in your feedback. Please comment.

    jim

    Threaded Messages (30)

  2. How can we really perform validation?[ Go to top ]

    I'm pretty sure the EJB container calls ejbStore on your Account bean when the withdawal method completes (at least with WebLogic it does). So the database would be updated in step 4 of your scenario(just not committed - that wouldn't happen until the Teller withdrawal method completes successfully). Then in step 6, your performLimitCheck would be looking at a consistent state of the database.
  3. How can we really perform validation?[ Go to top ]

    Jim, the ejb container is just following the EJB spec. Your bean's ejbStore() is invoked by the EJB container after all of your methods execute. As long as a new transaction was not started by the withdrawal() method of step 4, no ejbStore() will be invoked until the session bean's business method completes. It is totally out of your control at that point.

    I can assure you that Weblogic or *any* EJB container works the same way in this regard.

    jim
  4. How can we really perform validation?[ Go to top ]

    The withdrawal method of your Account entity bean should have the TX_REQUIRED attribute, so that it will join an existing transaction or start one if necessary. Any method that changes the state of the Account bean should have TX_REQUIRED.

    If your Teller.withdrawal method has TX_REQUIRED, then it will begin the transaction and commit the transaction when it completes. However, this has nothing to do with when ejbStore on the entity bean gets called. From what I've seen, ejbStore gets called on the entity bean whenever a business method completes.
  5. How can we really perform validation?[ Go to top ]

    Jim, I'm sorry if I'm being contentious here, but this is not the way it works. Imagine if ejbStore() was invoked every time you made a business method call against the same entity bean! The performance penalty would be severe. In fact, this is one of the primary reasons that it is recommended to provide a session bean facade to an entity bean.

    To be fair, there is nothing in the spec that states that ejbStore cannot be called after each business method, but no containers (that I know of) do this because of the performance penalty incurred. ejbStore() is also called before the bean is passivated, however it is very rare to passivate an entity bean in a transaction. I doubt many EJB containers do this either.

    The only way it would work the way you describe is if the session bean didn't require a transaction and the entity bean did. This would be similar to a client making calls directly against an entity bean.

    As you noted, both bean's methods are marked as Required in my example.

    jim
  6. How can we really perform validation?[ Go to top ]

    Jim, I'm sorry if I'm being contentious here, but this is not the way it works.


    You're not being contentious. You are, however, wrong. Read on.

    >> Imagine if ejbStore() was invoked every time you made a business method call against the same entity bean!

    I don't have to imagine it! That's how it works!

    I put a simple example together and ran it under WebLogic 5.1 SP5. The example has one EntityBean (EmployeeBean) and one SessionBean (EmployeeServiceBean). Here are skeletons of each (I didn't include all required methods - setEntityContext, ejbActivate, ejbRemove, etc.):

    public class EmployeeBean implements EntityBean {
        public int manager;
        private int id;
        private double salary;

        public EmployeePK ejbCreate( int id ) throws CreateException, EJBException, RemoteException, SQLException {
           System.out.println( "In EmployeeBean.ejbCreate()" );
           return new EmployeePK( id );
        }

        public void ejbStore() throws RemoteException, EJBException {
            System.out.println( "In Employee.ejbStore()" );
        }

        public void setManager(int id){
            System.out.println( "In EmployeeBean.setManager()" );
        }

        public void setSalary(double salary){
            System.out.println( "In EmployeeBean.setSalary()" );
        }

    }


    public class EmployeeServiceBean implements SessionBean {

        public void createNewEmployee(int id, int manager, double salary) throws RemoteException {
            System.out.println( "In EmployeeServiceBean.createNewEmployee()" );
            try {
                System.out.println( "Creating new Employee with id = " + id );
                InitialContext context = new InitialContext();
                EmployeeHome home = (EmployeeHome)javax.rmi.PortableRemoteObject.narrow(context.lookup("EmployeeHome"), EmployeeHome.class);
                Employee emp = home.create( id );
                System.out.println( "Setting manager for new employee" );
                emp.setManager( manager );
                System.out.println( "Setting salary for new employee" );
                emp.setSalary( salary );
                System.out.println( "Leaving EmployeeServiceBean.createNewEmployee()" );
            } catch (NamingException e) {
                System.err.println( "Unable to locate EmployeeHome" );
            } catch (Exception e) {
                System.err.println( "Unable to create new Employee: " + e );
            }
       }

    }

    I created a simple EJB client which creates an EmployeeServiceBean and calls createNewEmployee(). Here's the output captured from the WebLogic console:

    In EmployeeServiceBean.createNewEmployee()
    Creating new Employee with id = 100
    In EmployeeBean.ejbCreate()
    Setting manager for new employee
    In EmployeeBean.setManager()
    In Employee.ejbStore()
    Setting salary for new employee
    In EmployeeBean.setSalary()
    In Employee.ejbStore()
    Leaving EmployeeServiceBean.createNewEmployee()

    As you can clearly see, ejbStore() is called after each business method invocation in EmployeeBean. I have not tried this in any other EJB 1.1 compliant app server, so it would be interesting to see if this behavior is consistent among app servers.

    If you'd like the complete source code for this example, post your email address and I'll mail it to you.
  7. How can we really perform validation?[ Go to top ]

    WebLogic supports both modes. Calling ejbStore after every business method or at the end of txn boundry. Check you descriptors.

    >>You can disable the default behavior by using the delay->>updates-until-end-of-tx deployment element. When you set >>this element to "false," WebLogic Server calls ejbStore() >>after each method call, rather than at the conclusion of >>the transaction.
  8. How can we really perform validation?[ Go to top ]

    I added the following element to the <persistence-descriptor> section of weblogic-ejb-jar.xml:

    <delay-updates-until-end-of-tx>true</delay-updates-until-end-of-tx>


    Made absolutely no difference. ejbStore() still gets called after each business method invocation.
  9. How can we really perform validation?[ Go to top ]

    Jim,

    Thanks for the example. I can assure you that the behavior that you are seeing (ejbStore() called after each business method) would cause container vendors to shudder. Imagine the performance drag called by the unnecessary constant execution of ejbStore()!

    The only thing I can imagine that may be wrong in your example is the transaction context. Please post your deployment descriptor. The only thing I can think of is that you have the entity bean set to Requires New.

    jim
  10. How can we really perform validation?[ Go to top ]

    Jim,

    Here's my ejb-jar.xml contents:

    <?xml version="1.0"?>

    <!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN' 'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>

    <ejb-jar>
      <enterprise-beans>
        <entity>
          <ejb-name>EmployeeBean</ejb-name>
          <home>EmployeeHome</home>
          <remote>Employee</remote>
          <ejb-class>EmployeeBean</ejb-class>
          <persistence-type>Bean</persistence-type>
          <prim-key-class>EmployeePK</prim-key-class>
          <reentrant>False</reentrant></entity>
        <session>
          <ejb-name>EmployeeServiceBean</ejb-name>
          <home>EmployeeServiceHome</home>
          <remote>EmployeeService</remote>
          <ejb-class>EmployeeServiceBean</ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Container</transaction-type></session></enterprise-beans>
      <assembly-descriptor>
        <container-transaction>
          <method>
            <ejb-name>EmployeeServiceBean</ejb-name>
            <method-name>*</method-name></method>
          <method>
            <ejb-name>EmployeeBean</ejb-name>
            <method-name>*</method-name></method>
          <trans-attribute>Required</trans-attribute>
        </container-transaction>
      </assembly-descriptor>
    </ejb-jar>

    The transaction attribute is set to Required for all bean methods. So the session bean method starts the tx, calls several methods in the entity bean, and then completes, committing the transaction. But ejbStore is called multiple times inside the tx.

    Jim
  11. How can we really perform validation?[ Go to top ]

    Thanks Jim.

    If there isn't any other things we might be overlooking, I would say that WebLogic's implementation is a programming nightmare. What you have shown is that WebLogic will call ejbStore() every time a business method is executed on an entity bean, even though all of those methods take place within the same transaction.

    Although this behavior doesn't violate the intent of the EJB specification, I would say that it violates any basis of common sense. Why even support the concept of a dirty flag? There will be no way for your bean to know if the ejbStore() call is the last one in a transaction, or just a series of transitional stages. I don't envy you (or the other 70% of the market using WebLogic). ;-)

    I would assume that there is some fundamental switch in WebLogic that you are missing.

    jim
  12. How can we really perform validation?[ Go to top ]

    Jim,

    The WebLogic documentation seems to support my hypothesis, although your example contradicts it. Must be a weird setting someplace.

    Check out:
    http://www.weblogic.com/docs51/classdocs/API_ejb/EJB_environment.html#1046004

    jim
  13. Hi Jims,

    For FWIW, I have run the example under WebSphere (or more specifically, under the VAJ Test Environment, which hopefully behaves the same as WebSphere in this example).

    The output that I got is:

    In EmployeeServiceBean.createNewEmployee()
    Creating new Employee with id = 100
    In EmployeeBean.ejbCreate()
    Setting manager for new employee
    In EmployeeBean.setManager()
    Setting salary for new employee
    In EmployeeBean.setSalary()
    Leaving EmployeeServiceBean.createNewEmployee()
    In Employee.ejbStore()

    Which is consistent with what Jim Cook is saying. Now what we need is some WebLogic architect to explain this :)

    Regs, Bartek
  14. How can we really perform validation?[ Go to top ]

    Tarek,

    The delayUpdatesUntilEndOfTx setting only applies to Container Managed Beans.

    jim
  15. How can we really perform validation?[ Go to top ]

    hi,

    i think the problem u talked about getting bad state from the database will only occur if u fire pure jdbc/SQL statements in ur performLimitCheck() business method. if u continue to use "Account" entity bean to perform this business logic there shud me no problem.

    for eg : u can fire account2.getBalance(), account3.getBalance() and then also use account.getBalance() to get the balance and perform ur necessary business logic.

    this way u r using the state of the entity bean and not state of the database which as u mentioned cud be different.

    please respond

    kapil


  16. How can we really perform validation?[ Go to top ]

    You are correct. If I use the EJB infrastructure to perform the validation there is no problem. What I tried to point out in my example, is that it can be up to 500x slower to use EJB structures to perform validation than simply querying the database. This is especially true when dealing with hierarchical data.

    The specification authors have an opportunity to allow direct database validation if they make the proposed changes in the next version of the spec.

    jim
  17. How can we really perform validation?[ Go to top ]

    i think the only workaround that wud work is not at all using any entity bean in business method cause then u r dealing with raw data. just fire pure jdcb statements or even write framework/wrapper over ur jdbc calls and then use that framework/wrapper for database access to give a more OO look to ur code.

    i anyway am not a great fan of entity bean concept. they r all good on paper for OO data access(may be other benifits too), but when they come to performance they r i guess not very slick. since entity beans r only reference to actual instance they can incurr a lot of network trips if ur entity beans r hosted over the network, which is very likely (consider an application server farm which will consist of multiple server)

    kapil

  18. How can we really perform validation?[ Go to top ]

    I don't entirely agree with your assessment of an entity bean's usefulness. If any components in a distributed environment are deployed without purpose, performance can most certainly drag. This isn't an entity bean phenomenon.

    I find it interesting that such an important failure as direct database validation is not evoking a lot of compassion. Have most others simply not faced a performance requirement where direct DB access was necessary?

    jim
  19. How can we really perform validation?[ Go to top ]

    what i am saying is Entity beans does give u certian benefits like OO data access(may be other too), but dat comes with a cost, namely performance. come to think of it if u have a entity bean representing ur customer profile with around 20 attributes. now u can fire these 20 getter methods on ur entity beans from ur session beans. great but what if the entity beans are sitting on a different machine. u got 20 network trips which is certianly gonna degrade ur performance. now u can employ detailed object(serialized versions) pattern to do the same task. the next question is why entity beans then. why not use the detailed objects in session bean methods, why wrap them(detailed objects) using ur entity beans.

    another thing is security. if u wrap ur database(tables) using entity beans u r making ur data public. any developer with access to the bean can have direct access(using JNDI ofcourse) to the bean and modify ur database. the better wud be to have session who represent ur actual business logic manage the data for u.

    the advantage that entity bean provide is OO data access which u can also say as OQL(object query language) which is very good for ur code). but for that u can also use products like TopLink, Visual BSF.

    ur views ???

    kapil
  20. How can we really perform validation?[ Go to top ]

    It seems like you are basing some of your opinions on supposition. I'm not going to detail the benefits of entity beans because that has been done to death. But your argument regarding machine to machine serialization should be a moot point.

    What I tried to explain earlier is that network calls are expensive (as you point out), and they should be avoided at all costs. If I deploy a system where every session bean is on a separate machine than the entity beans they work with, I should be fired. This is a very poor deployment-time decision. And again, it has nothing to do with entity beans. The same problems would exist if I deployed session beans that are logically coupled on different machines. The same thing would happen if I had CORBA objects on different machines. Welcome to the world of distributed programming.

    A similar form of security that exists in your database (typically user-group-role) also exists in EJB. Every bean method can have its own security constraints applied to it. The claims you make are incorrect.

    If all I needed was OO access to my data, I would probably be using JDO. I use entity beans because I need transaction management and security. These two items are the foundation of EJB, and they require no additional programming burden on the developer to achieve.

    jim
  21. How can we really perform validation?[ Go to top ]

    I didn't the read the other post. I just want to comment that in line 4, the change made will be visible to the validation since your validation method and the withdrawal is under the same transaction. Although the withdrawal is not yet committed, the validation should be able to see the change made. I've encountered this before with weblogic. It's a weblogic bug (I think it's called the local diamond). Installing sp6 will solve the problem.

  22. How can we really perform validation?[ Go to top ]

    Jerson,

    The problem I described is not due to a bug, it is a shortcoming in the EJB design. I'm not looking for a workaround, because there really isn't one.

    I can assure you that if an EJB container can see the results of line 4 in the database while line 6 (the validation routine) is executing, then there is most likely a bug in the EJB container.

    Keep in mind that the validation routine does *not* use the EJB model...it goes directly to the database to perform validation. Your statement is true if I validated against beans and not the database.

    jim
  23. How can we really perform validation?[ Go to top ]

    Yes.. you're right what I'm referring to is validation using beans not direct db access. Haven't tried direct db access.

    Anyway, how about passing the amount to be withdrawn to the validation method?

    cheers...
    Jerson
  24. How can we really perform validation?[ Go to top ]

    Jim,

    Would be kind enough to tell us (or point us) what those proposed changes could be, that provides a solution to the dilemma?

    I suppose, there should be some way (in Ejb 2.x) of telling the Ejb container to flush, otherwise I can't see how to support this as we are really trying to circumvent the container by doing direct DB access.

    -Nik.
    PS: On a slightly related note, I feel since the SB-as-a-facade-for-EB-pattern is wide spread, JDO is probably a better use in those cases, as the SB can provide the TX context. Here we are really interested in providing an OO DB representation, but are not interested in a networked remote object which is what an EB is. Just thinking aloud. Any thoughts on this?
  25. How can we really perform validation?[ Go to top ]

    Nik,

    My first post on this thread discussed one possible solution to the problem. The problem is that so many people have yet to "really" develop complex EJB systems with some "real-world" business rules. Many of the shortcomings with any system are experienced only in the real-world.

    I think the EJB model is fantastic. I also think that Microsoft/Roger Sessions pointed out some of the problems with the entity model early on. (Although I loathe the tactics of their approach). I also think that vendors such as BEA are quick to pick up on holes in the spec and implement a proprietary workaround, such as the read-only bean. There is also no way to implement a cross-VM singleton bean in EJB. Let me also say that validation (in a complex app) is a bitch.

    The EJB spec is new and it will evolve. It is important to realize that EJB was developed to simplify distributed development. EJB *does* make it easier to deal with security and transactions. EJB does *not* increase your application's performance. It does *not* make it easier to handle concurrency issues. These are still the developer's problems.

    At the current time, there exist some very real performance issues with the EJB model. This thread demonstrates one of these problems, and I hope it shows an area where EJB can be improved.

    Perhaps the solution to the "uncommited database validation" problem introduces concepts that are outside the EJB spec. If so, I suspect that some forward-thinking EJB container vendors will begin to supply a means of registering event listeners with the transaction managers. It would be nice if this was done in a portable fashion.

    jim

    PS: about your PS, perhaps you should post your thoughts on a different thread and begin a discussion. The "networked remote object" (enterprise bean) that you are not interested in is what EJB is all about. It is why you get transactional support, centralized business logic, and security.
  26. How can we really perform validation?[ Go to top ]

    Sorry for replying so late.
    About my PS: I was a little confused by your reply to my PS, till I noticed that you took EB as Enterprise Bean, while I meant EB as Entity Bean. Sorry!

    Looks like I don't need to start any thread for entity bean/JDO, there is a good one going on for that here: http://theserverside.com/home/thread.jsp?thread_id=4137

    -nik.
  27. How can we really perform validation?[ Go to top ]

    Jim,

    The issue you brought up is an interesting one. At our development team, we have also faced the similar (but more complex) problem.

    Perhaps I can take a shot at it and see what you think.

    As you said, if a customer should have thousands of accounts (nested or not), then to validate a single withdrawal involve all the Account EJB that belongs to the customer. What about creating a statless session bean to keep track of the customer's total balance across all accounts? There would be a stateless session bean, say, called TotalBalance, that would look something like this for the remote interface:

    public interface TotalBalance extends SessionBean
    {
    void ejbCreate() throws ...
    boolean canWithdraw(CustomerId pk, BigDecimal withdrawingAmount) throws ... ...
    void updateBalance(CustomerId pk, BigDecimal withdrawingAmount) throws ... ...
    ... ...
    }

    As such, your pseudologic can be slightly modify as the following:
    1. Teller.withdrawal (String accountPK, BigDecimal amount) {
    2. // do the dirty work
    3. TotalBalance totalBalance = totalBalanceHome.ejbCreate();
    4. Account account = accountHome.findByPrimaryKey(pk);
    5. if (totalBalance.canWithdraw(pk, amount)) {
    6. account.withdrawal(amount);
    7. totalBalance.updateBalance(pk, amount);
    8. }
    9. }

    - totalBalance.withdraw(CustomerId, BigDecimal) would check to make that the requested amount can be withdrew.
    - totalBalance.updateBalance(CustomerId, BigDecimal) would update the total balance for the specific customer.
    - totalBalance can be kept as an instance variable for the Teller object and that way TotalBalanceHome.ejbCreate() would not have to be called every time.

    Essentially, if all withdraw/deposit methods would also update the TotalBalance object, then the TotalBalance object can be used as part of the validation without inquiring other Account EJBs or calling the database.

    If there should be a substantial amount of customer, then the TotalBalance EJB can be modified as 1) a Stateful Session Bean, or 2) a partitioned Stateless Session Bean (like TotalBalanceA, TotalBalanceB, etc.) for performance and resource issues.

    What was done at our development team was to update the TotalBalance EJB after the withdrawl/update method as well. Performance is slightly affected, but accuracy is of more importance for us. In our case, step 6 (of above logic) is as follows:

    6. totalBalance.updateBalance(account.withdraw(amount));

    where withdraw() method returns the new total balance.

    Comment?





  28. How can we really perform validation?[ Go to top ]

    Mike,

    What you are suggesting is to pre-validate the state of the database before performing transactional activities. This is perfectly fine when possible, but it certainly has its problems in a complex system.

    I originally started implementing a mechanism as you describe, however it suffered somewhat from the fact that our data was hierarchical with constraints at different levels of the hierarchy. This necessitated the storing of these "roll-up" ammounts at each level of the hierarchy. I don't want to negate your idea, but the complexity was burdensome to the developers and the database schema.

    The "solution" to our problem is for the spec authors to add some capability to validate the uncommitted state of the database before the transaction manager issues its commit. I detailed this process more in my original post.

    I don't believe we will see this enter the spec because it isn't "pure" EJB, but rather describes a hybrid EJB environment. I think the best we will see is support from some container vendors to add event notification to their transaction management. It seems that the container vendors should be interested in adding this type of functionality to differentiate there offering from other vendors, especially when the performance benefit can be so huge.

    jim
  29. I would consider something like this:

    1) Use BMP (or don't use EJB entity beans at all).
    2) Separate all the persistence out into a separate class.
    3) Any database level validation (eg mandatory fields) would be enforced by the persistence class.
    4) Any business-rule level validation would be handled by a separate control object.

    There are a number of ways you could tie the control object to the entity:

    1) Not at all.
    2) The entity holds a list of control objects accessed by name.
    3) The entity is a factory for these control objects.
    4) The persistence class holds a list of control objects accessed by name.
    5) The persistence class is a factory for these control objects.

    I would say 4 and 5 are the lest preferred.

    Edward
  30. For a beginner/intermediate who is trying to follow this discussion, I strongly recommend you to visit

    http://java.sun.com/products/ejb/applyingEJB.html

    and download chapter8 and go thru it in order to undertstand what are the different types of transactions and how the behaviour differs between Entity and Session beans and also how the transactions are demarcated.

  31. How can we really perform validation?[ Go to top ]

    Absolutely right, validation is one of the (many) design flaws in EJB. If you want to criticise EJB you have to understand its roots (not that I'm criticising you, your spot on). Now I'm going to say something controversial.

    The EJB design was foremost (and still is) for building (selling) remote objects (middleware), and not about making life easy for application developers.

    Some of you will remember when Sun and Corba had a falling out about 3 years ago. The whole RMI/CORBA thing went a bit frosty, it wasn't even mentioned at the (2nd) Java One: then EJB appeared. EJB was a policital fudge by Sun to keep the Corba vendors on side. Unfortunately the designs are still being run by and for the middle-ware companies and not the developers. Just take a look at the specs (and I have built an EJB server) the client side /usablity examples are *very* thin on the ground.

    All the problems raised on this site, validation, client-side caching, performance tuning, development tools etc, etc are a consequence of this. EJB has very nice high-level design patterns for persistence but you have to remember ease of development is a secondary consideration. Still that keeps my (and hopefully your) contract rate high ;)

    www.javelinsoft.com