To write Junit Test cases for spring based REST API - java

For Spring based Rest API, in order to write JUnit test cases, do I need an established database connection or can i have a mock database. Can I get some suggestions.
Technology Stack used si:
Spring MVC,
Hibernate

It depends on what you are testing. If you are testing the service layer, you should not establish actual connections to the database. Instead, you can mock up repository objects, using Mockito, for example. Here is an example of how to wire up mock Repository objects.
If you want to test your data access logic, you might consider using an in-memory database like hsqldb and define it as a test data source in the test configuration.
For more sophisticated, integration testing, you might want to connect to the actual database.

Under your root-context.xml you may consider setting up different bean profiles. For example:
<beans profile="dev">
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.1.2:3306/mydb"/>
<property name="username" value="admin"/>
<property name="password" value="password"/>
<property name="initialSize" value="3"/>
</bean>
...
</beans>
...
<beans profile="prod">
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.1.3:3306/mydb"/>
<property name="username" value="admin"/>
<property name="password" value="password"/>
<property name="initialSize" value="3"/>
</bean>
...
</beans>
And then under your JUnit tests you may consider using the #Profile annotation above your tests:
#Profile(value="dev")
Alternatively, you may set the spring.profiles.active environment property in your application.properties file or as a launch configuration for your application server via -Dspring.profiles.active=dev
For more information, you may read the Spring docs on Profiles.

Related

JAVA + PostgreSQL + Spring

I want to use Spring to connect to my local PostgreSQL db. I don't know if it is possible, cause I didn't find any tutorials for this. So is it possible? If yes, please explain me where can I find some fine tutorial. If no, how can I do it? I know I can make it via postgresql jdbc, but I want to do it like in real company.
Of course you can. The database vendor is immaterial. Java hides database details using JDBC.
Here is a Spring tutorial that shows you how to do it in 15 minutes or less.
First you need to create a spring project from https://start.spring.io/ and add postgresql to its dependencies. You will then see it build up in your pom.xml file. Then you have to enter the information of the postgresql database you want to connect to in the application.yml file.
Here is my example.
applicationContext.xml :
<!-- the setting msg -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/database.properties</value>
</list>
</property>
</bean>
<!-- PostgreSQL datasource -->
<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>
<!-- ibatis client -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:config/SqlMapConfig.xml" />
<property name="dataSource" ref="dataSource" />
</bean>

Configuring Spring to useMultiple Data Sources

I am trying to connect 2 different schemas within my spring boot application.
To do this I have got 2 different data sources. How should I configure this within my properties files?
I seen this answer which gave me an idea of how to do so. I currently have the following 3 property files in my application:
1. application.properties
2. hibernate.properties
3. multiple-db.properties
application.properties is currently empty. Below are the other 2 files:
hibernate.properties:
# Connection configuration
hibernate.connection.username= my_uname1
hibernate.connection.password= my_pword1
multiple-db.properties:
# Schema 1-Data source configuration
oracle.db.username1= my_uname1
oracle.db.password1= my_pword1
oracle.db.url1= my_url1
# Schema 2-Data source configuration
oracle.db.username2= my_uname2
oracle.db.password1= my_pword2
oracle.db.url2= my_url2
# JPA configuration
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
# Hibernate configuration
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=my_url
hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider
Is this the correct approach? Do I need 3 properties files, or could I do this all in one?
The Spring documentation suggests a way to create primary and secondary data sources:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources
Each data source can be configured as described here:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-configure-a-datasource
You can access them by using #Autowire from other beans. You can associate a prefix to each data source so you can configure it in your application.properties or application.yml file.
You can also set one as primary.
With Spring you can do this easily.
It would be something like this:
<bean id="dataSource_1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/northwind" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="dataSource_2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/northwind_dup" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
You could also use your properties files and do something like this:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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>
<context:property-placeholder location="jdbc.properties"/>
And you could use only one file, or three. It is really up to you.

Get database information at runtime

