I'm getting errors trying to inject resource dependencies into my unit testing.
My approach has been to write a TestConfig.java to replace the applicationContext.xml for production which manages the connections of the beans. So that I can run it with an in-memory database and just test components.
TestConfig.java
#Configuration
#EnableTransactionManagement
public class TestConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl("jdbc:hsqldb:mem:testdb");
ds.setUsername("sa");
ds.setPassword("");
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
LocalContainerEntityManagerFactoryBean lcemfb
= new LocalContainerEntityManagerFactoryBean();
lcemfb.setDataSource(this.dataSource());
lcemfb.setPackagesToScan(new String[] {"com.dao","com.data"});
lcemfb.setPersistenceUnitName("MyTestPU");
HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
lcemfb.setJpaVendorAdapter(va);
Properties ps = new Properties();
ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
ps.put("hibernate.hbm2ddl.auto", "create");
lcemfb.setJpaProperties(ps);
lcemfb.afterPropertiesSet();
return lcemfb;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
return tm;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor()
{
return new AutowiredAnnotationBeanPostProcessor();
}
}
ProductsDaoTest.java
#ContextConfiguration(classes = { TestConfig.class })
#RunWith(SpringJUnit4ClassRunner.class)
public class ProductsDaoTest {
#Resource(name="com.dao.ProductsDao")
private ProductsDao testDao;
#Test
public void testSaveProduct() {
Product productA = new Product();
testDao.save(productA);
Set<Product> products = testDao.getAllProducts();
assertNotNull(products);
}
}
The error is Error creating bean with name 'com.dao.ProductsDaoTest': Injection of resource dependencies failed
So it can't find the ProductDao Bean which is a #Repository with a #Autowired sessionFactory.
So my guess is that because I'm not naming the beans using xml it can't find it, though I thought it should automatically pick it up from setPackagesToScan(). So is there a way to manually insert the Bean mapping so that it can be found?
Also more generally is this a reasonable way to go about testing Spring DAO configurations?
Regards,
Iain
I think you are trying to use wrong name of your DAO bean in #Resource annotation. Have you explicitly specify name of the ProductsDao bean using #Qualifier? If no, then as I remember by default the name of the bean will be productsDao. So you should inject your DAO like:
#Resource(name="productsDao")
private ProductsDao testDao;
If you have only one ProductDAO implementation then simply write:
#Autowired
private ProductsDao testDao;
or
#Inject
private ProductsDao testDao;
In case if you want to give specific name to DAO then use next construction:
#Respository
#Qualifier(name="specificName")
public class ProductDAO...
EDIT:
As Boris noted you should also specify which package to scan for defined beans (classes annotated with #Component, #Service, #Repository...). For this you should add #ComponentScan annotation to your configuration class definition.
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = {"package_to_scan"})
public class TestConfig {...}
Related
Maybe it is kind of too common but still.
I have a small test project where I'm testing all the JPA stuff. Almost everywhere I'm using Spring Data and JPA repositories work just fine. But now I'm trying to make my service to save entities. The service looks something like this:
#Service
public class SomeServiceImpl implements SomeService {
#Autowired
private EntityManagerFactory entityManagerFactory;
public SomeServiceImpl(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
#Override
#Transactional
public SomeEntity save(SomeEntity someEntity) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.persist(someEntity);
return someEntity;
}
The persistence config looks like this (I'm intentionally copying and pasting the whole config. Maybe it would help you to reproduce the error):
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories
#PropertySource({"classpath:conf/application.properties"})
public class PersistenceConfig {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() throws SQLException {
PoolDataSourceImpl dataSource = new PoolDataSourceImpl();
dataSource.setConnectionFactoryClassName(environment.getRequiredProperty("db.driverClassName"));
dataSource.setURL(environment.getRequiredProperty("db.url"));
dataSource.setUser(environment.getRequiredProperty("db.username"));
dataSource.setPassword(environment.getRequiredProperty("db.password"));
dataSource.setFastConnectionFailoverEnabled(
Boolean.valueOf(environment.getRequiredProperty("db.fast.connect.failover.enabled")));
dataSource.setValidateConnectionOnBorrow(true);
dataSource.setSQLForValidateConnection("SELECT SYSDATE FROM DUAL");
dataSource.setONSConfiguration(environment.getRequiredProperty("db.ons.config"));
dataSource.setInitialPoolSize(Integer.valueOf(environment.getRequiredProperty("db.initial.pool.size")));
dataSource.setMinPoolSize(Integer.valueOf(environment.getRequiredProperty("db.min.pool.size")));
dataSource.setMaxPoolSize(Integer.valueOf(environment.getRequiredProperty("db.max.pool.size")));
dataSource.setAbandonedConnectionTimeout(0);
dataSource.setInactiveConnectionTimeout(60 * 25);
dataSource.setTimeToLiveConnectionTimeout(0);
dataSource.setMaxConnectionReuseTime(60 * 30L);
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.setProperty("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.setProperty("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.setProperty("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
return properties;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(#Autowired DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setPackagesToScan("com.dropbinc.learning.jpa.model");
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
Map jpaProperties = new HashMap();
jpaProperties.put("javax.persistence.schema-generation.database.action", "drop-and-create");
entityManagerFactory.setJpaPropertyMap(jpaProperties);
entityManagerFactory.setJpaProperties(hibernateProperties());
return entityManagerFactory;
}
#Bean
public PlatformTransactionManager transactionManager(#Autowired EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
And one more where I'm planning to configurate the rest of the application (placed in the same package):
#Configuration
#ComponentScan(basePackages = "com.dropbinc.learning.jpa")
public class AppConfig {
}
I've tried to debug Spring but all that I wasn't able to detect a difference between transaction behaviour of JPA repositories and my service. I saw transaction was created and even commited. But in case of JPA repositories it got saved while in my service implementation it did generated ids but an entity didn't appeared in a database.
I'm running all the stuff in tests, autowiring the service by interface:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { AppConfig.class, PersistenceConfig.class })
public class AllTheTests {
#Autowired
SomeService someService;
...
}
Thank you very much for any suggestion!
EDIT Adding entityManager.flush() call generates nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress.
I am new to the programming world so what I say may seem silly.
I am trying to run a spring-boot test as JUnit under Eclipse but I just can't figure out how to use the spring-boot annotations... I have read several guides and browsed this website but didn't find anything that resolved my problem.
I am trying to run the JUnit test-class below :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={CBusiness.class,CService.class,CDao.class}, loader = AnnotationConfigContextLoader.class)
#SpringBootTest
public class CalculTest {
#Autowired
CBusiness business;
#Test
public void testCalcul() throws TechnicalException {
Object object= new Object();
object.setId1("00");
object.setId2("01");
object.setNombrePlacesMaximum(new BigInteger("50"));
Long result=business.calcul(object);
assertTrue(result>0);
}
Running this as a JUnit test gives me the following exception :
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
The EntityManager parameter from the CDao class has the annotation #PersistenceContext, I thought this meant it was automatically generated by Hibernate but apparently it isn't... How can I instanciate the EntityManager using only java code? I don't have any .xml or .properties file...
FYI here are the classes called by the test :
Business Layer :
#Component("cBusiness")
public class CBusiness {
#Autowired
CService cService;
public long calcul(Object object) throws TechnicalException {
//Code (calls a method from CService class)
}
Service layer :
#Service
public class CService {
#Autowired
CDao cDao;
Dao Layer
#Repository
#Transactional(rollbackFor = {TechnicalException.class})
public class CDao {
#PersistenceContext
EntityManager entityManager;
I tried testing the method inside a webservice using only the #autowire annotation on the Business layer and if worked fine, however I just cannot instanciate it in the JUnit tests. I tried several ways of running this test and I am not sure this is the right way of doing it, so I'm open to any suggestion.
Thanks in advance.
#Configuration
#EnableTransactionManagement
public class PersistenceJPAConfig{
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "\\your package here" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("\\Driver");
dataSource.setUrl("\\URL");
dataSource.setUsername( "\\userName" );
dataSource.setPassword( "\\password" );
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
Hi i am beginner in Spring and Jpa Integration. While i have tried to configure my database connection,details handler itp. I came across a strange behavior of spring.
First of all, I have 3 config file:
1) RootConfig - contains everything but controllers
2) WebConfig - contains every Bean which is controllers annotated
3) JdbcConfig - contains Beans related with dataSource, this config is imported by RootConfig using this annotation (#Import(JdbcConfig.class)).
RootConfig looks like this:
#Configuration
#Import(JdbcConfig.class)
#ComponentScan(basePackages = "app", excludeFilters = {#ComponentScan.Filter(type = FilterType.ANNOTATION,value = {EnableWebMvc.class, Controller.class})})
public class RootConfig
{
}
JdbcConfig:
#Configuration
#PropertySource("classpath:db.properties")
#EnableTransactionManagement
public class JdbcConfig
{
#Resource
public Environment env;
#Bean
public DataSource dataSource()
{
System.out.println(env);
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(env.getProperty("dataSource.driverClassName"));
ds.setUrl(env.getProperty("dataSource.Url"));
ds.setUsername(env.getProperty("dataSource.username"));
ds.setPassword(env.getProperty("dataSource.password"));
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource ds, JpaVendorAdapter jpaVendorAdapter)
{
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(ds);
emfb.setJpaVendorAdapter(jpaVendorAdapter);
emfb.setPackagesToScan("app.model");
return emfb;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter()
{
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.POSTGRESQL);
adapter.setShowSql(true);
adapter.setGenerateDdl(true);
adapter.setDatabasePlatform(env.getProperty("dataSource.dialect"));
return adapter;
}
#Bean
public BeanPostProcessor beanPostProcessor()
{
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
public JpaTransactionManager jpaTransactionManager(EntityManagerFactory em) {
return new JpaTransactionManager(em)}}
At this moment everything works fine, Environment field is not null value and contains all defined properties. The problem appear when I am trying to add Bean PersistenceAnnotationBeanPostProcessor So when I add this Bean to JdbcConfig.class, Environment field became null but when i add this RootConfig Environment again contains all needed values. So is there any known problem with propertySource and this bean? Is PersistenceAnnotationBeanPostProcessor somehow affect on #PropertySource or #Autorwired(#Inject/#Ressource) Environment field? Is there any reason why Environment must be configure in main config and it cannot be imported from other config by #Import?
I think your problem is related with this spring issue SPR-8269.
Can you try setting up PersistenceAnnotationBeanPostProcessor bean definition as static?
I also had same problem and I solved in this way.
I'm writing a RESTful web service using Spring MVC, using Java Configuration. My configuration file is below. My issue is this -- I discovered that 2 instances of "myService" bean is being created, instead of just one instance. I'm not sure why? How can I adjust the configuration to create only one?
Can anyone point me in the right direction? Thanks!
Here's my configuration class....
#Configuration
public class MyConfig {
#Bean(name = "dataSource")
public DriverManagerDataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// datasource set up
return dataSource;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DriverManagerDataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages("com.mypackages");
sessionBuilder.addProperties(getHibernateProperties());
return sessionBuilder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.enable_lazy_load_no_trans", "true");
properties.put("hibernate.id.new_generator_mappings", "true");
return properties;
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
#Bean
public MyMainBean MyMainBean() {
MyMainBean bean = new MyMainBean();
bean.setService(myService());
bean.setValidator(myValidator());
return bean;
}
#Bean(name = "myService")
public MyService myService() {
MyService s = new MyService();
s.setDao1(myDao1());
s.setDao2(myDao2());
s.setCopyUtil(copyUtil());
return s;
}
#Bean
public MyDao1 myDao1() {
return new MyDao1();
}
#Bean
public MyDao2 myDao2() {
return new MyDao2();
}
#Bean
public CopyUtil copyUtil() {
return new CopyUtil();
}
#Bean
public ReportValidator reportValidator() {
ReportValidator validator = new ReportValidator();
validator.setService(myService());
return validator;
}
#Bean
public XMLValidator xmlValidator() {
XMLValidator validator = new XMLValidator();
validator.setService(myService());
return validator;
}
}
Actually, Spring is smart when wiring beans and should only call the myService() function once, and then pass the result to the other myService() calls, resulting in only one bean of MyService.
Make sure you really are getting 2 instances of MyService, e.g. by adding a log in the constructor of the MyService class.
If you truly see more than one constructor log statement, make sure that you are not declaring other MyService beans in other #Configuration classes, or that you are not using any component annotation on the MyService class (i.e. don't use #Service, #Component, #Repository).
If you declare the class with #Service, it effectively instantiates the class and adds it to the context. When you declare it again with #Bean you end up with 2 instances, so don't mix them.
Also, you don't need to use those #Autowired annotations here, or even calls to other beans, because the following will also work:
#Configuration
public class DbConfiguration {
#Bean
public MovieDao dao() {
return new MovieDao();
}
#Bean
public MovieService service(MovieDao dao) {
return new MovieService(dao);
}
}
Spring will see that you need a MovieDao to build a MovieService and it will instantiate the dao first and pass it to the service bean. You don't even need to add #Service or similar annotations to your classes!
It really is that good, hope these tips help ;)
At the outset, I have tried the options mentioned in various forums for the same stack trace I get. A few of them did not work while with others (like removing javax.persistence.transactiontype) I did not understand how and where to try it.
I am using Spring Boot data JPA (1.2 RC2) + Hibernate (with a custom persistence.xml). Here is my Application.java
#Configuration
#ComponentScan(<our package>)
#EnableAutoConfiguration(exclude = EmbeddedServletContainerAutoConfiguration.class)
#EnableTransactionManagement
#DependsOn("transactionManager")
#EnableJpaRepositories(transactionManagerRef = "transactionManager")
public class Application {
public static void main(String[] args) {
run(Application.class, args);
}
}
My RepositoryConfiguration (as we have custom persistence.xml - currently need to reuse it)
#Configuration
public class RepositotyConfiguration {
#Autowired
private DataSource dataSource;
#Value("${db.dialect}")
private String dialectClass;
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = builder.dataSource(dataSource).
persistenceUnit("main").build();
entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties additionalProperties = new Properties();
additionalProperties.put("hibernate.dialect", dialectClass);
entityManagerFactory.setJpaProperties(additionalProperties);
return entityManagerFactory;
}
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return txManager;
}
}
The transactionManager here is created if I do not have a single Repository but the moment I add one, ny tests fail with this exception:
Caused by: java.lang.NullPointerException
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:76)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:118)
at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
My test application context is:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#EnableAutoConfiguration
#TransactionConfiguration(transactionManager = "transactionManager")
#IntegrationTest("server.port:0")
#ActiveProfiles("test")
public abstract class TestApplicationContext {
#Autowired
private WebApplicationContext wac;
#Value("${local.server.port}")
private int port;
...
}
An example (not the actual) of the repository I try to add (where let's say Item is a model object)
public interface ItemRepository extends CrudReposity<Item, Long> {
Item findByCode(String code); // this seems to cause the problem, assume 'code' is field in Item
}
Any pointers will be of utmost help.
EDIT: It now fails only if I add extra method in ItemRepository say Item findByItemCode(String itemCode) where let's say itemCode is a field in Item model, but can't understand why?
Thanks,
Paddy