Is DefaultAutoProxyCreator needed if tx:annotation-driven is already enabled ?
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true" />
</bean>
<tx:annotation-driven proxy-target-class="true"/>
It seems when there are both of them enabled, then proxy of proxies start getting created and starts failing.
Having only tx-annotation enabled, I have disabled spring-aspect and cglib also in maven dependencies. Do I need to have cglib even in Spring 4 for class based proxies like above ?
Spring version : 4.0.6
As far as I understand, you don't really need the explicit DefaultAdvisorAutoProxyCreator unless you have specific Advisors that you are using for cross cutting purpose - if so I feel that an #AspectJ approach may be cleaner.
Also, disabling cglib explicitly does not have any effect, Spring comes packaged with its own copy of CGLIB.
Related
I am working on a new project and using Spring-Boot for the first time.
Traditionally, when using Spring and property files for configuration, I provided default properties in the distribution (WAR) and allowed for overriding them in some documented place.
For example:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:app.properties</value>
<value>file:${user.home}/.company/app/app.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="ignoreResourceNotFound" value="true" />
</bean>
This would allow us to re-deploy the application without losing local system configurations.
After reading the documentation on this for Spring-Boot, it seems that anything in "application.properties" takes a higher priority, and overwrites, anything specified with the #PropertySource annotation.
I like Spring because it allows us to stick to convention, which concerns me that I may have been doing the properties cascading wrong.
What would be the most appropriate way to provide externalized properties, with sensible defaults (embedded database, simple authentication, etc) that are included in the distribution?
Also, if anyone knows, I would love to know the reasoning behind the order for properties in Spring-Boot.
Note
I've tried looking at SpringApplication.setDefaultProperties, but cannot seem to find where to get a reference to the SpringApplication Object. The main method calls a static method on it (run), which is never actually run when bundled as a WAR file. It also seems a little bit of a hack to do it this way.
SpringApplication is a public class so you can create an instance and set its properties before running your app (the static run() methods are just conveniences). You can also use SpringApplicationBuilder, which is what you get as a callback when you are running in an external container anyway. Using those APIs you can set default properties, and profiles, including the location (spring.config.location) and name (spring.config.name) of the application.properties file.
Note that (per the link you provided) you can also use JNDI variables in the container to override or set environment properties. That could also be useful if you are packing multiple apps into the same JVM.
I'm writing an app that may talk to multiple database and web services. I'd like to use Spring's #Transactional annotation so that a failure in any one can rollback them all.
I'm not clear about how I should do this, and I can't find any examples of it either after searching.
One thought I have is to create a bean that is a custom aspect and use that to intercept the methods, adding my own custom code to rollback problems. But I'm sure there must be a way to do this in a standardised fashion.
Thank you!
Alex
The most straightforward way to implement distributed transactions is JTA, but I don't think it's feasible in your case, because you also need to cover web services.
However, you can implement a "best effort" solution manually by registering TransactionSynchronizations for your transactional resources. This way you can integrate them with #Transactional.
See TransactionSynchronizationManager.
you should have something like below declared in your spring config xml for each of the datasource to be able to use #Transactional in your application:
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
In Spring, beans can be configured to be lazily initialized. Spring Batch jobs are also (Spring-managed) beans. That is, when I configure something like
<sb:job id="dummyJob" job-repository="jobRepository">
<sb:step id="dummyStep">
<sb:tasklet ref="dummyTasklet" />
</sb:step>
</sb:job>
I actually configure a new (Job-typed) bean inside the Spring container.
My issue is I really want my Job beans to be lazily initialized. As they are regular Spring-managed beans, I'd expect I can instruct the Spring context to make them lazy. This is because I have a large number of beans and there are many cases in which, during one execution of my Spring-based application, I only run one job.
But there's no lazy-init property I can set on my <sb:job... \> configuration. Is there any way I can force lazy initialization? If I configure my <beans\> root with default-lazy-init="true", will this also apply to the Job beans?
You have two options here:
Configure your job manually. This would allow you to use the regular lazy-init attributes Spring exposes.
Use the JobScope now available in Spring Batch 3. Spring Batch 3 will be available soon, but the JobScope was available in the last milestone.
Just to elaborate on Michael Minella's answer.
I had a similar requirement to lazy initialize the job repository.
I am working with Spring Batch 2.1.9.
The following is working for me.
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
lazy-init="true">
<property name="dataSource" ref="jobDataSource"/>
<property name="transactionManager" ref="jobTransactionManager"/>
</bean>
Note one pitfall I had run into: do not set the databaseType i.e. avoid the following:
<property name="databaseType" value="SQLSERVER"/>
This is bad because it disable the auto-discovery of the database type and breaked my JUnits that works on H2.
I am trying to use JtaTransactionManager in spring/hibernate. I have below configuration.
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName" value="java:comp/UserTransaction"></property>
</bean>
Now can i mark my service methods with #Transactional ? or do i need any extra configuration to use #Transactional ? do i need to add ?
An annotation is nothing more then metadata, so only slapping an annotation on there and expect it to magically work isn't going to happen.
To make #Transactional work you need to tell spring that you want to use annotation to drive your transactions. For this add the <tx:annotation-driven /> tag to your configuration.
However that probably isn't going to be all there is needed as you also need to configure hibernate appropriately for JTA.
A small tip instead of defining the bean, use the shorter <tx:jta-transaction-manager />. This will do some detection on which app server you are running and configure the appropriate transaction manager for you. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-application-server-integration for more information.
I have a web application using JPA and JTA with Spring. I would like to support both JBoss and Tomcat. When running on JBoss, I'd like to use JBoss' own TransactionManager, and when running on Tomcat, I'd like to use JOTM.
I have both scenarios working, but I now find that I seem to need two separate Spring configurations for the two cases. With JOTM, I need to use Spring's JotmFactoryBean:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
In JBoss, though, I just need to fetch "TransactionManager" from JNDI:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="resourceRef" value="true" />
<property name="jndiName" value="TransactionManager" />
<property name="expectedType"
value="javax.transaction.TransactionManager" />
</bean>
</property>
</bean>
Is there a way to configure this so that the appropriate TransactionManager - JBoss or JOTM - is used, without the need for two different configuration files?
I think you have missed the point of JNDI. JNDI was pretty much written to solve the problem you have!
I think you can take it up a level, so instead of using the "userTransaction" or "transactionManager from JNDI" depending on your situation. Why not add the "JtaTransactionManager" to JNDI. That way you push the configuration to the JNDI where it is supposed to be instead of creating even more configuration files [ like there aren't enough already ;) ].
You can use PropertyConfigurerPlaceholder to inject bean references as well as simple values.
For example if you call your beans 'jotm' and 'jboss' then you could inject your TM like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">
<property name="location" value="classpath:/path/to/application.properties"/>
</bean>
<bean id="jotm">...</bean>
<bean id="jboss">...</bean>
<bean id="bean-requiring-transaction-manager">
<property name="transactionManager" ref="${transaction.strategy}"/>
</bean>
Then you can swap transaction managers using
transaction.strategy=jotm in a properties file
-Dtransaction.strategy=jotm as a system property
This is one possible approach. See my blog for a more complete example.
Hope this helps.
If you are using Spring 2.5 you can use <tx:jta-transaction-manager/>. I have not used it with JBoss but it should work for you according to section 9.8 Application server-specific integration from the Spring reference manual.
The <tx:jta-transaction-manager/> approach will look for a transaction manager in several default locations listed here. If your JBoss transaction manager is not in one of those locations, I suggest you move it, if possible, or move it in Tomcat so that both containers have their TM in the same JNDI location.
Just adding my experience here so I don't have to re-suffer the experience again.
As bmatthews68, Chochos and these posters have said, use <tx:jta-transaction-manager/> in your Spring bean file; it definitely provides the appropriate level of abstraction and there's no need to do anything extra on the Spring side.
As for Tomcat, I declared <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> in the default/shared conf/context.xml file, which binds to java:comp/UserTransaction. As this is one of the places searched for by Spring, you shouldn't need to do anything else.
One gotcha though: if like me you use Maven, make sure you exclude any dependencies on the javax.transaction:jta jar or set the scope to provided. Otherwise you will experience classloader issues.