2 Replies Latest reply on Nov 12, 2003 8:05 AM by Thomas Louis

    read-only optimization of entity beans

    Jon Martin Solaas Newbie

      There is an article available at OnJava now describing how to optimize deployment so that get-methods are excluded from transactions and JBoss uses commit option A. (http://www.onjava.com/pub/a/onjava/2003/05/28/jboss_optimization.html?page=1)

      Basically this is pretty easy to set up following the instructions in the article.

      However, when it comes to CMR getters, things get slightly more complicated, because one can't manipulate a read-only CMR collection, still it'd be nice to access the CMR collection read-only when there is no updates to be done, to gain speed.

      A suggestion from the authors is to make two deployments of the same bean, one with the cmr-getter read-only, and one with write-access. This will work, but I suppose it requires some deployment descriptor overhead:

      Suppose I have a TeamEJB and a MemberEJB and a one to many or many to many relation between them, implying a getMembers() function in TeamEJB.

      Also suppose I've already optimized deployment in accordance with the article, setting getMembers() (and all other getters in TeamEJB) read-only in jboss.xml. Now, I have code that add members; a'la

      teamEJB.getMembers().add(newMemberEJB);

      This won't work anymore because getMembers() returns a read-only collection, and JBoss throws an exception runtime.

      So the proposed solution is to create a new deployment, so that I can get a bean instance where getMembers() is not read-only. In order to do this I suppose I must:

      1. create description of TeamEJB_RW in ejb-jar.xml. This could be done just copying the from the original deployment of TeamEJB and just change <ejb-name> and <display-name>

      2. create needed transaction attributes for methods in the new description created in 1.

      3. update jbosscmp-jdbc.xml so that both deployments (TeamEJB and TeamEJB_RW) access the same table (I suppose it's the ejb-name and not the actuall class names that affect this)

      4. update jboss.xml so that all getters _except_ getMembers() in TeamEJB_RW are read-only. (All getters (including getMembers() in TeamEJB would still be read-only too)

      5. Duplicate the relation between TeamEJB and MemberEJB so that TeamEJB_RW and MemberEJB are related in the same way.

      Now, it'd be possible to access all getters read-only using TeamEJB and still manipulate the getMembers() collection thru' TeamEJB_RW when needed. I suppose this is all I've got to do (but I'm not completely sure, please share your knowledge :-)

      Still, I feel I've produced quite an amount of xml to achieve this. When I have more than a few beans and a larger amount of relations amongst them, this sounds like a lot of work to deploy, and not exactly what one would love to maintain.

      So I wonder how I could do this a little easier. Would anyone care to comment on an alternative approach, perhaps like below:

      1. Deploy optimizations like described in the article so that all getters are read-only.

      2. Define a second getter and a new collection attribute for the collection of read-write members, lets call the attribute membersRW, in the bean (and appropriate interface), and let's call the method getMembersRW(), specify it in ejb-jar.xml as well in the section, and define transaction attribute.

      3. Make a new <ejb-relation> in ejb-jar.xml, just like the previous one, except that it'd map to the new attribute, members_RW.

      Now I'd be able to use separate getters on the same TeamEJB to get a read-only and a read-write version of the members collection. I'm not sure it'd work, though. For instance, would adding a member to the read-write collection/relation cause the new member to show up in the old read-only members collection/relation?

      Any hints and tips on the subject would be most welcome.

      --
      Jon Martin Solaas
      jonmartin.solaas@mail.link.no

        • 1. Re: read-only optimization of entity beans
          Jon Martin Solaas Newbie

          The easiest way to cope with this seems to be to just create a new Collection in the business method that wants to manipulate the collection, based on the collection that the read-only getter delivers, .add/.remove on that collection instead, and then use the set-method to write it back, like this (old code commented out):

          contentEJB = contentMasterHome().findByPrimaryKey(contentID);
          //themeEJB.getContent().add(contentEJB);
          Collection content = new ArrayList(themeEJB.getContent());
          content.add(contentEJB);
          themeEJB.setContent(content);



          The overhead is that a new collection has to be created, populated and written back, and I suppose the sql that actually runs when the set method is called is more heavy, but still it's outweighted by the overall performance gain. I'm writing a small CMS system (ie. re-inventing the wheel), and updates aren't that frequent after all, and it won't handle waste amounts of content anyway.

          --
          Jon Martin Solaas

          • 2. Re: read-only optimization of entity beans
            Thomas Louis Newbie

            Hi Jon,

            what about this idea:

            add add- and remove-methods to your entity bean like this

            public abstract Collection getMembers();
            public void addMember(MemberLocal m) {
            getMembers().add(m);
            }
            public void removeMember(MemberLocal m) {
            getMembers().remove(m);
            }

            Would this work? I think this depends on where JBoss interceptors makes function-results read-only. Did you try this earlier?

            Thomas