5 Replies Latest reply on Oct 31, 2013 4:48 PM by jfuerth

    ErraiEntityManager: Missing event before merge

    jannis

      Hello,

       

      is it possible to add an event that is fired before an entity gets merged into another one, or to change the existing PrePersist / -Update events to be fired on the entity that will be merged, instead of the one that has been merged?

       

      This is necessary for us, as we need to prepare entities before they are persisted. More precisely, we have nested objects which are not known to the entity manager. We marshal these objects into a JSON String which is stored in a helper field:

       

      @Entity
      public class ExampleEntity {
           @Transient
           private Nested nested;
      
           private String nestedHelper;
      
           @PrePersist
           private void prePersist() {
                nestedHelper = Marshalling.toJSON(nested);
           }
      
      
           @PreUpdate
           private void preUpdate() {
                nestedHelper = Marshalling.toJSON(nested);
           }
      
           @PostLoad
           private void postLoad() {
                 nested = Marshalling.fromJSON(nestedHelper, ExampleEntity.class);
           }
      }
      

       

      When a new version from this entity is received from the server, it is merged into the entity manager. The helper field of the received entity is null and after the merge the nested object is null as well. Our problem is, that the marshalling is not done, because neither PrePersist nor PreUpdate got called for the received entity. One of them is fired after the merge for the merged entity.

       

      One solution might be the introduction of a new event to notify that an entity is about to be merged into another one. But I think that this would be inappropriate. The other events are general events from javax.persistence and one event should be enough.

      My other idea would be to change the already existing PrePersist / -Update events to be fired before the merge and not for the merged entity but the entity that will be used as basis for the merge. I think, that this would rely to the documentation:

      @PrePersist The entity is about to be persisted or merged into the entity manager. (Errai)

      Problems with this idea might be that there are different objects getting notified by the PrePersist / -Update and the PostPersist / -Update events, the object being notified by the PrePersist / -Update events is not going to be persisted (directly) and that it is not managed.

       

      Alternatively, we would have to ensure, that nested objects are marshalled before merge is called.

       

      Are there any alternatives that I forgot to think of?

       

      Thanks in advance

      Jannis

        • 1. Re: ErraiEntityManager: Missing event before merge
          jfuerth

          Hi Jannis,

           

          I agree we shouldn't change the meaning of the existing javax.persistence annotations. As much as possible, we want to make the code work the same on the client and the server.

           

          An Errai-specific annotation for a "BeforeMerge" lifecycle event could solve the problem, but it still has the "different behaviour on the client and the server" problem.

           

          Have you considered making the Nested class another entity and using a one-to-one relationship between ExampleEntity and Nested?

           

          Alternatively, if we implemented @Embeddable, would you consider using that instead of the custom-serialized JSON string?

          • 2. Re: ErraiEntityManager: Missing event before merge
            jannis

            Hello Jonathan,

             

            yes, you are right. What we actually need is an implementation of @Embeddable. That is what we try to achieve with our implementation.

             

            For the moment, we changed the PrePersist / -Update event to be fired for the entity that will be merged and before the merge is performed. Additionally we manually call our postLoad method to demarshal the helper fields to the actual nested objects of the merged entity.

             

            Is the implementation of @Embeddable planned for the near future?

             

            Cheers

            Jannis

            • 3. Re: ErraiEntityManager: Missing event before merge
              jfuerth

              Hi Jannis,

               

              Yes, we can implement Embeddables on the Errai 3.0 branch. We wanted to see how much traction client-side JPA was going to get before implementing every last bit of it. For example, we just added support for abstract entities, entity inheritance, and polymorphic queries a couple of weeks ago based on a similar request. By "chipping away at it" on demand like this, we hope we can keep the quality high for the parts that are implemented.

               

              Would you be interested in helping add support for @Embeddable? It should be a relatively straightforward addition to what's already there.

               

              -Jonathan

              • 4. Re: Re: ErraiEntityManager: Missing event before merge
                jannis

                Hi Jonathan,

                 

                sorry for the late response. I am not sure whether I am enough into the generation of the ErraiEntityManagerFactory and I am not sure which components need to be adapted to add support for @Embeddable.

                 

                Still, I would like to participate, but I am quite busy at the moment. So I don´t know when I will have enough time to work on the support.

                 

                We encountered a problem with the fired PostPersist / -Update events after merging. The problem occurs in the case of the old state being New or Detached. I think that the events are fired too early. When the event is fired, nested and referenced objects of the merged object are not merged yet.

                To test this, a test has to be performed in the event handler of the PostPersist / -Update event. If the object of the event is stored and the test is performed after the merge is completed, nested and referenced objects are there. The problem is that they are not there when the event handler is called.

                 

                To avoid this problem, the firing of PostPersist / -Update events can be moved to the end of applyCascadingOperation if the new state is Merge and the old state is either New or Detached. I would like to send a pull request for this issue, but have to wait until I have some more time. I attached a file containing the changes I made to applyCascadingOperation.

                 

                Cheers

                Jannis

                • 5. Re: Re: ErraiEntityManager: Missing event before merge
                  jfuerth

                  Thanks for digging into this, Jannis!

                   

                  We're definitely interested in a pull request with your fix to the timing of PostPersist and PostUpdate events. Since we protect all Errai functionality with automated tests, the PR should come with an additional test case in ErraiJpaTest that ensures the referenced/nested objects are already merged (and of course this test should pass when run in the context of HibernateJpaTest.)

                   

                  If you need any help setting up your environment for running the tests, just pop into #errai on freenode.net and we'll be happy to help!

                   

                  Thanks again!