Spring Data MongoDB
  1. Spring Data MongoDB
  2. DATAMONGO-519

Cannot use the cross-store plugin in an application that has Entity classes with PrePersist or PreUpdate JPA handler methods

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.0.2
    • Fix Version/s: Backlog
    • Component/s: Cross-store
    • Labels:
      None
    • Environment:

      Description

      Scenario is that we have an application with a large number of JPA-managed entity classes (decorated with @Entity JPA annotation). Many of these classes have JPA event handling methods decorated with JPA annotations such as @PrePersist, @PreUpdate, etc. The underlying

      We would like to use the Spring Data MongoDB Cross-Store plugin in this application to persist some part of entity data to MongoDB. However, as soon as we enable the Cross-Store plugin for this application, the Spring application context fails to load with an error like the one below:

      Caused by: javax.persistence.PersistenceException: You can only annotate one callback method with javax.persistence.PrePersist in bean class: org.example.domain.Person
          at org.hibernate.ejb.event.CallbackResolver.resolveCallback(CallbackResolver.java:110)
          at org.hibernate.ejb.event.EntityCallbackHandler.addCallback(EntityCallbackHandler.java:123)
          at org.hibernate.ejb.event.EntityCallbackHandler.add(EntityCallbackHandler.java:61)
          at org.hibernate.ejb.event.JpaIntegrator.integrate(JpaIntegrator.java:151)
          at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:306)
          at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
          at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
          at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
          at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
          at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
          at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)
          at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
      

      I have found out that the root cause for the error is that the aspect MongoDocumentBacking weaves additional PrePersist and PreUpdate methods into entity classes. Since some of the classes already have methods with these annotations, Hibernate Entity Manager fails to validate these classes.

        Activity

        Hide
        Manish added a comment -

        I would say that rather than weaving callback methods into entity classes, the following approach would be cleaner and avoid all possible issues:

        1. Create JPA entity event listener classes and move PrePersist, PreUpdate, etc. code into these listeners.
        2. Change the aspects to first search whether an entity class has any field annotated as RelatedDocument.
        3. If an entity class has one or more fields annotated as RelatedDocument, check whether the class already has EventListeners annotation.
        4. If the EventListeners annotation is already present, add cross-store event listeners to the list. If not, add the EventListeners annotation to the class.

        Show
        Manish added a comment - I would say that rather than weaving callback methods into entity classes, the following approach would be cleaner and avoid all possible issues: 1. Create JPA entity event listener classes and move PrePersist, PreUpdate, etc. code into these listeners. 2. Change the aspects to first search whether an entity class has any field annotated as RelatedDocument. 3. If an entity class has one or more fields annotated as RelatedDocument, check whether the class already has EventListeners annotation. 4. If the EventListeners annotation is already present, add cross-store event listeners to the list. If not, add the EventListeners annotation to the class.
        Hide
        Michal Moravcik added a comment -

        Is there any update on this issue? I got stuck with the same problem.
        The workaround solution to migrate @PrePersist and @PreUpdate logic to EventListeners seems to be quite fragile and limiting.

        Show
        Michal Moravcik added a comment - Is there any update on this issue? I got stuck with the same problem. The workaround solution to migrate @PrePersist and @PreUpdate logic to EventListeners seems to be quite fragile and limiting.

          People

          • Assignee:
            Thomas Risberg
            Reporter:
            Manish
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: