In Spring, how do I use a ClassPathXmlApplicationContext to get an EntityManager? - spring

With Spring I can autowire a bean with the following property:
#PersistenceContext(unitName="foo") private EntityManager em;
Using the following I can manually autowire the bean "someBean":
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
AutowireCapableBeanFactory fac = ctx.getAutowireCapableBeanFactory();
fac.autowireBean(someBean);
However, I can't figure out how to directly get a particular EntityManager. The use case is that I want to write a test that will get all EntityManager objects and execute simple queries in them to ensure that they are set up properly. To do this I need to be able to get all EntityManager objects from the application context. How can I do that?
The following does not work. It returns an empty map.
Map<String,EntityManager> ems = ctx.getBeansOfType(EntityManager.class);

Try calling
EntitiyManagerFactory factory =
(EntityManagerFactory) ctx.getBean("myEntityManagerFactoryBean")
EntityManager em = factory.createEntityManager();
where "myEntityManagerFactorBean" is your LocalContainerEntityManagerFactoryBean
But why would you need that?

I use the SpringJUnit4ClassRunner
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:jndiContext-mock.xml",
"classpath:spring/testContext.xml" })
The clase under test is injected via the mock context. With this annotated it will get the entity manager via injection.
#PersistenceContext
protected HibernateEntityManager entityManager;

Related

Spring Batch : How to instantiate "Step" scope bean in Cucumber Testing?

How to instantiate "Step" scope bean of spring in Cucumber Testing?
SpringJUnit4ClassRunner uses #TestExecutionListeners to instantiate the step scoped beans for testing purpose.
I am trying get this behavior in Cucumber. Cucumber uses a #RunWith(Cucumber.class)
Is there anyway we can instantiate step scope bean?
Thanks in advance
I'm not familiar with Cucumber, but I have instantiated/tested step scope items using #RunWith(SpringJUnit4ClassRunner.class)
I would recommend including the StepScopeTestExecutionListener.class as well as the DependencyInjectionTestExecutionListener (if you're injecting any dependencies) in your #TestExecutionListeners annotation, e.g. #TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
In order to instantiate a step scope bean in the test class, first get an instance of the ExecutionContext by utilizing the MetaDataInstanceFactory.
For example:
ExecutionContext executionContext = MetaDataInstanceFactory.createJobExecution().getExecutionContext();
Once you can have an instance of the ExecutionContext, you'll need to make use of the JobLauncherTestUtils class (documentation: http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/test/JobLauncherTestUtils.html). You can launch a step by calling launchStep(), for example:
jobLauncherTestUtils.launchStep(<step_name>, <job_parameters>, <execution_context>);
Hope that helps!
By exploring some options i have made it workable for now.
Below is my workaround
Bean Configuration
#Bean(name = "abc")
#StepScope
public ABC getABC(){
return new ABC();
}
#ContextConfiguration(classes = AppConfiguration.class, loader = AnnotationConfigContextLoader.class)
public class StepDef {
#Autowire
ABC abc;
public StepDef{
StepExecution stepExecution = getStepExecution();
StepSynchronizationManager.register(stepExecution);
}
}
I am not sure how correct is this implementation. I have initialize the StepExecution to load my configuration in stepDef Constructor so my AutoWiring can work properly and i can run my test against it.
I need to follow same approach for all stepDef , may be i will write a super class and implement that in super constructor.
Do let me know if you see any concerns.
Thanks again

Inject autowired object as mock into spock test in spring boot application

I have a Spring Boot application and Service with private DAO field inside it. Private DAO property is annotated with #Autowired (no setters or constructors set it, just annotation).
I tried to write Spock test for service, but can't find how to inject mock DAO into #Autowired variable.
class TestService extends Specification {
DAO dao = Mock(DAO)
Service service = new Service()
def "test save"() {
when:
service.save('data')
then:
1 * dao.save('data')
}
}
Any ideas?
UPD: I'm testing java code.
As result I did this:
class TestService extends Specification {
DAO dao = Mock(DAO)
Service service = new Service()
void setup() {
service.dao = dao
}
def "test save"() {
when:
service.save('data')
then:
1 * dao.save('data')
}
}
One point was to use reflection. But Groovy can set private fields directly without additional manipulations. It was news for me.
sorry to bring a little over a year old thread to life but here is my two cents. Groovy does provide access to private fields even though it break encapsulation. Just incase if you haven't figured it out, when you manually instantiate a class with Autowired fields, Autowired fields will be null. You can either provide setters for it and set them or groovy can see private fields anyways. However, if you have luxury I would suggest to refactor it to use constructor injection and do the same for any of your code in future. Field Injection and setter injections have some problems when it comes to testing.

Hibernate Filters with JPA EntityManagerFactory and Spring

I have a jersey + spring application that is using EntityManagerFactory and spring JpaTransactionManager to handle the db manipulations. The JPA implementation is hibernate.
I would like to know is there a way to enable hibernate filters in this scenario.
I tried extending org.springframework.orm.jpa.JpaTransactionManager and overriding
#Override
protected EntityManager createEntityManagerForTransaction() {
EntityManager manager = super.createEntityManagerForTransaction();
Session session = manager.unwrap(Session.class);
return manager;
}
But I am not sure that this method is called at the right place.
EDIT:
I am using spring JpaRepositories to persist/query entities.
I found an answer for this problem. It seems like other people are still struggling with this, I will post my solution.
I am enabling the filters that I need in business service methods that are marked as #Transactional (that is important).
In your service, inject the entity manager factory:
#Autowired
private EntityManagerFactory entityManagerFactory;
Inside the #Transactional method obtain the entity manager from the transactionManager, unwrap it to hibernate session and enable the filters that you need. This is done as follows:
//Obtain the entity manager for the current transaction
EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory);
EntityManager entityManager = holder.getEntityManager();
//Unwrap to get the underlying hibernate session
Session hibernateSession = entityManager.unwrap(Session.class);
//Configure your filters
Filter publishedAfterFilter = hibernateSession.enableFilter("...");
publishedAfterFilter.setParameter("...", ...);
publishedAfterFilter.validate();

