title: When JMS updating record using JPA/Hibernate — TransactionRequiredException: No Transaction is in progress error
body: <p>What we are doing: Update subscription for received business ID.</p>
  
  <p>We receive business ID on activeMQ queue.</p>
  
  <p>JMSListener picked business ID, find the all associated subscription for received business.</p>
  
  <p>Process all subscription identify who need update (can be zero or more than one).</p>
  
  <p>For each subscription we call service method udate(SubscriptionDTO subscriptionDTO). Find the subscription entity object. This update method update the entity object using dto object. Then we call flush method on it. Note : Update method is annotated with @transactional. Call flush method from service@udpate(dto) method.</p>
  
  <p>We observed different behavior in windows vs Linux. On windows it worked well but on Linux we are getting failure after execution of flush method– javax.persistence.TransactionRequiredException: no transaction is in progress</p>
  
  <p>We tried adding @Transactional on JMSListner but got same error on Linux. But when we tried without call of flush method error gone but no update happened. Subscription data is same as before.</p>
  
  <p>Not sure how good problem was explained above.</p>
  
  <p>Looking for guidance, much appreciated for response. </p>
  
  <p><strong>JPA Configuration</strong></p>
  
  <pre><code>package edu.learn.config;
  
  @Configuration
  @EnableJpaRepositories(basePackages = "edu.learn.repositories",     entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef =     "transactionManager")
  @EnableTransactionManagement
  public class JpaConfiguration
  {
  private final String DEFAULT_TEST_QUERY = "SELECT 1";
  
  @Autowired
  private Environment environment;
  
  @Value("${datasource.maxPoolSize:10}")
  private int maxPoolSize;
  
  /*
   * Populate SpringBoot DataSourceProperties object directly from
   * application.yml based on prefix.Thanks to .yml, Hierachical data is
   * mapped out of the box with matching-name properties of
   * DataSourceProperties object].
   */
  @Bean
  @Primary
  @ConfigurationProperties(prefix = "datasource")
  public DataSourceProperties dataSourceProperties()
  {
      return new DataSourceProperties();
  }
  
  /*
   * Configure HikariCP pooled DataSource.
   */
  @Bean
  public DataSource dataSource()
  {
      DataSourceProperties dataSourceProperties = dataSourceProperties();
  
      HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder.create()
              .type(com.zaxxer.hikari.HikariDataSource.class).username(dataSourceProperties.getUsername())
              .password(dataSourceProperties.getPassword()).build();
      dataSource.setMaximumPoolSize(PropertyUtil.getMaxPoolSize(environment));
      dataSource.setInitializationFailFast(PropertyUtil.getInitializationFailFast(environment));
      dataSource.setMinimumIdle(PropertyUtil.getMinIdle(environment));
      dataSource.setConnectionTestQuery(DEFAULT_TEST_QUERY);
      dataSource.setConnectionTimeout(PropertyUtil.getConnectionTimeout(environment));
      dataSource.setIdleTimeout(PropertyUtil.getIdleTimeout(environment));
      dataSource.setMaxLifetime(PropertyUtil.getMaxLifetime(environment));
      dataSource.setDataSourceClassName(PropertyUtil.getDataSourceClassName(environment));
  
      if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(PropertyUtil.getDataSourceClassName(environment)))
      {
          dataSource.addDataSourceProperty("databaseName", PropertyUtil.defaultSchema(environment));
          dataSource.addDataSourceProperty("cachePrepStmts", PropertyUtil.getCachePrepStmts(environment));
          dataSource.addDataSourceProperty("prepStmtCacheSize", PropertyUtil.getPrepStmtCacheSize(environment));
          dataSource.addDataSourceProperty(
                  "prepStmtCacheSqlLimit", PropertyUtil.getPrepStmtCacheSqlLimit(environment)
          );
          dataSource.addDataSourceProperty("useServerPrepStmts", PropertyUtil.getUseServerPrepStmts(environment));
          dataSource.addDataSourceProperty("serverName", PropertyUtil.dbServerName(environment));
          dataSource.addDataSourceProperty("portNumber", PropertyUtil.portNumber(environment));
      }
      return dataSource;
  }
  
  /*
   * Entity Manager Factory setup.
   */
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException
  {
      LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
      factoryBean.setDataSource(dataSource());
      factoryBean.setPackagesToScan(new String[]
      {
              "edu.learn.model"
      });
      factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
      factoryBean.setJpaProperties(jpaProperties());
      return factoryBean;
  }
  
  /*
   * Provider specific adapter.
   */
  @Bean
  public JpaVendorAdapter jpaVendorAdapter()
  {
      HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
      return hibernateJpaVendorAdapter;
  }
  
  /*
   * Here you can specify any provider specific properties.
   */
  private Properties jpaProperties()
  {
      Properties properties = new Properties();
      properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
      properties.put("hibernate.globally_quoted_identifiers", "true");
      properties.put("hibernate.hbm2ddl.auto", "validates");
      properties.put("ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
      properties.put("show_sql", "false");
      properties.put("format_sql", "true");
  
      return properties;
  }
  
  @Bean
  @Autowired
  public PlatformTransactionManager transactionManager(EntityManagerFactory emf)
  {
      JpaTransactionManager txManager = new JpaTransactionManager();
      txManager.setEntityManagerFactory(emf);
      return txManager;
  }
  
  static class PropertyUtil
  {
      final static String DEFAULT_CHARACTER_ENCODING = "utf-8";
      final static String DEFAULT_DATASOURCE_CLASS = "com.mysql.jdbc.Driver";
  
      public static boolean getCachePrepStmts(final Environment environment)
      {
          String cachePrepStmts = environment.getProperty("spring.datasource.hikari.cachePrepStmts");
          if ("false".equalsIgnoreCase(cachePrepStmts))
          {
              return false;
          }
          return true;
      }
  
      public static int getPrepStmtCacheSize(final Environment environment)
      {
          String prepStmtCacheSize = environment.getProperty("spring.datasource.hikari.prepStmtCacheSize");
          try
          {
              return Integer.parseInt(prepStmtCacheSize);
          }
          catch(Exception e)
          {
              return 250;
          }
      }
  
      public static int getPrepStmtCacheSqlLimit(final Environment environment)
      {
          String prepStmtCacheSqlLimit = environment.getProperty("spring.datasource.hikari.prepStmtCacheSqlLimit");
          try
          {
              return Integer.parseInt(prepStmtCacheSqlLimit);
          }
          catch(Exception e)
          {
              return 2048;
          }
      }
  
      public static boolean getUseServerPrepStmts(final Environment environment)
      {
          String useServerPrepStmts = environment.getProperty("spring.datasource.hikari.useServerPrepStmts");
          if ("false".equalsIgnoreCase(useServerPrepStmts))
          {
              return false;
          }
          return true;
      }
  
      public static boolean getInitializationFailFast(final Environment environment)
      {
          String initializationFailFast = environment.getProperty("spring.datasource.hikari.initializationFailFast");
          if ("false".equalsIgnoreCase(initializationFailFast))
          {
              return false;
          }
          return true;
      }
  
      public static long getConnectionTimeout(final Environment environment)
      {
          String connectionTimeout = environment.getProperty("spring.datasource.hikari.connectionTimeout");
          try
          {
              return Integer.parseInt(connectionTimeout);
          }
          catch(Exception e)
          {
              return TimeUnit.SECONDS.toMillis(60);
          }
      }
  
      public static long getIdleTimeout(final Environment environment)
      {
          String idleTimeout = environment.getProperty("spring.datasource.hikari.idleTimeout");
          try
          {
              return Integer.parseInt(idleTimeout);
          }
          catch(Exception e)
          {
              return TimeUnit.SECONDS.toMillis(60);
          }
      }
  
      public static long getMaxLifetime(final Environment environment)
      {
          String maxLifetime = environment.getProperty("spring.datasource.hikari.maxLifetime");
          try
          {
              return Integer.parseInt(maxLifetime);
          }
          catch(Exception e)
          {
              return TimeUnit.SECONDS.toMillis(90);
          }
      }
  
      public static int getMinIdle(final Environment environment)
      {
          String minIdle = environment.getProperty("spring.datasource.hikari.minIdle");
          try
          {
              return Integer.parseInt(minIdle);
          }
          catch(Exception e)
          {
              return 5;
          }
      }
  
      public static int getMaxPoolSize(final Environment environment)
      {
          String maxPoolSize = environment.getProperty("spring.datasource.maxPoolSize");
          try
          {
              return Integer.parseInt(maxPoolSize);
          }
          catch(Exception e)
          {
              return 25;
          }
      }
  
      public static String getDataSourceClassName(final Environment environment)
      {
          String dataSourceClassName = environment.getProperty("spring.datasource.dataSourceClassName");
          if (dataSourceClassName != null &amp;&amp; "".equalsIgnoreCase(dataSourceClassName.trim()) == false)
          {
              return dataSourceClassName;
          }
          return DEFAULT_DATASOURCE_CLASS;
      }
  
      public static String getCharacterEncoding(final Environment environment)
      {
          String characterEncoding = environment.getProperty("spring.datasource.characterEncoding");
          if (characterEncoding != null &amp;&amp; "".equalsIgnoreCase(characterEncoding.trim()) == false)
          {
              return characterEncoding;
          }
          return DEFAULT_CHARACTER_ENCODING;
      }
  
      public static boolean getUniCode(final Environment environment)
      {
          String useUnicode = environment.getProperty("spring.datasource.useUnicode");
          if ("false".equalsIgnoreCase(useUnicode))
          {
              return false;
          }
          return true;
      }
  
      public static String showSQL(final Environment environment)
      {
          String showSQL = environment.getProperty("spring.datasource.hibernate.showSQL");
          if ("false".equalsIgnoreCase(showSQL))
          {
              return "false";
          }
          return "true";
      }
  
      public static String formatSQL(final Environment environment)
      {
          String formatSQL = environment.getProperty("spring.datasource.hibernate.format_sql");
          if ("false".equalsIgnoreCase(formatSQL))
          {
              return "false";
          }
          return "true";
      }
  
      public static String dbServerName(final Environment environment)
      {
          String dbServerName = environment.getProperty("spring.datasource.serverName");
          if (dbServerName == null || "".equalsIgnoreCase(dbServerName.trim()))
          {
              return "localhost";
          }
          return dbServerName;
      }
  
      public static int portNumber(final Environment environment)
      {
          String portNumber = environment.getProperty("spring.datasource.portNumber");
          try
          {
              return Integer.parseInt(portNumber);
          }
          catch(Exception e)
          {
              return 3306;
          }
      }
  
      public static String defaultSchema(final Environment environment)
      {
          String defaultSchema = environment.getProperty("spring.datasource.defaultSchema");
          if (defaultSchema == null || "".equalsIgnoreCase(defaultSchema.trim()))
          {
              return "subscription";
          }
          return defaultSchema;
      }
  }
  }
  </code></pre>
  
  <p><strong>JMS Configuration</strong></p>
  
  <pre><code>@EnableJms
  @Configuration
  public class JmsConfiguration
  {
      @Bean
      public JmsListenerContainerFactory&lt;?&gt; myFactory(ConnectionFactory     connectionFactory,
                                                      DefaultJmsListenerContainerFactoryConfigurer configurer)
  {
      DefaultJmsListenerContainerFactory factory = new     DefaultJmsListenerContainerFactory();
      configurer.configure(factory, connectionFactory);
      return factory;
  }
  }
  </code></pre>
  
  <p>Startup class</p>
  
  <pre><code>@Import({JpaConfiguration.class, JmsConfiguration.class})
  @SpringBootApplication(scanBasePackages={"edu.learn"})
  public class SubscriptionApiApplication
  {
      public static void main(String[] args)
      {
          SpringApplication.run(SubscriptionApiApplication.class, args);
      }
  }
  </code></pre>
  
  <p>JMS queue listener</p>
  
  <pre><code>@Component
  public class OrderTransactionReceiver
  {
      private static final Logger             LOGGER =     LoggerFactory.getLogger(OrderTransactionReceiver.class);
  
      @Autowired
      private SubscriptionService             subsriptionService;
  
      @JmsListener(destination = "OrderTransactionQueue", containerFactory = "myFactory")
  public void receiveMessage(String businessID)
  {
      List&lt;SubscriptionDTO&gt; subscriptions = subsriptionService.findByBusinessID(businessID);
      for (SubscriptionDTO subscription : subscriptions)
      {
          subscription.setStatus("active");
          subsriptionService.update(subscription);
      }
  }
  }
  </code></pre>
  
  <p><strong>Service</strong></p>
  
  <pre><code>@Service
  class RepositorySubscriptionService implements SubscriptionService
  {
  private static final Logger LOGGER = LoggerFactory.getLogger(RepositorySubscriptionService.class);
  
  private final SubscriptionRepository          repository;
  
  @Transactional
  @Override
  public SubscriptionDTO update(SubscriptionDTO updatedSubscriptionEntry)
  {
      LOGGER.info(
              "Updating the information of a subscription entry by using information: {}", updatedSubscriptionEntry
      );
  
      SubscriptionEntity updated = findSubscriptionEntryById(updatedSubscriptionEntry.getId());
  
      updated.update(updatedSubscriptionEntry.getStatus());
  
      // We need to flush the changes or otherwise the returned object
      // doesn't contain the updated audit information.
      repository.flush();
  
      LOGGER.info("Updated the information of the subscription entry: {}", updated);
  
      return SubscriptionMapper.mapEntityIntoDTO(updated);
  }
  }
  </code></pre>
  
  <p><strong>Repostiory</strong></p>
  
  <pre><code>public interface SubscriptionRepository extends 
      Repository&lt;SubscriptionEntity, String&gt;, 
      JpaSpecificationExecutor&lt;SubscriptionEntity&gt;
  {
  void delete(SubscriptionEntity deleted);
  
  List&lt;SubscriptionEntity&gt; findAll();
  
  Optional&lt;SubscriptionEntity&gt; findOne(String id);
  
  List&lt;SubscriptionEntity&gt; findByBusinessID(final String businessID);
  
  void flush();
  
  SubscriptionEntity save(SubscriptionEntity persisted);
  }
  </code></pre>
  
  <p><strong>JTA transaction configuration</strong></p>
  
  <pre><code>@Configuration
  @EnableJpaRepositories(basePackages = "edu.learn.repositories", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
  @EnableTransactionManagement
  public class JpaConfiguration
  {
  private final String DEFAULT_TEST_QUERY = "SELECT 1";
  
  @Autowired
  private Environment environment;
  
  @Value("${datasource.maxPoolSize:10}")
  private int maxPoolSize;
  
  /*
   * Populate SpringBoot DataSourceProperties object directly from
   * application.yml based on prefix.Thanks to .yml, Hierachical data is
   * mapped out of the box with matching-name properties of
   * DataSourceProperties object].
   */
  @Bean
  @Primary
  @ConfigurationProperties(prefix = "datasource")
  public DataSourceProperties dataSourceProperties()
  {
      return new DataSourceProperties();
  }
  
  /*
   * Configure HikariCP pooled DataSource.
   */
  @Bean(initMethod = "init", destroyMethod = "close")
  public DataSource dataSource()
  {
      DataSourceProperties dataSourceProperties = dataSourceProperties();
  
      MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
      mysqlXaDataSource.setServerName(PropertyUtil.dbServerName(environment));
      mysqlXaDataSource.setPort(PropertyUtil.portNumber(environment));
      mysqlXaDataSource.setUser(dataSourceProperties.getUsername());
      mysqlXaDataSource.setPassword(dataSourceProperties.getPassword());
      mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
      mysqlXaDataSource.setDatabaseName(PropertyUtil.defaultSchema(environment));
      mysqlXaDataSource.setCachePreparedStatements(PropertyUtil.getCachePrepStmts(environment));
      try
      {
          mysqlXaDataSource.setPrepStmtCacheSqlLimit(PropertyUtil.getPrepStmtCacheSqlLimit(environment));
          mysqlXaDataSource.setPrepStmtCacheSize(PropertyUtil.getPrepStmtCacheSize(environment));
      }
      catch (SQLException e)
      {
          e.printStackTrace();
      }
  
      AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
      xaDataSource.setXaDataSource(mysqlXaDataSource);
      xaDataSource.setUniqueResourceName("xaSubscription");
      xaDataSource.setTestQuery(DEFAULT_TEST_QUERY);
      xaDataSource.setMaxPoolSize(PropertyUtil.getMaxPoolSize(environment));
      xaDataSource.setMaxIdleTime(PropertyUtil.getMinIdle(environment));
      xaDataSource.setMaxLifetime((int)PropertyUtil.getMaxLifetime(environment));
      xaDataSource.setBorrowConnectionTimeout((int)PropertyUtil.getConnectionTimeout(environment));
  
      return xaDataSource;
  }
  
  /*
   * Entity Manager Factory setup.
   */
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException
  {
      LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
      factoryBean.setDataSource(dataSource());
      factoryBean.setPackagesToScan(new String[]
      {
              "edu.learn.model"
      });
      factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
      factoryBean.setJpaProperties(jpaProperties());
      return factoryBean;
  }
  
  /*
   * Provider specific adapter.
   */
  @Bean
  public JpaVendorAdapter jpaVendorAdapter()
  {
      HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
      return hibernateJpaVendorAdapter;
  }
  
  /*
   * Here you can specify any provider specific properties.
   */
  private Properties jpaProperties()
  {
      Properties properties = new Properties();
      properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
      properties.put("hibernate.globally_quoted_identifiers", "true");
      properties.put("hibernate.hbm2ddl.auto", "validates");
      properties.put("ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
      properties.put("show_sql", "false");
      properties.put("format_sql", "true");
      properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
      properties.put("javax.persistence.transactionType", "JTA");
  
      return properties;
  }
  
  
  @Bean
  public UserTransaction userTransaction() throws Throwable
  {
      UserTransactionImp userTransactionImp = new UserTransactionImp();
      userTransactionImp.setTransactionTimeout(1000);
      return userTransactionImp;
  }
  
  @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
  public TransactionManager atomikosTransactionManager() throws Throwable
  {
      UserTransactionManager userTransactionManager = new UserTransactionManager();
      userTransactionManager.setForceShutdown(false);
  
      AtomikosJtaPlatform.transactionManager = userTransactionManager;
  
      return userTransactionManager;
  }
  
  @Bean(name = "transactionManager")
  @DependsOn({ "userTransaction", "atomikosTransactionManager" })
  public PlatformTransactionManager transactionManager() throws Throwable
  {
      UserTransaction userTransaction = userTransaction();
  
      AtomikosJtaPlatform.transaction = userTransaction;
  
      TransactionManager atomikosTransactionManager = atomikosTransactionManager();
      return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
  }
  }
  
  public class AtomikosJtaPlatform extends AbstractJtaPlatform
  {
  
  private static final long serialVersionUID = 1L;
  
  static TransactionManager transactionManager;
  static UserTransaction    transaction;
  
  @Override
  protected TransactionManager locateTransactionManager()
  {
      return transactionManager;
  }
  
  @Override
  protected UserTransaction locateUserTransaction()
  {
      return transaction;
  }
  }
  </code></pre>