In my web application (spring + tomcat), below is by applicationContext.xml. All the database information (username, password) is currently directly embedded. But now in our application, the server forks a new JVM instance and this new JVM instance needs to communicate with the same database.
<bean id="meetingDBSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:initialSize="10" p:maxActive="50" p:minIdle="5"
p:maxIdle="35" p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://10.0.1.100/warehouse_mon?useLegacyDatetimeCode=false&useUnicode=true&serverTimezone=UTC&"
p:username="user" p:password="pass" p:testOnBorrow="true"
p:validationQuery="SELECT 1" />>
<bean id="appDB" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="meetingDBSource" />
</property>
</bean>
So I wish to pass the required information as arguments while launching it. Now what is the dignified way of getting this database information?
Initially in my applicationContext.xml, I made a map and inserted all the db information in the map. Using Spring special expressions, I was obtaining the values and then using them for BasicDataSource initialization. And in my code, using dependency injection I obtained access to this map and then obtained information.
But I guess there should be a more standard factory way of doing it. (Or probably using context-param and if so, how?)
I use it like this.
I have a database.properties file like this.
db.driverClassName=com.mysql.jdbc.Driver
db.connectionUrl=jdbc:mysql://localhost:3306/test
db.username=test
db.password=testpass
sql.use.db.data=false
sql.use.db.test.data=false
Then in applicationContext.xml I will configure
<!--property place holder bean -->
<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="false"/>
<property name="locations">
<list>
<value>classpath:/properties/database.properties</value>
</list>
</property>
Then datasource is configured like this
<!-- data source bean-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.connectionUrl}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
You can use #Value annotation to access the properties in that file.
#Value("${sql.use.db.data}")
private String use_data;

Configure two PostgreSQL database(fail over mechanism) using Spring 3

I am using Tomcat JDBC API(org.apache.tomcat.jdbc.pool.DataSource) to connect to my PostgreSQL database from Spring configuration file as shown below. I got a new requirement to configure two databases which should act as a fail over mechanism, Like When one database is down application should automatically switch back to another database.
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost/dbname?user=postgres" />
<property name="username" value="postgres" />
<property name="password" value="postgres" />
<property name="maxActive" value="5" />
<property name="maxIdle" value="5" />
<property name="minIdle" value="2" />
<property name="initialSize" value="2" />
</bean>
Can anyone suggest how this can be achieved using Spring configuration file.
The normal way this is done is by using virtual IP addresses (with possible forwarding), checking for activity, a shoot-the-other-node-in-the-head approach and proper failover. Spring is exactly the wrong solution to this if you want to avoid things like data loss.
A few recommendations.
repmgr from 2ndquadrant will manage a lot of the process for you.
Use identical hardware and OS and streaming replication.
Use virtual IP addresses, and the like. Use a heartbeat mechanism to trigger failover via rempgr
Then from this perspective your spring app doesn't need reconfiguring.

How to initialize in-memory HSQLDB using script via Spring

I am attempting to do unit testing of my DAO (using Spring and Hibernate). I am using HSQLDB per this tutorial. The tutorial states that the in-memory HSQLDB database can be initialized using a SQL script but I cannot find information on how to do so in Spring. Here is the pertinent Spring context config:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:mydb" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="10" />
</bean>
Any help would be appreciated. Thanks.
If you are trying to work with in-memory databases and Spring, there is a new jdbc namespace for Spring 3 that makes working with embedded databases very easy.
The best part is that it acts as a DataSource, so it can easily be dropped in to replace your existing dataSource bean.
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
If you are more interested in doing this with Java Config, take a look at the EmbeddedDatabaseBuilder (new in Spring 3.0).
#Configuration
public class DatabaseTestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
}
Nicholas answer is perfectly fine, but you can use jdbc namespace to initialize external database as well:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DS"/>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:/META-INF/database/init.sql"/>
</jdbc:initialize-database>
In the tutorial you link to, one of the ways of setting things up is this (after obvious correction):
In-memory from a script: jdbc:hsqldb:file:path-to-file
I think that that would appear to be relevant. I suggest replacing path-to-file with something that looks like a fully-qualified filename…
You could get around this by creating a subclass of BasicDataSource with getters/setters for two new properties, initExecuteSqlFile and destroyExecuteSqlFile, that can have a comma-seperated list of SQL files to execute. The subclass would have init() and destroy() methods that handle the init/destroy SQL files.
Then use the following bean definition:
<bean
id="datasource"
class="com.example.MyBasicDataSource"
destroy-method="destroy"
init-method="init"
>
<property name="destroyExecuteSqlFile">
<value>h2-destroy-01.sql</value>
</property>
<property name="initExecuteSqlFile">
<value>h2-init-01.sql,h2-init-02.sql,h2-init-03.sql</value>
</property>
<!-- Other properties -->
</bean>
With embedded-database we would only be able to connect to the database from the same JVM. If we have two JVMs, for performance or other constraints, we can:
Instead of using an embedded-database, you can use the datasource suggested in this answer.
Then initialize like Poitrek De suggested (and suggested in previous answer too). You may want to create tables only if they do not exist (as suggested here).

Categories