Spring autowiring with bean scope of prototype

I have a question in spring with autowire with a bean which is having a scope of prototype..
So basically i am writing a code which is spring with JPA.So i am autowiring my entity manager in my DAO layer .I am loading the entitymanager from a class by using the #configuraion Annotation .
#Configuration
public class DALConfigurationLoader {
#Bean
#Scope("prototype")
public EntityManager getEntityManager() {
}
When i do this i am expecting that for every request it should get a new bean .
#Component
public class OfferPriceDomainDAOImpl {
#Autowired
private EntityManager entityManager;
public OfferPrice getOfferPrice(String offer_Price_Id) throws DataAccessException{
//use entitymanager here
}
}
In this case it is a single entity manager for all the request which is wrong.i want each method should get a new entity manager .As based on the jpa specification every new request should process a new entity manager...How can i autowire a bean with a scope of prototype..
I would really appreciate if some one can answer my question..
Thank,
Swati
Use #PersistenceContext to inject an EntityManager, not #Autowired, as outlined in the JPA section of the Spring reference guide. It takes care of the lifecycle for you properly.
As to why it wasn't working the way you thought it might: whenever an instance of your DAO is created, it would be injected with an EntityManager. Since the EntityManager is scope=prototype, a new one will be created for each DAO that needs to be injected for one. However, since your DAO is a singleton, only one of them is created, so only one EntityManager is ever needed.
#Inject // or #Autowire
Provider<EntityManager> entityManagerProvider;
and then get EntityManager instance using entityManagerProvider.get().
I used javax.inject.Inject instead of Autowire because Provider is defined there too. Also that also would work in Guice.

Spring JPA : Application managed persistence context with #Transactional and #PersistenceContext

Currently im trying out the application managed persistence context, by creating the entity manager manually and store them to enable transaction that spans multiple request calls (perhaps something like extended persistence context) in JSE application.
But, im wondering whether i can avoid sending the entityManager object throughout the service and DAO methods as an additional parameter by making use of the spring's #PersistenceContext injection and mark the methods with #Transactional annotation to use the transaction started manually with that entity manager.
I think i can somehow manage this by using a ThreadLocal for this feature, but i'll be happier to be able to attach this to the spring framework.
This is an example of What i have in mind :
The UI action method :
Here we can see the transaction is started by the ui logic, since there iss no facade / command method in the backend to group these callings to the business logic :
Long transactionid = tool.beginTransaction();
// calling business methods
tool.callBusinessLogic("purchase", "receiveGoods",
paramObject1, transactionid);
tool.callBusinessLogic("inventory", "updateInventory",
paramObject2, transactionid);
tool.commitTransaction(transactionid);
Inside the tool :
public Long beginTransaction() {
// create the entity --> for the #PersistentContext
Entitymanager entityManager = createEntityManagerFromFactory();
long id = System.currentTimeMillis();
entityManagerMap.put(id, entitymanager);
// start the transaction --> for the #Transactional ?
entityManager.getTransaction().begin();
return id;
}
public void commitTransaction(Long transactionId) {
EntityManager entityManager = entityManagerMap.get(transactionId);
entityManager.getTransaction().commit();
}
public Object callBusinessLogic(String module, String function,
Object paramObject, Long transactionid) {
EntityManager em = entityManagerMap.get(transactionId);
// =================================
// HOW TO DO THIS????
// =================================
putEntityManagerIntoCurrentPersistenceContext(em);
return executeBusinessLogic(module, function, paramObject, transactionid);
}
And the example for the service method :
public class Inventory {
// How can i get the entityManager that's been created by the tool for this thread ?
#PersistenceContext
private EntityManager entityManager;
// How can i use the transaction with that transactionId ?
#Transactional
public void receiveGoods(Param param) {
// ........
}
}
Is there anyway to achieve this ?
Thank you !
Spring's handling of the #PersistenceContext annotation does almost exactly what you're after, with one big difference: you always get a transaction scoped EntityManager and Spring injects always the same instance for the same thread, so you have kind of propagation and don't have to worry about thread-safety. But you'll never get an extended context this way!
Believe me, Spring 3 and extended persistence context don't play well together, maybe this will change in Spring 3.1 but I'm afraid that's not in their focus. If you want to use an extended persistence context let Spring inject the EntityManagerFactory (via #PersistenceUnit annotation) and then create the EntityManager on your own. For propagation you'll have to either pass the instance as a parameter or store it in a ThreadLocal yourself.
Indeed to have a application managed persistence context, you need to somehow "hack" the #Transactional & #PersistenceContext infrastructure by providing them your own Entity Manager and do not let Spring create its own.
The key to achieve this is to play a little bit with the TransactionSynchronizationManager class to register your own Entity Manager to the thread local, Spring will use it to inject to the #PersistenceContext attribute.
I had this need some time ago for my own application and I've designed a small architecture based on Spring AOP to manage the extended persistence context.
Details here: JPA/Hibernate Global Conversation with Spring AOP
When you configure your transactions via #Transactional, then you should handover the configuration of your transactions to the annotation.
Here you start your transaction and then hope that the #Transactional will also be triggerd.
for more information you would best start reading http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html => 9.5.6. Using #Transactional

Resources