How to mock a Datasource spring bean in class test - java

i want to test a class with a Datasource bean injected, but i don't know how to Mock the Bean Datasource(i dont' have the class but only bean configuration).
My class is like this:
public class Configurazione {
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
...
}
my beans:
<bean id="Configurazione" class="com.company.configurazione.Configurazione">
<property name="dataSource" ref="dataSourceMySql" />
</bean>
<bean name="dataSourceMySql"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="..." />
<property name="username" value="..." />
<property name="password" value="..." />
</bean>
how can i test the class Configurazione with mockito and inject the datasource bean?
i've no class DataSource to #mock in the test class Configurazione.

Usually for testing purposes additional Spring application context is created. And you can define beans differently there. For example you can use in-memory HSQL database as your datasource
<jdbc:embedded-database id="dataSource" type="HSQL" >
<jdbc:script location="scripts/ddl/sequences/*"/>
<jdbc:script location="scripts/ddl/tables/*"/>
<jdbc:script location="scripts/dml/*"/>
</jdbc:embedded-database>
To use this snippet of code as-is you need to add hsql dependency to your project and adjust paths to scripts (these scripts create and populate database schema used in your tests).
And you run your tests with that test application context

Related

Can't access the database values using JdbcTemplate

I'm trying to insert value into Oracle DB using JdbcTemplate, but its throwing the following exception:
Can't access the database values using JdbcTemplate.
This is how I am trying to insert the values to the DB:
package com.sample.common.Dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class UserDao extends JdbcDaoSupport {
public void insert(){
System.out.println("Tring to insert");
String sql = "INSERT INTO SB_TBL_USER (user_id,user_password,user_name,user_email,user_mobile)"+" "
+"VALUES ('test12', 't1est1', 't2est2', 't7est2','t7estm')";
getJdbcTemplate().update(sql);
}
public static void main(String args[]){
UserDao dao= new UserDao();
dao.insert();
}
}
DataSourceConfiguration.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="sbjdev" />
<property name="password" value="sbjdev" />
</bean>
<bean id="UserDao" class="com.mPowerQuartz.common.Dao.UserDao.java">
<property name="dataSource" ref="dataSource" />
</bean>
This exception is most likely thrown by your own code.
And it's most likely thrown because the dataSource field of the UserDao is null.
The reason for that is that you're not using Spring correctly. Instead of asking Spring to create the UserDao and inject the DataSource in that Spring bean, you're creating the UserDao yourself, using new. So no Spring context is ever used, and Spring doesn't play any role in your code.
Read the Spring documentation to understand how to create a Spring application context and get a bean from it.
I found the answers they are..
1)ApplicationContext and bean is not initialized, which will look like..
ApplicationContext ctx = new ClassPathXmlApplicationContext("userconfig.xml");
UserDao usr = (JobDetailsDao) ctx.getBean("UDao");
2)In configuration xml, Dao and Dao implementation are not mapper. Which looks like.
<bean id="UserDao" class="com.mPowerQuartz.common.DaoImpl.UserDaoImpl">
<property name="jdbcTemplate"> <ref bean = "jdbcTemplate" ></ref>
</property>
</bean>

Can a bean be a value to another bean in the Spring Framework?

I'm trying to learn spring framework and bean configuration and so far it seems really cool.
I'm about to create a generic class to include all my Mysql functions and it needs to contain the DataSource. My question is: Is it possible to set the datasource already in the bean configuration?
If not then I'll need to set the class as singleton, create an init function and in the init function to do the following:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
DataSource ds = (DataSource) context.getBean("dataSource");
The question is, instead of doing that, can I 'inject' (donno if that's the right term)
it directly in the bean?
this is my bean configuration.
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/foo"/>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
<property name="validationQuery" value="SELECT 1" />
<property name="testOnBorrow" value="true" />
<property name="testWhileIdle" value="true" />
<property name="initialSize" value="5" />
</bean>
<bean id="bar" class="foo.bar">
<property name="dataSource" value="<HERE_SETTING_THE_DATA_SOURCE_ABOVE>" />
</bean>
Is this possible ?
You can reference a bean like your dataSource.
Your class should have a member that can hold the dataSource:
package mypackage;
public class MyBean {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = data.Source;
}
}
Then you can inject the dataSource bean into this bean:
<beans>
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<!-- set properties -->
</bean>
<bean id="myBean" class="mypackage.MyBean">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
That's it.

