title: Persistent aware KieSession not using Pessimistic Lock during transactions
body: <p>I am using <strong>Drools</strong> with <strong>Spring Boot</strong> 2.3 and I have implemented the persistent aware <code>KieSession</code>, in which <strong>MySQL</strong> is used for storing the session. I have successfully integrated the default <code>EntityManagerFactory</code> of Spring Boot with Drools but my problem is with transactions. By default, Drools uses Optimistic Lock during transactions but it allows us to use the Pessimistic Lock as well, which is what I want. Now while firing rules, Drools persists/updates the KieSession in MySQL with the following query:</p>
  <pre><code>update SessionInfo set lastModificationDate=?, rulesByteArray=?, startDate=?, OPTLOCK=? where id=? and OPTLOCK=?
  </code></pre>
  <p>Now the above statement is executed twice if I do not use transactions using the <code>@Transactional</code> annotation in the method, and if <code>@Transactional</code> is used then the above statement is executed only once after firing the rules.</p>
  <p>Now, if I manually change the value of the OPTLOCK field then Drools throws an exception:</p>
  <pre><code>javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]
  </code></pre>
  <p>followed by:</p>
  <pre><code>Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]
  </code></pre>
  <p>I am unable to post the entire Stacktrace due to text length limitations here. The entire stacktrace can be viewed in <a href="https://github.com/samimaftabahmed/spring-drools-persistence" rel="nofollow noreferrer">this GitHub project</a>.</p>
  <p>I am not sure whether Drools is using the Pessimistic Lock as defined in the environment. About my session implementation, I want to have a single <code>KieSession</code> since I am using KieSession as a <code>Bean</code>.</p>
  <p>Below is my implementation:</p>
  <p>The configuration class:</p>
  <pre class="lang-java prettyprint-override"><code>@Configuration
  public class DynamicDroolsConfig {
  
      private KieServices kieServices;
      private KieFileSystem kieFileSystem;
  
      @Autowired
      private PersistentSessionDAO persistentSessionDAO;
      @PersistenceUnit
      private EntityManagerFactory entityManagerFactory;
      @Autowired
      private PlatformTransactionManager platformTransactionManager;
  
  
      @PostConstruct
      private void init() {
          this.kieServices = KieServices.Factory.get();
          this.kieFileSystem = kieServices.newKieFileSystem();
      }
  
      @Bean
      public KieServices getKieServices() {
          return this.kieServices;
      }
  
      @Bean
      public KieContainer getKieContainer() {
          kieFileSystem.write(ResourceFactory.newClassPathResource(&quot;rules/rules.drl&quot;));
          final KieRepository kieRepository = kieServices.getRepository();
          kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
          KieBuilder kb = kieServices.newKieBuilder(kieFileSystem).buildAll();
          KieModule kieModule = kb.getKieModule();
          return kieServices.newKieContainer(kieModule.getReleaseId());
      }
  
      @Bean
      public KieFileSystem getFileSystem() {
          return kieFileSystem;
      }
  
      @Bean
      public KieSession kieSession() {
          List&lt;SessionInfo&gt; sessionDetails = persistentSessionDAO.getSessionDetails();
  
          if (sessionDetails.size() == 0) {
              return kieServices.getStoreServices().newKieSession(getKieContainer().getKieBase(), null, getEnv());
          } else {
              return kieServices.getStoreServices().loadKieSession(sessionDetails.get(0).getId(), getKieContainer().getKieBase(), null, getEnv());
          }
      }
  
      private Environment getEnv() {
          Environment env = kieServices.newEnvironment();
          env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
          env.set(EnvironmentName.TRANSACTION_MANAGER, platformTransactionManager);
          env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);
          env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING_MODE, LockModeType.PESSIMISTIC_FORCE_INCREMENT.name());
          return env;
      }
  }
  </code></pre>
  <p>The controller class:</p>
  <pre class="lang-java prettyprint-override"><code>@RestController
  public class MyController {
  
      @Autowired
      private KieSession kieSession;
  
      @Transactional
      @GetMapping(&quot;fire-person&quot;)
      public void firePerson() {
          Person person = new Person();
          person.setName(&quot;Christy&quot;);
          kieSession.insert(person);
          kieSession.fireAllRules();
      }
  }
  </code></pre>
  <p>The Fact class</p>
  <pre class="lang-java prettyprint-override"><code>public class Person implements Serializable {
  
      private String name;
      private int age;
      private String gender;
      private String toCompareName;
      private String toCompareGender;
  
      // getters and setters
  }
  </code></pre>
  <p>The repository interface:</p>
  <pre class="lang-java prettyprint-override"><code>public interface DroolsSessionRepository extends JpaRepository&lt;SessionInfo, Long&gt; {
  }
  </code></pre>
  <p>The service class:</p>
  <pre class="lang-java prettyprint-override"><code>@Service
  public class PersistentSessionDAO {
  
      @Autowired
      private DroolsSessionRepository droolsSessionRepository;
  
      public List&lt;SessionInfo&gt; getSessionDetails() {
          return droolsSessionRepository.findAll();
      }
  }
  </code></pre>
  <p>The runner class:</p>
  <pre class="lang-java prettyprint-override"><code>@EntityScan(basePackages = {&quot;com.sam.springdroolspersistence.entity&quot;, &quot;org.drools.persistence.info&quot;})
  @EnableJpaRepositories
  @SpringBootApplication
  public class SpringDroolsPersistenceApplication {
  
      public static void main(String[] args) {
          SpringApplication.run(SpringDroolsPersistenceApplication.class, args);
      }
  }
  </code></pre>
  <p>The Drools dependencies used:</p>
  <pre class="lang-xml prettyprint-override"><code>        &lt;dependency&gt;
              &lt;groupId&gt;org.drools&lt;/groupId&gt;
              &lt;artifactId&gt;drools-persistence-jpa&lt;/artifactId&gt;
              &lt;version&gt;${drools-version}&lt;/version&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.kie&lt;/groupId&gt;
              &lt;artifactId&gt;kie-spring&lt;/artifactId&gt;
              &lt;version&gt;${drools-version}&lt;/version&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.jbpm&lt;/groupId&gt;
              &lt;artifactId&gt;jbpm-persistence-jpa&lt;/artifactId&gt;
              &lt;version&gt;${drools-version}&lt;/version&gt;
          &lt;/dependency&gt;
  </code></pre>
  <p>The code implementation can also be found in <a href="https://github.com/samimaftabahmed/spring-drools-persistence" rel="nofollow noreferrer">this GitHub Project</a>. Any kind of help/suggestions will be much appreciated. Thank you.</p>