0 Replies Latest reply on Nov 30, 2006 8:59 AM by toni

    Bugs? Weird transaction problems

    toni

      Hi,

      I have a JSP file, which contains a table that displays a list of clients. Each of the clients can have many addresses attached to it.

      If you click on one of the clients you end up on a second page, which again displays a table that lists all the addresses of the selected client.

      There exists a corresponding Statefull Session Bean (SSB) for each JSP. Both SSBs called ClientAction and AddressAction contain a funtion, which returns the DataModel containing the clients and addresses respectively.

      The first SSB also has a function, which returns the selected Client from the DataModel, so that the second SSB can get the currently selected client to display his addresses:

      public Client getSelection()
      {
      return (Client) dataModel.getRowData();
      }

      The second SSB calls the above function to get the currently selected Client and to retrieve the client's addresses to initialize it's own DataModel that it needs for it's JSP page.

      If this function is called from the AddressAction SSB and we do NOT use an EXTENDED persistent context inside the ClientAction SB (see NOTE A), then we get the first exception (this is only the beginning):

      "Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.pilati.calc.model.Client.proposals, no session or session was closed"

      After I change the persistent context of the ClientAction SSB to an extended one, I get rid of the exception, but noticed something else, which seems very strange to me: It's a matter of live or death for my application, from which method inside the AddressAction the getSelection() method gets called.

      In particular I it's very unhealty to call it from within the "getAddresses()" method of the AddressAction SSB, which is used to initalize the DataModel for use in the JSP file that displays the addresses. If I place the getSelection() method into the function which returns(!) the DataModel, the I get the following exception:

      "Caused by: org.hibernate.TransactionException: Could not register synchronization
      at org.hibernate.transaction.CMTTransaction.registerSynchronization(CMTTransaction.java:159)
      at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:59)
      at org.jboss.ejb3.stateful.StatefulBeanContext.closeExtendedPCs(StatefulBeanContext.java:284)
      at org.jboss.ejb3.stateful.StatefulBeanContext.remove(StatefulBeanContext.java:268)
      ... 169 more
      Caused by: javax.transaction.RollbackException: Already marked for rollback TransactionImpl"

      If I instead move the "getAddresses()" out of the function, which returns the DataModel to the JSP page that displays the addresses into the the "list()" function, which gets called when the user clients onto the link that selects a client, then everything works fine. This is good, but it seems that something is very wrong here!?

      To sum it all up I have two questions:

      1.Why do I need a extended persitent context? After the ?getClients()? returns all the Entities should be detached from the persitent manger, shouldn't they? So why would a call to return the client (not the addresses inside) cause a LazyInitializationException, when I had retrieved the client object already before?! After all the getSelection only returns a client, which has already been fetched.
      2.Why do I get a TransactionException, when I call the ?getSelection()? method in the function, which returns the DataModel to the JSP page(which needs it to render itself) but NOT when I place it into the method, which gets called to navigate to the JSP page???

      Here are the important code snippets:


      Client SSB
      ------------
      public class ClientAction implements BasicClientAction
      {
      // NOTE A: This throws the first exception so I remove it
      //@PersistenceContext

      @PersistenceContext(type=PersistenceContextType.EXTENDED)
      EntityManager entityManager;

      // Stores all the clients
      DataModel dataModel;

      @Begin(join = true)
      public DataModel getClients()
      {
      if (dataModel == null)
      dataModel = new ListDataModel();
      dataModel.setWrappedData(entityManager.createQuery("from Client").getResultList());
      return dataModel;
      }

      public Client getSelection()
      {
      return (Client) dataModel.getRowData();
      }
      ...
      }

      Address SSB
      ---------------
      @Name("addressAction")
      @Stateful

      public class AddressAction implements BasicAdressAction
      {
      // Makes not difference if I set the context to extended or not
      @PersistenceContext
      EntityManager entityManager;

      @In(create = true) @Out @Valid
      Address address;

      // Stores all the addresses of a SELECTED client
      DataModel dataModel;

      // This is needed to retrieve the currently selected client
      @In(required = false)
      BasicClientAction clientAction;

      Client selectedClient;

      public String list()
      {
      // NOTE B: Calling the getSelection() from here DOES NOT cause an excepiton
      //selectedClient = clientAction.getSelection();
      return "addresses";
      }

      @Begin(join = true)
      public DataModel getAddresses()
      {
      if (dataModel == null)
      dataModel = new ListDataModel();

      // NOTE B: If the JSP page calls this fuction to initalize itself, the
      // we get an exception
      selectedClient = clientAction.getSelection();

      dataModel.setWrappedData(selectedClient.getAddresses());
      return dataModel;
      }
      ...
      }