Running <jdbc:initialize-database> at the beginning of context creation

I need to execute SQL script before PropertyPlaceholderConfigurer is initialized in Spring's context, as soon as application properties are stored in the database and this script should insert them. But currently placeholder is initialized earlier, which leads to errors.
Is there a way to execute <jdbc:initialize-database data-source="dataSource" ... before <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" ... in Spring?
Or is there a way to initialize placeholderConfig bean later? I tried to use depends-on, lazy-init attributes for this bean, but it didn't help. Thanks in advance.
Another solution without creating any Bean:
If you've got one <jdbc:initialize-database /> you can add this property depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" to your bean <bean id="placeholderConfig" />
If you have more than one <jdbc:initialize-database /> adapt the #0.
Here is how I solved that. I created a class Initializer. This class in its constructor executes plain old sql statements (java.sql.Statement), creates table (if it doesn't exist), and inserts properties (if they are not there). The dataSource bean is passed in the context to this constructor, and placeholderConfig bean uses depends-on="initializerBean". So, properties appear in the database before they are used.
This script
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc">
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:database/drop_schema.sql" />
<jdbc:script location="classpath:database/create_schema.sql" />
<jdbc:script location="classpath:database/sample_data.sql"/>
</jdbc:initialize-database>
<!-- Other bean definitions -->
</bean>
is essentially a shortcut to
<bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer" id="dataSourceInitializer">
<property name="databasePopulator" ref="resourceDatabasePopulator"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="resourceDatabasePopulator"
class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
<property name="scripts">
<array>
<value>classpath:database/drop_schema.sql</value>
<value>classpath:database/create_schema.sql</value>
<value>classpath:database/sample_data.sql</value>
</array>
</property>
</bean>
Note that I've added id to the DataSourceInitializer bean. Now you can reference it in PropertyPlaceholderConfigurer's depends-on attribute. That way you declare that your PropertyPlaceholderConfigurer should be created after DataSourceInitializer.
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="dataSourceInitializer"/>
In my case db was initialized after the LocalContainerEntityManagerFactoryBean had been created and Hibernate was unable to validate my schema.
The documentation explains how to deal with these problems:
http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch12s09.html
12.9.1.1 Initialization of Other Components that Depend on the Database
Our use case was arguably even more complex. We're using flyway for database migrations and it needs to be started before the entityManagerFactory is created. The problem for us was that <jdbc:initialize-database /> was only used in our migration tests and thus initialized in a different application context than flyway and the entityManagerFactory. So we couldn't simply use L. BIZE answer and let our flyway bean depend on org.springframework.jdbc.datasource.init.DataSourceInitializer#0 because it might not exist (i.e. in production it doesn't exist). We ended up creating a custom factory bean like this:
class OptionalBeanInitializer extends AbstractFactoryBean implements BeanFactoryAware {
private String beanName;
private BeanFactory beanFactory;
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
#Override
public Class<?> getObjectType() {
return OptionalBeanInitializer.class;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
#Override
protected Object createInstance() throws Exception {
if (beanFactory.containsBean(beanName)) {
// Initialize
beanFactory.getBean(beanName);
}
return new OptionalBeanInitializer();
}
}
Which we could use to depend on our optional dependency like this:
<bean id="optionalDataSourceInitializer" class="com.x.y.z.OptionalBeanInitializer">
<property name="beanName" value="org.springframework.jdbc.datasource.init.DataSourceInitializer#0"/>
</bean>
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate" depends-on="optionalDataSourceInitializer">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"
depends-on="flyway, optionalDataSourceInitializer">
<property name="dataSource" ref="dataSource"/>
</bean>
The OptionalBeanInitializer will take care of initializing the org.springframework.jdbc.datasource.init.DataSourceInitializer#0 bean only if it exists.
There are two simpler ways to add the depend-on attribute only for test context, and not for production context.
1/Override the bean in the test context.
In our case here is the production context :
<bean id="placeholderConfig" />
And the unit test context :
<bean id="placeholderConfig" depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" />
Make sure that the unit test context is loaded before the production context and the good placeholderConfig bean will be instanciated, after the jdbc:initialize-database phase.
2/Another way is to use profiles
<beans profile="!test">
<bean id="placeholderConfig" .../>
</beans>
<beans profile="test">
<jdbc:initialize-database data-source="dataSource" .../>
<bean id="placeholderConfig" depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" .../>
</beans>

Spring Mvc DataSource Bean when using annotations

I would like to know how Dependency Injection is done on the dataSource bean when using annotations in the applicationContext.xml or whats the annotation equivalent for injecting this bean into DAO's, i have the following dataSource bean defined:
<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>
Something like this: Create a SimpleJdbcTemplate and inject it with the DataSource. Then annotate that into your DAO:
#Repository
public class FooDao {
#Resource(name = "jdbcTemplate")
private SimpleJdbcTemplate jdbcTemplate;
}
You're correct - you don't need anything more than SimpleJdbcTemplate. Hibernate isn't necessary.
Either of these should work.
#Resource
private DataSource dataSource;
or
#Autowired
private DataSource dataSource

Spring JPA and persistence.xml

I'm trying to set up a Spring JPA Hibernate simple example WAR for deployment to Glassfish.
I see some examples use a persistence.xml file, and other examples do not.
Some examples use a dataSource, and some do not. So far my understanding is that a dataSource is not needed if I have:
<persistence-unit name="educationPU"
transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.coe.jpa.StudentProfile</class>
<properties>
<property name="hibernate.connection.driver_class"
value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/COE" />
<property name="hibernate.connection.username" value="root" />
<property name="show_sql" value="true" />
<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
I can deploy fine, but my EntityManager is not getting injected by Spring.
My applicationContext.xml:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="educationPU" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="StudentProfileDAO" class="com.coe.jpa.StudentProfileDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="studentService" class="com.coe.services.StudentService">
</bean>
My class with the EntityManager:
public class StudentService {
private String saveMessage;
private String showModal;
private String modalHeader;
private StudentProfile studentProfile;
private String lastName;
private String firstName;
#PersistenceContext(unitName="educationPU")
private EntityManager em;
#Transactional
public String save()
{
System.out.println("*** em: " + this.em); //em is null
this.studentProfile= new StudentProfile();
this.saveMessage = "saved";
this.showModal = "true";
this.modalHeader= "Information Saved";
return "successs";
}
My web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
Are there any pieces I am missing to have Spring inject "em" in to StudentService?
Just to confirm though you probably did...
Did you include the
<!-- tell spring to use annotation based congfigurations -->
<context:annotation-config />
<!-- tell spring where to find the beans -->
<context:component-scan base-package="zz.yy.abcd" />
bits in your application context.xml?
Also I'm not so sure you'd be able to use a jta transaction type with this kind of setup? Wouldn't that require a data source managed connection pool? So try RESOURCE_LOCAL instead.
I'm confused. You're injecting a PU into the service layer and not the persistence layer? I don't get that.
I inject the persistence layer into the service layer. The service layer contains business logic and demarcates transaction boundaries. It can include more than one DAO in a transaction.
I don't get the magic in your save() method either. How is the data saved?
In production I configure spring like this:
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/ThePUname" />
along with the reference in web.xml
For unit testing I do this:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:persistence-xml-location="classpath*:META-INF/test-persistence.xml"
p:persistence-unit-name="RealPUName" p:jpaDialect-ref="jpaDialect"
p:jpaVendorAdapter-ref="jpaVendorAdapter" p:loadTimeWeaver-ref="weaver">
</bean>
If anyone wants to use purely Java configuration instead of xml configuration of hibernate, use this:
You can configure Hibernate without using persistence.xml at all in Spring like like this:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}
Since you are not using persistence.xml, you should create a bean that returns DataSource which you specify in the above method that sets the data source:
#Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}
Then you use #EnableTransactionManagement annotation over this configuration file. Now when you put that annotation, you have to create one last bean:
#Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}
Now, don't forget to use #Transactional Annotation over those method that deal with DB.
Lastly, don't forget to inject EntityManager in your repository (This repository class should have #Repository annotation over it).
I have a test application set up using JPA/Hibernate & Spring, and my configuration mirrors yours with the exception that I create a datasource and inject it into the EntityManagerFactory, and moved the datasource specific properties out of the persistenceUnit and into the datasource. With these two small changes, my EM gets injected properly.
This may be old, but if anyone has the same problem try changing unitname to just name in the PersistenceContext annotation:
From
#PersistenceContext(unitName="educationPU")
to
#PersistenceContext(name="educationPU")

Categories