If I have the following configuration in a Spring project, and different parts of the app get different instances of ServiceA, will I still have a concurrency problem because all instances of ServiceA will be sharing a single instance of dataSource? Do I need to simply know if BasicDataSource is threadsafe? If it is, then I am ok, if it is not, then I will have threading issues?
<bean id="serviceA" name="serviceA" class="com.company.ServiceA" scope="prototype">
<constructor-arg name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" destroy-method="close" name="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${dbConnectionUrl}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
<property name="initialSize" value="${connectionSize}" />
<property name="maxActive" value="${maxConnectionSize}" />
<property name="validationQuery" value="SELECT 1" />
<property name="testOnBorrow" value="true" />
</bean>
You won't have any issues unless you are using some very strange datasource. All your beans in Spring should be stateless except for session beans. Out of the box beans from Spring will be like this. If you do this in your code as well you won't have any problems. All your singleton beans could have been essentially static but this would make them less or not testable, as you would have a tough time mocking them. The other issue besides concurrency with having state in your beans which are not session beans is if you try to scale up your application and deploy multiple instances of the same webapp, it will most likely fall over. Typically you don't have your beans use the datasource, (although you may have reasons too). You usually work with a session factory and just get current session from your session factory which has a reference to the datasource. Or using an entity manager which is similar.
Edit To addresss the comments. A stateless bean (no variables) is inherently thread safe. So unless your bean has variables as many threads as you want can access it at the same time. Even if a bean is accessing a database this is the case, it will still be thread safe because the database handles all the concurrency data problems for you. I'm not too sure what you mean by context switching? Two requests may run through the same bean but they will have different sessions from the session factory, there will be no shared state so there will be no concurrency issues.
With the session factory you'll just have to read up on that. Typically you would use something like hibernate for mapping classes to a database, and your session is like your link to the database. This handles all sorts of aspects for working with a database for you. The vast majority of Spring apps are like this. If you google Spring MVC hibernate you will see what I mean.
I believe there is a big debate about whether or not a REST service still can have sessions but I can't really comment on that, although I know you can just pass a session id in the URL, but any way if you are really not having any sessions and no variables you won't have any concurrency issues unless you are referencing a very very strange library, simply because no problems can exist if there is no shared state.
Related
This might be a repetitive question for you, but I couldn't find (atleast I couldn't understand) a satisfactory answer, hence asking again.
I am working with two data sources (MySQL and Oracle). Following is a flow of execution:
Main method-A calls method-B (Which writes into Oracle DB) then it(Method-A) calls method-C (Which writes into mySQL DB) then it(Method-A) calls method-D(Which writes into Oracle DB).
If failure occurs at any of place, everything should be rolled back. Currently only changes in Oracle DB are getting rolled back & mySQL DB is not getting rolled back.
I have defined two transactional managers.
=========> First <=========
<tx:annotation-driven transaction-manager="txManager" mode='proxy' proxy-target-class='true’/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id=“SessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean” parent="AbstractSessionFactory" depends-on="AppConfigHelper”>
<property name="hibernateProperties”>
...
ORACLE DB Properties
</property>
</bean>
<aop:aspectj-autoproxy/>
==============================
=========> Second <=========
<tx:annotation-driven transaction-manager="txManager2" mode='proxy' proxy-target-class='true'/>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory2" />
<qualifier value="CherryTransaction" />
</bean>
<aop:aspectj-autoproxy/>
<bean id="SessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" parent="AbstractSessionFactory2" depends-on="AppConfigHelper">
<property name="hibernateProperties">
...
MYSQL DB Properties
</property>
</bean>
==============================
On top of method-A I have used #Transactional annotation
On top of method-B I have used #Transactional annotation
On top of method-C I have used #Transactional("txManager2")
annotation
On top of method-D I have used #Transactional annotation
Question Is:
Why is MySQL changes are not getting rolled back?
Is the only way to get this working is to use Global transaction management using JTA? (Its a legacy system, and this is the only place where I need to interact with two DBs)
Can you please point me to an example / tutorial where this kind case is handled?
Sincerely thanks for reading this!
For that to work, AFAIK you'd need to use JTA. Even that won't help if you're using a storage engine in MySQL that doesn't support transactions. With MySQL, only InnoDB and BDB storage engines support transactions.
If you are using MySQL with storage engine that supports transactions, you need to configure XA drivers for both Oracle and MySQL datasource and ensure that both datasources are enlisted in the transaction of your container. Spring then needs to participate in the same transaction. You can't use HibernateTransactionManager for this, but need the JtaTransactionManager, as explained in this thread.
So, what you need for this to work is
Use InnoDB or BDB storage engines on MySQL
Configure XA datasources in your application server instead of regular ones
Use JtaTransactionManager on Spring configuration
I'm currently learning EclipseLink and Spring 3.0 MVC:
I wrote a simple standalone application using EclipseLink : it uses a META-INF/persistence.xml file and it reads and writes data from a mysql database.
I also wrote a simple 'HelloWorld' application using Spring3 MVC under apache tomcat. It is based on the following tutorial: http://www.mkyong.com/spring-mvc/spring-3-rest-hello-world-example
now, how should I link both technologies ? As far as I understand from http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch14s06.html I need to create a LocalContainerEntityManagerFactoryBean:
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="someDataSource"/>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
but what is "someDataSource" ? should I use another library like http://commons.apache.org/dbcp/ ? then what should I do with eclipselink ?
And once the JPA will be configured, how should I access it from my spring Controller ?
Thank you
someDataSource would just be another bean, for example:
<bean id="someDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
Here I'm also using a property replacement for the properties, this is designated by the following bean:
<context:property-placeholder location="classpath:properties/runtime.properties" />
Since context is under a different xml namespace add:
xmlns:context="http://www.springframework.org/schema/context"
to your XML namespaces, and
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
to your schemaLocation string within the bean xml document.
classpath:properties/runtime.properties
This property file would be found at the following location in a standard Maven setup:
src/main/resources/properties/runtime.properties
Within this runtime.properties file you'd need to define values for each of the properties that have placeholders (i.e. jdbc.driverClassName, jdbc.url, etc.). An example of this would be:
jdbc.driverClassName=com.mysql.jdbc.Driver
If you're using MySQL for your database.
Generally speaking, you might want a service layer between your controller and repository (DAO). The reason being is controller should concentrate only on handling requests, and responding. Any business logic should be done in a different layer, through business objects, etc. Service layer acts as an intermediary between web layer, and repository layer. This not only separates concerns, but also makes things infinitely more unit testable, a huge part of any Spring application (at least it should be!).
As to how to wire things up, try inserting this bean into your Context as well:
<context:component-scan base-package="xx.yy..." />
Where xx and yy are your package names, this will tell Spring to scan your packages for "components" or #Controller objects, #Service, and #Repository (there are a few other ones but those are the main things to know about). With this information provided to Spring, you can #Autowire beans (dependency inject) into other beans.
For example:
#Service
public class SomeServiceImpl implements SomeService
{
private SomeRepository someRepository;
#Autowired
public void setSomeRepository(SomeRepository someRepository)
{
this.someRepository = someRepository;
}
...
}
This will inject the repository into the service allowing you to access that repositories methods.
Another design tip, always program for interfaces in Spring. This is especially true when it comes to repositories due to the fact that early in development, you might want to implement a Hibernate repository, but down the line DBAs might scoff at that, and require a JDBC repository using straight SQL. This way, you just need to implement the Repository using a JDBC approach rather than Hibernate, inject the JDBC repository instead of Hibernate, and you're done.
Hope this gets you started!
I'm using Spring in Glassfish and I have the need to configure it so it also works outside of the container, mainly for development purposes.
What I'm uncertain of, and couldn't find the answer to, was whether I can use the LocalContainerEntityManagerFactoryBean class without a container.
From its name, LocalContainer, it seems I can but in the docs it says:
FactoryBean that creates a JPA
EntityManagerFactory according to
JPA's standard container bootstrap
contract
so I'm uncertain about this issue.
Thanks,
Ittai
I just wanted to note that Spring supports running the JPA stuff outside of a container, and doesn't require anything in the way of a transaction manager. The question to ask is whether you are using Spring's declarative transaction management (e.g., "#Transactional").
If you are, then you need to provide an implementation of "PlatformTransactionManager." Here still, you do NOT need to use full on JTA support (as provided by Atomikos in the above example. YOu can simply use a JpaTransactionManager instance (which expects a reference to the entity manager factory) provided you are not doing anything with "XA" etc. If you are doing XA, then Atomikos, or Bitronix or any of a number of other options are just fine. You might look at this example http://blog.springsource.com/2011/08/15/configuring-spring-and-jta-without-full-java-ee/ which demonstrates how to use JTA (with JPA and JMS, for example).
So, reiterating, if you're just doing simple JPA (connecting to one database) then you don't need JTA, and you definitely don't need GlassFish. If you need XA, then you can still use a third party JTA provider as the responder above suggested, and you still don't need Glassfish.
Finally, if you truly wish to maintain both GlassFish + JTA, and a separate JPA that works only locally for rapid development on a faster container, you might consider the imminent Spring 3.1, which features "profiles" to allow you to conditionally define beans per environment (e.g., "production," or "dev," or "cloud," or whatever you'd like.)
Yes, it's possible, but you need to provide a transaction manager (like Atomikos). The rest of the configuration is the same.
This is an example:
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
</bean>
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="userTransactionService">
<property name="forceShutdown" value="true" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
....
</bean>
I am using Oracle 9 JDBC Thin Driver - the connection string I have used for standard JDBC was:
jdbcConn.connect("jdbc:oracle:thin:myDevDb/myDevDb#fooServer:1521:MYSIDNAME");
...just trying to get my head around using this kind of connection in Spring 2.5.
How do you wire up Spring to an Oracle connection - think it has something to do with an XML conifg file but not sure, there seems to be a couple of ways to do it.
Any help much appreciated...
LATEST EDIT
Thanks to those who have responded so far - but I need a bit of a "leg up" - on the part where you configure in the database connection string setup in your config, where do you put this info, and how?
I have an existing Java web application - and I am trying to get to grips with how I 'shoehorn' Spring into my existing app.
There are a few ways of doing this and it depends on what your environment is. If you're using Spring there's a fair chance you're deploying a Web application or you're otherwise in a J2EE environment. If this is the case (and arguably even if it isn't) you probably want to configure a DataSource.
This is a fairly minimal solution:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The above is using the Apache (Jakarta Commons) database connection pooling but your appserver probably has an alternative you may want to use instead. Also, different database vendors have their own data source implementations too (eg OracleDataSource and OracleXADataSource for Oracle).
Note the use of properties like jdbc.username. This is a typical configuration because database configurations typically vary between environment. You can activate a property configurator with something like:
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
Now you probably want transactions too I would imagine. The easiest way is to use a platform transaction manager but, like with most things Spring, there are multiple ways of doing it.
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
After this you can use this bean directly or (arguably more common) you can use declarative transactions with AOP (annotations).
More on these subjects in the (superb) Spring reference documentation.
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.