With spring boot, how does it detect a JTA environment? - spring-boot

I'm trying to enable JTA with spring boot so that JPA and JMS will roll back together. All docs point to http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html and it states
When a JTA environment is detected, Spring’s JtaTransactionManager
will be used to manage transactions.
What is meant by "JTA environment is detected"?
I ask because I think that is what is tripping me up. I added dependencies for Atomikos, but jmsTemplate.isSessionTransacted() returns false. I am assuming I haven't properly marked my environment as JTA. I'm running with embedded tomcat.
What I am experiencing is the database changes are being rolledback with the transaction, but not the JMS messages.
UPDATE:
The part about sessionTransacted was not related. It was my misunderstanding.

A JTA environment is detected when a supported transaction manager is on the classpath (Atomikos or Bitronix in 1.3, and also Narayana in 1.4) or because a javax.transaction.TransactionManager is available in JNDI (typically because you've deployed your Boot app to a Java EE container).
I think you have misunderstood the purpose of the sessionTransacted flag on JmsTemplate. It's used when creating a new session (Connection.createSession), however the transacted value that's passed to createSession is ignored when you're running in a JTA environment.

You can see it in the class org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration:
#ConditionalOnClass(javax.transaction.Transaction.class)
#ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
#AutoConfigureBefore({ XADataSourceAutoConfiguration.class,
ActiveMQAutoConfiguration.class, HornetQAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
#Import({ JndiJtaConfiguration.class, BitronixJtaConfiguration.class,
AtomikosJtaConfiguration.class, NarayanaJtaConfiguration.class })
#EnableConfigurationProperties(JtaProperties.class)
public class JtaAutoConfiguration {
}
Basically you have to have the JTA API on the classpath, and at least one JTA provider (Bitronix or Atomikos, if you're not using an application server).

Related

Enabling compile-time AspecJ for Spring Method Security

Spring AOP runs everything through proxies which sadly can't be everywhere. For this reason Spring Security's annotations #PreAuthorize, #PostAuthorize, #PreFilter and #PostFilter (also #Secured) will not be taken into consideration when calls are not going through said proxies. Proxies are created only for singletons (#Beans) so We are greatly limited when We want to secure methods on specific objects (such as JPA #Entities) that are not beans. Proxies also won't be called within calling objects (bean calling its methods in context of self - this).
I know that Spring has suppot not only for Spring AOP but also real AOP - AspectJ. Not only that, but it SHOULD support AspectJ out of box. Testament to this is:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
When enabled, Spring will require (crash on startup otherwise) aspectj dependency, which is provided within:
'org.springframework.security:spring-security-aspects'
After adding this dependency we will have AspectJ libraries in classpath and will get:
org.springframework.security.access.intercept.aspectj.aspect
with:
public aspect AnnotationSecurityAspect implements InitializingBean
But here it all ends. There is no documentation that I could find that would state how to further enable aspectj weaving. Setting #EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ) certainly DOES something as we lose standard Spring AOP - security annotations stop working anywhere (on Beans) and at the same time they are not weaved with AspectJ.
Does anyone have some knowledge on Spring's support for this out of box (compile-time weaving) and what further configuration is needed? Maybe I need to weave it myself? Do I need some specific libraries for building?
Version: Spring 5.2.1.RELEASE (all packages).
#DimaSan comment helped me find few threads/issues I missed while doing my search and while many of them are too years-outdated I managed to setup my app.
Turns out I was actually very close and by making few updates and changing dependencies/plugins on gradle I have a working environment.
Gradle: 5.6.4
with:
plugins {
id "io.freefair.aspectj.post-compile-weaving" version "4.1.6"
}
dependencies {
aspect 'org.springframework.security:spring-security-aspects'
runtime 'org.springframework.security:spring-security-aspects'
}
Spring setup at 5.2.1.RELEASE with
spring-boot-starter-
web
data-jpa
security
With above setup this is actually only thing needed:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
Finally if You are not using Gradle (e.g. want to use STS/Eclipse Run Configuration), you will add:
-javaagent:C:\Users\USER\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.4\<cache-string>\aspectjweaver-1.9.4.jar
.gradle and 1.9.4 being case for my current setup/version.
Note that this is yet untested (but working with JPA/Hibernate) with e.g. Transaction management and I will comment on it once I start using complex transactions where weaving would create issues.

Spring Batch combined with Atomikos not working

I’m having trouble configuring an Tomcat – Spring Batch – Atomikos combination.
I have configured the following (I’m not mentioning the JMS configuration)
Atomikos DataSource (proxy) based on
com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory for Oracle XA datasource.
JtaTransactionManager based on
transactionManager based on com.atomikos.icatch.jta.J2eeTransactionManager
userTransaction based on
com.atomikos.icatch.jta.J2eeUserTransaction
When executing a batch job I receive the following error:
Caused by: java.lang.RuntimeException: Transaction Service Not Running?
at com.atomikos.icatch.jta.J2eeUserTransaction.checkSetup(J2eeUserTransaction.java:70)
at com.atomikos.icatch.jta.J2eeUserTransaction.getStatus(J2eeUserTransaction.java:125)
at org.springframework.transaction.jta.JtaTransactionManager.
isExistingTransaction(JtaTransactionManager.java:797)
Debugging revealed the following:
Spring Batch makes use of TaskletStep. This class uses a PlatformTransactionManager that is instantiated with a DataSourceTransactionManager? The datasource is referring to a AtomikosDataSourceBean, that seems ok.
I have several questions:
Where is this DataSourceTransactionManager coming from? I have defined a JtaTransactionManager!
I thought the AtomikosDataSourceBean acts like a proxy to connect to JtaTransactionManager. Why is Atomikos given the error “Transaction Service Not Running?”
Spring Batch: 2.1.8
Atomikos: 3.9.3

MySQL and Infinispan - JTA implementation

We have an web application under Tomcat, integrated with Hibernate 4X, Spring 4X and HibernateTransactionManager as our transaction manager (currently one MySQL resource).
As part of our configuration distribution, we should integrate with Infinispan as our cache manager to store configuration with other format than in the MySQL. Meaning, not as Hibernate second level cache integration!
I managed to integrate Infinispan with Spring but now I'm facing a big problem due to the fact the MySql transaction and Infinispan must be on the same #Transactional.
I read about Spring JTA and how to integrate with Atomikos (e.g.) as our Global Transaction manager but I'm not sure if we can combine the whole entities to work together and how :(
I need to know if there's an option to work with Atomikos Spring JTA so the Infinispan will recognize this JTA implementation and will handle the MySql and Infinispan as one global transaction! (2PC)
Thanks!
At first I would suggest to configure Spring + Hibernate + JTA together. Here is a very nice tutorial. If you configured everything correctly - you should have one bean of a type TransactionManager. In above tutorial it is configured inside this block:
#Bean(initMethod = "init", destroyMethod = "close")
public TransactionManager transactionManager() throws Throwable {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
return userTransactionManager;
}
Now you may configure Infinispan to use this transaction manager. The easiest way to achieve this, is to implement your own TransactionManagerLookup. This should return the transaction manager, which was created above.
Finally you have to create transactional cache, like this:
<local-cache name="transactional">
<transaction mode="FULL_XA"/>
</local-cache>
After that everything should work with the same Transaction Manager and Spring should handle everything within single #Transactional annotation.

Multiple DataSource beans with Spring Boot Actuator's EndpointAutoConfiguration possible?

I have a spring-boot application that uses several DataSource beans and would still like to use the EndpointAutoConfiguration from spring-boot-actuator that is loaded as part of using the #EnableAutoConfiguration annotation. This doesn't seem possible as there is a DataSource bean injected into EndpointAutoConfiguration to setup the HealthEndpoint bean. Due to the multiple instances of DataSource that exist in my application, a NoUniqueBeanDefinitionException is thrown upon application startup unless I exclude EndpointAutoConfiguration but then I must setup all the other endpoints manually (/env, /metrics, etc).
Is there a better way to do this?
You could mark one of your DataSources as #Primary or you could provide your own HealthIndicator (it's not the endpoint that wants your DataSource but that bean, which is designed to be overridden by just adding one of your own).

Transaction in Spring with datasources create in runtime

I have a problem with transaction in spring, because in my project datasources are created in runtime from side files and according to documentation:
I should inject to TransactionManager dataSource and made it visible for annotation #Transactional using <tx:annotation-driven transaction-manager="txManager"/>.
So my question is how can I do it when I want to use annotation?
First of all how are you creating the datasources at runtime.
if directly as Datasource=new datasource... I will suges use BeanDefinitionBuilder in Spring 3.2 to Create the Datasourcebean and then register it via BeanDefinitionRegistry.
and then get the bean from Spring context and it will be considered using the transaction.

Resources