3 Replies Latest reply on Feb 6, 2012 1:58 PM by lightguard

    Seam3: General question regarding JSF and persistence in conversations (& flushing)

    waterman

      Hi,

       

      I am quite new to Seam and have a general question: I wonder how to generally realize a basic CRUD use case using JSF and seam with regard to persistence. The documentation I found is not really clear to may. However I found very little documentation, so maybe I missed something.

       

      I find it quite common to have a long running conversation consisting of multiple pages where the user might change multiple fields of multiple entities during the conversation. On the last page the user can decide to "Save" or "Cancel". On the prior pages no data is written to the DB.

       

      1) I think with Seam 2 one would start a new conversation with @Begin(flush=Manual) and just flush manually at the end of the conversation if the users decides to save. Sound reasonable and simple to me.

      Is this still the way to go with Seam 3? How can I implement this with Seam 3? (@Begin has no flush mode any more)

      I found the FlushModeManager, but it is hardly documented. Should this class be used? Which affect has modifying the FlushModeManager? Has it the same scope as the EntityManager?

      Or do I have to fallback to the underlying Hibernate API? How?

       

      2) I generally understand that it is a good idea to use EntityManager with extended scope to avoid application layering (DTOs, detach/merge,...) for such situations.

      What are the pros/cons/alternatives?

       

      3) Does it make any sense to use stateful SB for these cases? Or should one avoid the overhead, use plain JSF managed beans and use the transactions managed by Seam JSF (apparently 2 per Request: Is there any documentation? Documentation for Seam persistence 3 is *very* short).

      What are the pros/cons? What are the advantages of Seam Managed Persistence Contexts?

       

      I know my questions are somewhat general, but I a missing some high level documentation regarding this questions.

       

      Any help is very welcome.

      Best regards,
      Andreas

        • 1. Re: Seam3: General question regarding JSF and persistence in conversations (& flushing)
          bram666

          Ola,

           

          In my application all the long running stuff (creating entrries and so on) can have multiple pages and are in a conversation scope, but the interaction with the database and the final "store" is the only place i do in a transaction. It realy depends on the application/requirements if you need a long running transaction as well. I basicly use the same method used in the example for the 'actions' with a conversation that starts in the 'load' and ends in the save or cancel. I still use dto's though, i find it easier to just make them and split up my code in a database kind of layer with all the right finders/creators and so on (if my app gets bigger/complexer i can easy make them ejb's later on, eg if i need SSB) and an 'action' layer what is called by the jsf pages.

           

          regarding your 3e questions. I think that the seam-persistence module is mainly to hide the differences betwean a server managed emf and a webapp managed emf (differences between deploying in a JEE container and a servlet container) and some code to enlist the em to a running transaction and have not found anything yet for long running transactions. All in all i think that without a JEE container (where you can use SSB) a long running transaction is not something i would go for, i would see if i can change the requirements so a update or store can be done in one request.

           

          some code i use:

           

          @Named

          @ConversationScoped

          @UrlMapping(pattern = "/rss/#{iid:rssAction.id}")

          public class RssAction implements Serializable {

           

               @Inject

              Conversation conversation;

           

              @Inject

              RssDao rssDao;

             

              private RssModelImpl model;

           

              @Inject

              @RequestParam("id")

              private Instance<String> idProvider;

           

              public String create() {

                  conversation.begin();

                  model = new RssModelImpl();

                  return "edit?faces-redirect=true";

              }

           

              @SuppressWarnings("unchecked")

              public boolean isLoad() {

                  // Only load the layout if a id has been provided

                  String id = idProvider.get();

                  if (model == null && id != null && conversation.isTransient()) {

                      conversation.begin();

                      model = rssDao.find(Long.valueOf(id));

                      return true;

                  }

                  return false;

              }

           

               @Transactional

              public String delete(RssDTO dto) {

                  rssDao.delete(dto.getId());

                  return "index?faces-redirect=true";

              }

           

               @Transactional

              public String save() {

                  if (model.getId()== null) {

                      rssDao.create(model);

                  } else {

                      rssDao.update(model);

                  }

                  conversation.end();

                  return "index?faces-redirect=true";

              }

           

               public String cancel() {

                  this.model = null;

                  conversation.end();

                  return "index?faces-redirect=true";

              }

           

               public RssModelImpl getModel() {

                  return model;

              }

          }

          • 2. Re: Seam3: General question regarding JSF and persistence in conversations (& flushing)
            waterman

            Hi Bram,

             

            thank you very much for your answer!

             

            But one of the benefits I expect from Seam is that no DTOs are required. Reason: This saves a lot boilerplate code (DTOs itself, DAO, ...)

            Of course, when working with DTOs the setup is quite simple and clear to me, too.

             

            But imagine you have a complex data model consisting of JPA entities. On start of the conversation I pick one root entity, start editing it and its associated entities. A few screen later I would like to save to the DB. All changes at once.

            Without mapping entities to DTOs and vice versa, without DAOs.

            But thanks again, Bram!

             

            So I need to be sure, that flush() is postponed until a user defined call. How can I achieve this?

            Or is a different approach more approriate? Which?

             

            Best regards & thanks in advance!

            Andreas

            • 3. Re: Seam3: General question regarding JSF and persistence in conversations (& flushing)
              lightguard

              Andi, you can use the FlushModeManager. Simply inject it and change the setter. You should be good to go.  If you need to drop down into the Hibernate API, you can get the Session by calling EntityManager.getDelegate() and casting that to the Hibernate Session.