Uploaded image for project: 'jBPM'
  1. jBPM
  2. JBPM-9923

OptimisticLockRetryInterceptor retry causes data update instead of insertion when persisting custom entity using Pluggable Variable Persistence

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • 7.62.0.Final
    • None
    • Runtime Engine
    • None

    Description

      OptimisticLockRetryInterceptor triggers retry logic when exception such as javax.persistence.OptimisticLockException or org.hibernate.exception.ConstraintViolationException is thrown.

      This impacts the pluggable variable persistence when persisting the custom entity classes.
      Originally it tries to insert a new entity but after the retry it updates the record instead.

      The culprit is in the JPAPlaceholderResolverStrategy class [1].

      public byte[] marshal(Context context,
                                ObjectOutputStream os, 
                                Object object) throws IOException {
              Object id = getClassIdValue(object);
              String entityType = object.getClass().getCanonicalName();
              
              EntityPersister entityPersister = persister.get();
      
              if (!entityPersister.isPersited(object)) {
                  EntityManager em = getEntityManager();
                  if (id == null) {
                      em.persist(object);
                      id = getClassIdValue(object);
                  }
                  addMapping(id, entityType, object, os, em);
                  em.merge(object);
                  
                  entityPersister.processed(object);
                  
                  // since this is invoked by marshaller it's safe to call flush
                  // and it's important to be flushed so subsequent unmarshall operations
                  // will get update content especially when merged
                  em.flush();
              }
              ByteArrayOutputStream buff = new ByteArrayOutputStream();
              ObjectOutputStream oos = new ObjectOutputStream( buff );
              oos.writeUTF(entityType);
              oos.writeObject(id);
              oos.close();
              return buff.toByteArray();
          }
      

      The marshall method inserts a new record if the id is null. It then updates(merge) the entity again.

      The code would work fine when id is null(doesn't exist in the db). However, in the situation described above, when the OptimisticLockRetryInterceptor triggers retry logic due to javax.persistence.OptimisticLockException or org.hibernate.exception.ConstraintViolationException, the id might already exist in the db. It should not update the record in this case.

      [1] https://github.com/kiegroup/drools/blob/main/drools-persistence/drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/marshaller/JPAPlaceholderResolverStrategy.java#L138-L145

      Attachments

        Issue Links

          Activity

            People

              elguardian@gmail.com Enrique González Martínez (Inactive)
              elguardian@gmail.com Enrique González Martínez (Inactive)
              Daniel Rosa Daniel Rosa
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: