Spring TransactionInterceptor with multiple TransactionManager - java

In a webapplication I am using different components which are all using Spring 3.0.x having their own DataSource and TransactionManager (all with different names). They are all included in the context via the "main" webapp via including their spring config.
<import resource="classpath:spring-config-componentName.xml" />
In each of the Spring configs of the components I am using declarative transaction management, enabled via
<tx:annotation-driven transaction-manager="transactionManager_componentName" />
And for each method that should be transactional I add a annotation that looks like this:
#Transactional(propagation=Propagation.REQUIRES_NEW, value="transactionManager_componentName")
The problem I have is that I found out that only one TransactionInterceptor is created which has a reference to one of the transactionManagers but not of the one of the component itself. Is there a way to handle this? Like to specify a TransactionInterceptor as a bean and then reference it in the #Transactional annotation?
I think there is a possibility by specifying a TransactionProxyFactoryBean in each component and doing the declarative transaciton management via the xml config. But this is something I would like to avoid.
The proposed way as described in the Spring docs (10.5.6.2 Multiple Transaction Managers with #Transactional) does not work.

Finally I found out what the problem was and I have to say that it works as it is described in the spring docs.
If you are using more than one TransactionManagerin your Spring Container and you are using #Transactionit does not work if you are specifiying the TransactionManager like this:
<tx:annotation-driven transaction-manager="transactionManager_componentName" />
All you have to do ist to remove the specification of the TransactionManager and use a configuration like this:
<!-- ========== ENABLE ANNOTATIONS ========== -->
<tx:annotation-driven/>
<!-- ========== TRANSACTION MANAGER ========== -->
<bean id="transactionManager_component1"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource_component1" />
<property name="nestedTransactionAllowed" value="true" />
<qualifier value="component1"/>
</bean>
And for you methods you want to run in a transaction then just specify it like this:
#Transactional(value="component1")

Related

How to register Spring Cloud config server before any XML bean is declared?

I am trying to migrate a spring app who uses PropertyPlaceholderConfigurer to resolve all the XML placeholders in it's bean declarations to a spring cloud usage, I can check that the config server is contacted and responds with the respective data generated from a git repository, however, at server startup during the BeanFactoryPostProcessor registration the XML context fails to resolve the placeholders.
I assumed that by removing the bean definition:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="properties">
<bean class="org.apache.commons.configuration.ConfigurationConverter"
factory-method="getProperties">
<constructor-arg>
<ref bean="domainConfiguration" />
</constructor-arg>
</bean>
</property>
</bean>
And adding the POM dependency for config client and respective enviroment variables the placeholders should work but they dont.
Can I manually set the config server in a higher priority?
Or as an alternative, teach PropertyPlaceholderConfigurer to consume a config server?
If you are using spring-cloud-config, this should work out of the box. When spring will build/start the ApplicationContext, first it will create a bootstrap (parent) context which will happen before creating the main context. Getting the properties of the config server should happen in the bootstrap phase so that your beans which are created in the normal context should be able to get those properties.
Check out the Client Side Usage part of the documentation for an example and check out the usage of the bootstrap.properties file.
If you don't have spring-boot (it should work w/o it as well but the docs are spring-boot centric), check out this repo or this GitHub issue, you will need a ConfigServicePropertySourceLocator.

how to inject Environment on application context

I'm currently working with legacy code and I wanna read some properties from the Environment. I know this would be easily done using spring boot with:
#Autowired
Environment environment;
But, since I'm wiring all the components using an application-context.xml file, I don't know how to wire the Environment there,
<bean name="myBean" class="com.acme.MyClass">
???
</bean>
Thanks for your help #volveira89 #rmlan
Using the xml file, this is working:
<bean name="myBean" class="com.acme.MyClass">
<constructor-arg ref="environment"/>
</bean>
It seems that you have no experience in Spring XML config. You should look at this example by Spring team: https://spring.io/blog/2011/01/04/green-beans-getting-started-with-spring-mvc/
You need something like this in your application-context.xml:
<!-- Scans within the base package of the application for #Components
to configure as beans -->
<!-- #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="xyz.sample.baremvc" />
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
Now your,
#Autowired
Environment environment
should work!

Can I have multiple bean interconnection versions with Spring?

Spring configuration file creates beans and interconnects them. Is this correct? I have a chain of beans in my application but want to test it with smaller chains. Can I have multiple chains defined with Spring? Or only one bean structure is allowed?
EXAMPLE
Suppose this is production config:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="processor1" class="tests.Processor1">
<property name="input" ref="provider"/>
</bean>
<bean id="processor2" class="tests.Processor2">
<property name="input" ref="processor1"/>
</bean>
<bean id="consumer" class="tests.Consumer">
<property name="input" ref="processor2"/>
</bean>
And I want to test in the following configs:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="analyzer" class="tests.Analyzer">
<property name="input" ref="provider"/>
</bean>
And:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="processor1" class="tests.Processor1">
<property name="input" ref="provider"/>
</bean>
<bean id="analyzer" class="tests.Analyzer">
<property name="input" ref="processor1"/>
</bean>
And so on, attaching beans one by one.
Yes, you can.
You can break overall configuration of Spring application context for your application into parts (XML files if you use XML configuration, packages with #Components if you use classpath scanning, #Configurations if you use Java-based configuration) and construct an application context using a subset of these parts.
So, if your application has two features foo and bar, you can declare beans used by these features in foo.xml and bar.xml respectively (if you use XML configuration), and import them from the main configuration of your application (such as applicationContext.xml).
Now, if you want to write integration test for bar you can create application context from bar.xml only (#ContextConfiguration("bar.xml")). Obviously, you should take care of interdependencies between different parts of your configuration. For example, if both foo.xml and bar.xml depend on beans declared in db.xml, you may want to create something like test-db.xml and configure your integration test for bar as #ContextConfiguration({"bar.xml", "test-db.xml"}).
Note that this approach requres some discipline, especially if you use classpath scanning - in this case parts of your configuration are defined by packages, therefore you need to follow "package by feature, not by layer" rule.
See also:
9.3 Integration testing
I believe you want to test for integration, what I usually do is to separate my bean configuration files in tiers and then import them as needed for testing. Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<context:property-placeholder
location="classpath:mx/gob/jgtjo/apps/schedule/web/schedule-web.properties"
file-encoding="UTF-8" system-properties-mode="NEVER" />
<!-- Context files -->
<import resource="spring/dataContext.xml" />
<import resource="spring/serviceContext.xml" />
<import resource="spring/securityContext.xml" />
<import resource="spring/components.xml" />
</beans>
And then, if I need to test for Daos, I only import the dataContext.xml inside a testContextDao.
In simple terms spring framework takes care of Object Creation. These objects you want Spring to manage you define them as beans. So when spring creates a bean1 if that bean1 has reference to bean2, the bean2 is instantiated and injected to bean1 and finally bean1 is created. Thinking of it as chain will be over complicating.
Section 3.2 of spring docs

Use of Ajax with SimpleFormCotroller in Spring MVC

I'm developing an application in JSP using SimpleFormController with Spring MVC 3.0.2 using Hibernate. Everything is fine. I'm also using Validator to validate forms on the server side. It's also going on well.
Now, I need to use Ajax as an example, when a country is selected from a drop down (<form:select><form:option></form:option></form:select>), the states corresponding to that country should be populated from the database in the state drop down.
I have done such things using Ajax in places but yet not with Spring MVC. I have gone through many tutorials/articles about SimpleFormController on Google but none of them were using Ajax. I couldn't find a single idea about how to use Ajax with SimpleFormController.
With annotated controllers (#Controller), the thing can be made easy because methods can be mapped using the #RequestMapping annotation (nevertheless I haven't yet used it but I think I can).
But with SimpleFormController, I don't have any precise idea about how to handle Ajax requests in the Spring controller (which methods to be mapped and how). With SimpleFormController, I'm usually associated with the onSubmit(), showForm() and referenceData() methods.
Could you please expose some thoughts on how can an Ajax request be made on SimpleFormController, which methods can be mapped and how? (I don't want the full code anymore. A very simple example (if and only if it's possible) or furthermore specific links where the use of Ajax with the SimpleFormController is explained would be quite enough for me to study).
You could always just have a separate #Controller to handle the ajax requests. If you can have custom jsp on the view, there is nothing stopping you from handling an ajax request on the page. Just bind the onchange event of the select box to an ajax call pointing to the other Controller you made.
In terms of keeping it bound to just that SimpleFormController, I don't think this is possible, but if you create a new RESTful controller that the form would use, other parts of the website will be able to use this new controller as well.
In complement to dardo's answer, using both spring MVC 2 and MVC 3 controllers is possible, but a bit tricky to set up.
In order to use both SimpleFormController and #Controller controllers in the same Spring context, I used to following definition :
<!-- ======== MVC Spring 3.x ======== -->
<!-- Scans within the base package of the application for #Components to configure as beans #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="com.your.package" />
<!-- Enables the Spring MVC #Controller programming model -->
<!-- It's a shortcut equivalent to the (more complete) bean definition below (see bean AnnotationMethodHandlerAdapter).-->
<!--<mvc:annotation-driven />-->
<!-- This HandlerAdapter will register spring 3.x controllers (#Controller) into the DispatcherServlet -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<array>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="writeAcceptCharset" value="false"/>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</array>
</property>
</bean>
<!-- This HandlerMapping allows to map urls defined in #RequestMapping annotations to the corresponding controllers -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
<!-- ======== MVC Spring 2.x ======== -->
<!-- This HandlerAdapter will register spring 2.x controllers (#Controller) into the DispatcherServlet -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- Url mapper -->
<bean id="urlMapper" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/foo.do" value-ref="fooController" />
<entry key="/bar.do" value-ref="barController" />
...
</map>
</property>
</bean>

Spring transactions & hibernate: lazy initialization

From what I've read so far I had the understanding that using transactions would be the solution to hibernate's lazy loading problems. The session would be available during the whole transaction in the service layer without further adue.
So maybe I misconfigured my transaction management? I'm actually a newb when it comes to spring and hibernate, but maybe you guys could help me out.
My configuration:
<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
id="sessionFactory">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- Hibernate Template bean that will be assigned to DAOs. -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--
Transaction manager for a single Hibernate SessionFactory (alternative
to JTA)
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
My DAO implementation would simply have a #Repository annotation and a Hibernate-template bean injected using autowiring.
A typical header of a service Implementation would be:
#Service
#Transactional(readOnly=true)
public class LeerlingServiceImpl implements LeerlingService {
#Autowired
LeerlingDAO leerlingDAO;
#Autowired
LeerplanDAO leerplanDAO;
With a #Service(readOnly=false) annotation if anything is actually saved/updated in that particular method.
Do I need to configure something else to make sure that I can load the right associations in my Service, or is this normally handled by transactions?
Right now I am just a bit confused of what I should actually do, so please help me:)
Lazy-loading problems and transactions are not really related one to other. But that's another story :)
You've done all well, apart from the access to session in your beans. No sure how you are going to do this. The standard solution (in spring 2.x, not sure about 3.x, haven't looked yet) is to use HibernateDaoSupport as base class for classes were you are going to have an access to session. But personally that looks a little dodgy to me, because adds dependency on Spring-specific classes. Better way is to inject session into your beans. To do this you need to declare your session bean with definition similar to that one:
<bean name="hibernateSession" class="org.springframework.orm.hibernate3.SessionFactoryUtils" factory-method="getSession"
scope="prototype">
<constructor-arg index="0" ref="hibernateSessionFactory"/>
<constructor-arg index="1" value="false"/>
<aop:scoped-proxy/>
</bean>
and then just use it.
Here are details:
http://stas-blogspot.blogspot.com/2009/10/hibernate-spring-in-standalone.html
I think my understanding of Spring was just bad till now; there was indeed no real management for our session management. Basically what now happened was: you could get data from the DAO, but right after you received it you couldn't even get lazy collections loaded because the session was closed.
Now we are using the hibernate interceptor, which attaches the session to the thread at the beginning of each request and closes it when it ends. This is not always the most ideal solution, but for a school project I wouldn't bother too much.
The other solution seems to be: add AOP in a way that #around is used that the session is only available during a service method call. I think this is the best solution, though, I'm not going to dig that deeply right now for this project. The good thing is that I know it exists.
This article also helped me a lot: http://www.jroller.com/kbaum/entry/orm_lazy_initialization_with_dao
To those interested: here is what I had to add: In Spring MVC 3.0 there is a new feature called mvc:intereceptors which made me type less xml.
<!-- WEB-INF/applicationContext.xml or your own XML config file -->
<mvc:interceptors>
<bean
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
</mvc:interceptors>

Categories