I'm trying to use a Spring JdbcTemplate instance to generate a DataSet useable for subsequent DBUnit tests.
any ideas how to do that?
all the documentation I found where going from a JDBC Connection instance to a IDatabaseConnection instance.
But the code I have abstract all this away using Spring, and what I have is a JdbcTemplate instance.
Any ideas?
Your jdbcTemplate bean has a dataSource property, so you can either get it from the jdbcTemplate with its getter or inject the dataSource (which you already have defined somewhere in your applicationContext) in your class where you build the IDatabaseConnection and use it as a constructor-arg for that. (you should do the latter)
See the following blog for a detailed explanation and full example (written by a springsource trainer)
http://blog.zenika.com/index.php?post/2010/02/04/Testing-SQL-queries-with-Spring-and-DbUnit%2C-part-1
http://blog.zenika.com/index.php?post/2010/02/05/Testing-SQL-queries-with-Spring-and-DbUnit%2C-part-2
Related
I am migrating an EJB project to Spring boot project. I have successfully replaced other annotations to the spring annotation, but havving problem with SessionContext object.
My legacy code is bellow
#Resource
SessionContext sessionContext;
.....
if (some condition) {
sessionContext.setRollbackOnly();
return false;
}
For this code i am getting the following error
A component required a bean of type 'javax.ejb.SessionContext' that could not be found.
Action:
Consider defining a bean of type 'javax.ejb.SessionContext' in your configuration.
I think you'll have to use a few different functionalities.
setRollbackOnly()
Most often I have seen Session Context used for Rollbacks. In Spring, you can replace this with:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
or annotate class with
#Transactional(rollbackFor = MyException.class)
so you can throw your exception from class to cause rollback.
getBusinessObject()
The second most commonly used feature is method to load a business object so that I can, for example, create a new transaction within a same bean. In this case you can use Self-inject:
#Lazy private final AccountService self;
and annote method with #Transactional. This, of course, solves any other cases where you need to use the power of a proxy object.
Other functionality is provided by other classes in Spring, but I think that these two are the most commonly used in the Java EE world and when migrating, one will look to replace them in Spring.
I am developing a Spring-Boot application using spring-boot-starter-data-jpa. I am not able to understand which annotation I should use for injecting EntityManager?
#Autowired or #PersistenceContext
I know #PersistenceContext is a JPA annotation whereas #Autowired belongs to Spring. But internally how do they make a difference?
I have already taken a look at this. But could not understand the exact reason.
A datasource is source of data. This could be for example a database.
One option if you need multiple datasources is to define them in a persistence.xml file. Here you can define multiple and separate them by name.
#PersistenceContext will then give you more fine grain of what you want to inject. Here you can select which datasource by defined name. There are some other options too.
https://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceContext.html
If using #Autowire you are just injecting the available persistence context by bean name. If you have 2 or more persistence contexts this may fail because of ambiguity.
I've searched for a long time on this topic however I cannot find a solution to my specific issue. I am trying to figure out how I can pull the JDBC connection from Hibernate so that I can run a query for generating reports. I am trying to use a JDBC connection since my reports don't map well to the existing Entity situation that we have.
Right now, my application has a bean for a LocalContainerEntityManagerFactoryBean and a bean for DataSource, which is a just a DriverManagerDataSource, both residing in a core configuration file. The problem that I am having is, whenever I try to wire up my DAO to access the JDBC connection by doing something like this:
#PersistenceContext
private EntityManagerFactory entityManagerFactory;
private SessionFactory session;
public SystemUsageReportDAO() {
session = entityManagerFactory.unwrap(SessionFactory.class);
}
I simply get a null pointer exception at the constructor line. I've tried all manner of getting the connection from the EntityManagerFactory, however I'm not sure how I can do it. Any advice would be appreciated.
I know that my end goal is to get a Session object, and from there I can call doWork, however getting to that Session is proving quite the task for me.
I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.
Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.
It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.
According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory
JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
The problem turned out to be that #Transactional annotations are not used automatically, and need the help of a TransactionInterceptor
Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.
However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?
Update:
While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.
The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:
We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.
That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.
To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.
I solved this by manually binding the EntityManager and EntityManagerFactory to the executing thread, before creating repositories with the JpaRepositoryFactory. This is accomplished using the TransactionSynchronizationManager.bindResource method:
emf = Persistence.createEntityManagerFactory("com.foo.model", properties);
em = emf.createEntityManager();
// Create your transaction manager and RespositoryFactory
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
// Make sure calls to the repository instance are intercepted for annotated transactions
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new MatchAlwaysTransactionAttributeSource()));
}
});
// Create your repository proxy instance
FooRepository repository = factory.getRepository(FooRepository.class);
// Bind the same EntityManger used to create the Repository to the thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
try{
repository.save(someInstance); // Done in a transaction using 1 EntityManger
} finally {
// Make sure to unbind when done with the repository instance
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
There must be be a better way though. It seems strange that the RepositoryFactory was designed to use EnitiyManager instead of an EntityManagerFactory. I would expect, that it would first look to see if an EntityManger is bound to the thread and then either create a new one and bind it, or use an existing one.
Basically, I would want to inject the repository proxies, and expect on every call they internally create a new EntityManager, so that calls are thread safe.
Page 342 of spring-framework-reference.pdf (bundled with spring-framework-3.1.0.M2) states, "The JdbcTemplate can be used within a DAO implementation through direct instantiation with a DataSource reference." However, it goes on to say, "The DataSource should always be configured as a bean in the Spring IoC container."
Does anyone know why the DataSource shouldn't be provided to a JdbcTemplate from a plain-old JNDI lookup outside of the Spring container, e.g. How to programatically use Spring's JdbcTemplate?
"The DataSource should always be configured as a bean in the Spring IoC container."
It appears that this note is intended to clarify the preceding statement:
"The JdbcTemplate can be used within a DAO implementation through direct instantiation with a DataSource reference, or be configured in a Spring IoC container and given to DAOs as a bean reference."
I believe the information these statements are trying to convey is that when you're configuring a DAO in Spring, you can either:
inject the DataSource directly into the DAO and create the JdbcTemplate in code yourself, or
you can make the JdbcTemplate a Spring bean as well, inject the DataSource into the JdbcTemplate, and inject the JdbcTemplate into the DAO.
The note, then, means that if Spring is managing the DAO and its dependencies, the DataSource must be a Spring bean in either case, as it needs to be injected either into the DataSource for use in constructing the JdbcTemplate (case 1) or into the JdbcTemplate itself (case 2).
I wouldn't take it to mean that a DataSource used in a JdbcTemplate must always be managed by Spring and only Spring. The note does give that impression. It's probably worth filing a bug against.