Saturday 14 December 2013

Setup Jenkins Continuous and Automatic Build System

Jenkins is an open source tool which provides continuous integration services for software development. If you want to get more detail about Jenkins and it's history I would suggest refer this link. This post will help you installing and configuring Jenkins and creating jobs to trigger maven builds. Setting up Jenkins is not a rocket science indeed. In this post, I would like to concise the installation and configuration steps.


Installing Jenkins
Though, there are different ways to install Jenkins. But, in this post I will be describing Jenkins installation with Apache Tomcat server. Hence, please make sure that you have Apache Tomcat.   
  1. Download Jenkins war file from here and copy war into tomcat's 'webapp' folder
  2. Start the tomcat server and access Jenkins

Jenkins installation is done. Wow, so easy. Isn't it?

Configuring Jenkins
Now you have Jenkins running with you. It's time to configure the project specific environment for continuous and automatic build. This section describes about JDK, Maven and Mail Notification configuration.

Go to 'Manage Jenkins

 

Go to 'Manage Jenkins > Configure System'




Creating Job for Automatic and Continuous Build
So far you installed and configured  the Jenkins. It's time to create new job. Before creating new job ensure that your project is a maven project. Now, go to 'New Job' and fill the required information. believe, below screen shot tells everything which is required to configure a job. You just need to configure below points at minimum:
  • Source Code Management
  • Build Triggers
  • Build
  • Notifications





Once you save the job you will see below screen


Now click on 'Build Now' and see the 'Build History'. You will get new entry in 'Build History'. To see the build logs just hover the mouse on this build and click on 'Console Output', you can see the build logs.



Congratulations! you are done with setting up continuous build system.If you want to see that how effectively it works, just check-in any file in your project and see whether your build is triggered automatically. In case, build is failed with latest checked-in changes you must get a notification mail saying build is failed.

Last but not least, you should agree with my point 'Setting up Jenkins is not a rocket science indeed'. Shouldn't you? :) :) :)

Saturday 7 December 2013

CodeReviewer - Free Peer Code Review Tool

Peer code review is an important activity to find and fix mistakes which are overlooked during development. It helps improving both software quality as well as developers skills. Though, it’s a good process for quality improvement. But this process becomes tedious if you need to share files and send review comments through mails, you need to organize formal meetings and you need to communicate peers who are in different time zone. Here is the point, why to do this manually? Why to follow this tedious process? There are so many automated code review tools which ensure fast, easy and collaborative code review process.

My team used to follow this tedious process manually. By following this process almost for one year we realized that we should go for automated code review tools. I explored free tool for code review. After evaluating so many tools I found pretty interesting tool called CodeReviewer. I would say this is an ‘Awesome’ tool with rich documentation and great community support.

CodeReviewer is free code review tool from SmartBear. This tool provides basic features which are required in code review process like Subversion integration, user administration, event based email notification, real time chat with peers etc. If you want advanced feature you can go for commercial version ‘CodeReviewer Pro’. The yearly price for ‘CodeReviewer Pro’ subscription is around 257$ per enabled user.

'CodeReviewer' and 'CodeReviewer Pro' Features Comparison Matrix


Installation and Configuration Insights
Installing CodeReviewer is very easy task. You just download the windows setup from here and install on your system by following this link. Once installation is done follow link1 and link2 to configure CodeReviewer.

Environment Specific Configuration
Once CodeReviewer is ready to use, now it’s time to configure Server URL, integrate mail server, integrate Subversion and  configure users.

Review Life Cycle
As far as CodeReviewer’s life cycle concern, there are 5 phases of review life cycle. Below diagram describes each and every phase and there processing order. 

How to Use CodeReviewer 
You can start review by creating new review request. Note that you can't create review as admin user. You need to log-in as different user. If you want to upload file from Subversion you can follow this. Once the review request is created and sent for review, reviewers need to perform review and communicate with other participants who are participating in this review.

Questions and Answers
  • Which database is used in CodeReviewer by default?
The server installer comes with support for the hypersonic embedded database. 
  • Can I integrate my own database with CodeReviewer?
Yes. MySQL Server can be integrated with CodeReviewer. For Oracle and SQL Server you need to go for Pro. Refer this link for more detail. 
  • Can I integrate my own Bug Tracking system with CodeReviewer?
Code Reviewer can be integrated with external issue-tracking systems such as TeamTrack, Bugzilla, JIRA, and FogBugz. Refer this link for more detail. 
  • Can I take CodeReviewer Backup?
Yes. Admin user can take the CodeReviewer backup by following 'System Status > Server Backup'. Refer this link for more detail. 
  • How to restore backup?
CodeReviewer backup can be restored. Refer this link for more detail.

Others
You might face below issue while configuring SVN Repository. 


Install the SVN client from here and configure svn.exe path in 'svn Executable' text box.

At last I would suggest you to have a look into this video. This tells about how to use CodeReviewer in Eclipse IDE itself. 

WOW, I have very nice experience with CodeReviewer. I liked this one. You will like this.Won't you?


Saturday 30 November 2013

Hudson Plugin for Eclipse

If you are using Hudson as continuous integration server and you might feel lazy about accessing Hudson explicitly to check the build status or checking Hudson build status mails, there is an option to monitor Hudson build and perform build activities in Eclipse IDE itself. This post describes about installing, configuring and using the Hudson in Eclipse IDE.

Installing Hudson Plugin in Eclipse
Use below URL To install the Hudson Eclipse plugin using Eclipse Update Manager:

In case you face issue while installing plugin using update manager you can directly drop dk.contix.eclipse.hudson_x.x.x.jar  in Eclipse's plugins directory and restart IDE.

Configuring Hudson 
Once the installation is done, configure the Hudson URL from Preferences > Hudson to connect to Hudson server. Also remember to Check URL whether URL is valid or not. Your Hudson server must be running at this point of time.


How to Use Hudson in Eclipse?
In eclipse, go to Windows > Show View > Hudson. You will see below tab is added in your Eclipse. Also, When the plugin is running, a health icon is displayed at the bottom of the Eclipse window. The icon is red on build failure and green on success.  Please note that due to limitations in Eclipse, the Hudson view must be active before the icon is displayed.


In case build is failed, you will get below pop-up in your eclipse IDE. 


You can also perform below activities using this Eclipse Hudson plugin.For this, select any project listed in Hudson tab and right click.
  1. Schedule New Build
  2. View Console Output
  3. Open Hudson in Browser


If you want to  access the Hudson admin console in your Eclipse,  go to 'Hudson' tab and double click on your project.


Limitations 
If your Hudson server requires authentication and authorization for access, then you can not see the list of jobs in Eclipse. Because Eclipse Hudson plugin does not facilitates interface to provide Hudson web credentials. To overcome this limitation, you have to give read permission to Anonymous user for jobs in Hudson which need to be displayed in Eclipse. 

Common Issues
  •  Issue in configuring Hudson base URL which is SSL enabled
Solution: This issue is due to missing required certificates. Refer below links to generate the certificate. Once the certificate is generated you can copy those into $JAVA_HOME/lib/security for the JRE that eclipse is using for its run time. It will trust that cert and then you can access configured HTTPS URL successfully.

  • Once your certificate issue is resolved then you may face below issue
             java.security.cert.CertificateException: No subject alternative names present

            Solution: Configure HTTPS URL using DNS rather giving IP address.
             For example: Use this https://mybox.com/hudson instead of  https://XX.XX.XX.XX/hudson 
  • While refreshing build status you get below pop-up 

            Solution: Ensure that your job's name in Hudson does not contain white spaces.

References
Below are the references for more detail about Hudson Eclipse plugin.

Sunday 27 October 2013

Ehcache: Cache Replication in Clustered Environment using JGroups

If you are using Ehcache and you want to replicate your cache across all the nodes in a clustered environment, you may find some fruitful information in this post.There are three different ways to replicate your cache across all the nodes in a cluster:
  • JGroups Replicated Caching
  • RMI Replicated Caching
  • JMS Replicated Caching
This post tells about ‘JGroups Replicated Caching’. JGroups is a simple clustered task distribution system. JGroups integration with Ehcache facilitates replicating the cache across the nodes in a cluster.

How to configure?

Cache replication configuration with JGroups is not much complicated .With very simple configuration you can achieve cache replication in your clustered environment. 


You need to configure below files for cache replication:
  • ApplicationContext.xml (Spring's application context file)
  • Ehcache.xml: (Ehcache configuration file)
  • JgroupCache.xml (JGroups configuration file for nodes communication)
ApplicationContext.xml: Configure 'EhCacheManagerFactoryBean' in application context file to initialize cache manager.

<bean id='ehCacheManager'
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean''>
<property name="configLocation" value="classpath:Ehcache.xml"/>
 <property name="shared" value="true" />
</bean> 

Ehcache.xml: To replicate cache in a cluster you need to configure below tags in 'Ehcache.xml' file:
  • cacheManagerPeerProviderFactory: This tag is used to create a CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.
  • cacheEventListenerFactory: Enables registration of listeners for cache events, such as put, remove, update, and expire.
  • bootstrapCacheLoaderFactory: Specifies a BootstrapCacheLoader, which is called by a cache on initialization to prepopulate itself.
Each cache that will be distributed needs to set a cache event listener which replicates messages to the other CacheManager peers. This can be done by adding a 'cacheEventListenerFactory' element of type 'JGroupsCacheReplicatorFactory' to each distributed cache's configuration as per the following example:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    updateCheck="false">
    
    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
        properties="file=JGroupsCache.xml" />  
   
    //This cache is configured to be replicated
    <cache name=”mycache" eternal="true" maxElementsInMemory="100"
        overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
        timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU">       

      <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
            properties="replicateAsynchronously=true, replicatePuts=true,
            replicateUpdates=true, replicateUpdatesViaCopy=false,
            replicateRemovals=true" />   
       
      <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=false" />  
    </cache>

</ehcache>

JgroupCache.xml: In this file you generally need to configure your nodes and there listening ports for cache replication.

<?xml version="1.0" encoding="UTF-8"?>
<config>
   <TCP bind_addr="host1" bind_port="7831" />
   <TCPPING timeout="3000"
       initial_hosts=" host1[7831], host2[7832]"  //Two nodes are in the cluster
       port_range="1"
      num_initial_members="2"/>
   <VERIFY_SUSPECT timeout="1500"  />
   <pbcast.NAKACK use_mcast_xmit="false" gc_lag="100"
      retransmit_timeout="300,600,1200,2400,4800"
      discard_delivered_msgs="false"/>
   <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000" max_bytes="400000"/>
   <pbcast.GMS print_local_addr="true" join_timeout="5000" shun="false" view_bundling="true"/>
</config>

Frequently Asked Questions

1: What if I get below log message If one node tries to send cache notification to others?
'Dropped message from host1-64423 (not in xmit_table)'

Solution: There is a property named ‘discard_delivered_msgs’ should be false in JGroups configuration file.

2: How to keep JGroups configuration file out of web application war file?

Solution: In 'Ehcache.xml', you need not to hard code your 'JGroupsCache.xml'. You can specify this with the help of system property.

Define the JVM argument like -Djsgroup-config-location = C:\jgroups-configuration\JGroupsCache.xml
and then specify this property in 'Ehcache.xml' file.

<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
        properties="file=${jsgroup-config-location} " />  

3: How to analyze whether nodes are communicating each other?

Solution:  You must see below logs in your server to ensure whether your nodes are registered as per JGroups configuration or not.

Logs:
-------------------------------------------------------------------
GMS: address=IP-ADDRESS-41447, cluster=EH_CACHE, physical address= 2002:19a1:70a:0:0:0:19a1 :70a:58603
-------------------------------------------------------------------
[10/25/13 17:57:38:451 IST] 0000001e JGroupsCacheM I net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProvider init JGroups Replication started for 'EH_CACHE'. JChannel: local_addr=IP-ADDRESS-41447
cluster_name=EH_CACHE
my_view=[IP-ADDRESS-41447|0] [IP-ADDRESS-41447][IP-ADDRESS-41448]
connected=true
closed=false
incoming queue size=0
receive_blocks=false
receive_local_msgs=false
state_transfer_supported=true

4: How to enable 'Ehcache' logs?

Solution: In your log4j configuration file, add below entries to view the Ehcache related logs.

<category name="net.sf.ehcache"  additivity="false">
     <priority value="debug" />
     <appender-ref ref="console" />
  </category>
  <category name="net.sf.ehcache.config"  additivity="false">
     <priority value="debug" />
     <appender-ref ref="console" />
  </category>
  <category name="net.sf.ehcache.distribution"  additivity="false">
     <priority value="debug" />
     <appender-ref ref="console" />
  </category>

 Others                                                                                                        
  • To get more detail about cache replication methods in Ehcache, you can refer this link.
  • To get detailed information about above configuration you can refer this link.
  • You can also refer very nicely written post from here

Sunday 20 October 2013

Automatic Sequence Diagram Generation

As a developer or architect, you always need to draw some sequence diagrams to demonstrate or document your functionality. And of course, if you do this manually you have to spare much time for this activity. Just think about, what If sequence diagram is generated automatically and you get it free of cost. Your reaction would be ‘wow’ this is great. But the next question will be ‘how’. So, I am publishing this post to describe ‘how’.There are different open source tools which help to generate UML sequence diagrams. ‘Java Call Trace’ is such a tool that can generate UML sequence diagram based on reverse engineering.

Install ‘Java Call Trace’
  • Download the java call trace from here.
  • Extract its contents at your desired location.
How to Use ‘Java Call Trace’ to Generate Sequence Diagram

     To generate sequence diagram using Java call trace you have to follow below steps:
  • Define your filter in <javacalltracer>\Calltracer\filters.txt
This will generate sequence diagram only for the classes which are defined under given package. For example: com.mycom.example 
  • Capture call trace (as xml) of your application/program 
For JDK 1.5 and above, add the following JVM options and  execute your application/program.

Syntax:
-agentpath:[full-path-to-folder-of-dll]\calltracer5.dll=traceFile-[trace-file],filterFile-[filter-file],filterList-[filter|filter|...],outputType-[xml or text],usage-[controlled, uncontrolled] -Djava.library.path=[full-path-to-folder-of-dll] -Dcalltracerlib=calltracer5 

Example
-agentpath:C:\calltracer\jvmti\calltracer5.dll=traceFile-C:\calltracer\call.trace,filterFile-C:\calltracer\filters.txt,outputType-xml,usage-uncontrolled -Djava.library.path=C:\calltracer\jvmti -Dcalltracerlib=calltracer5
  • Generate sequence diagram using call trace captured in first step
Once you have generated a XML output using the ‘calltracer’ tool you can use the ‘Calltrace2Seq tool’ to generate UML sequence diagram.

<javacalltracer>\Calltrace2Seq\src\Calltrace2Seq.java INPUTXMLFILE-C:\\test.xml OUTPUTFOLDER-C:\\ OUTPUTFILENAME-mysequencediagram

INPUTXMLFILE: This is the generated xml location.
OUTPUTFILENAME: This is the location where generated sequence diagram image is copied.

Note: The output generated by the ‘calltracer’ tool has some header information that will not allow it (the output) to be used directly as an input to the ‘Calltrace2Seq’ tool. You can remove the header from the output xml file and then use this file as input argument for ‘Calltrace2Seq’.

Generated Sample Sequence Diagram

Below diagram is generated using Java Call Trace. There are three classes ManagedBean, Service and DataAccess. Where ManagedBean is having main method which is calling Service's method and Service is calling DataAccess's method.



Java Call Trace Details

If you are interested to get more details about Java Call Trace you can refer below:

<javacalltracer>\readme.txt
<javacalltracer>\calltracer\readme.txt
<javacalltracer>\Calltrace2Seq\readme.txt

Sunday 13 October 2013

Audit Logging using Hibernate Interceptor in JPA 2.0

If you are using JPA 2.0 with Hibernate and you want to do audit logging from middle-ware itself, I believe you landed up on the exact place where you should be. You can try audit logging in your local environment by following this post.

Required JPA/Hibernate Maven Dependencies

<dependency>
         <groupId>org.hibernate.java-persistence</groupId>
         <artifactId>jpa-api</artifactId>
         <version>2.0-cr-1</version>
</dependency>
<dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-entitymanager</artifactId>
         <version>3.6.4.Final</version>   
</dependency>
<dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-orm</artifactId>
         <version>3.0.5.RELEASE</version>
</dependency>

JPA Configuration in Spring Application Context File

For JPA/Hibernate, you need to configure entity manager, transaction, data source and JPA vendor in your ‘applicationContext.xml’ file.

<bean id="dataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource"
         p:driverClassName="oracle.jdbc.driver.OracleDriver"  
        p:url="jdbc:oracle:thin:@127.0.0.1:1521/mydbservice "
         p:username="nvuser" p:password="nvpass" />

<bean id="entityManagerFactory"
         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
         p:persistenceUnitName="MyPersistentUnit"
         p:persistenceXmlLocation="classpath*:persistence.xml"
         p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
         <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
         </property>              
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
                 p:entityManagerFactory-ref="entityManagerFactory" />

<bean id="jpaAdapter"
                 class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
                 p:database="ORACLE" p:showSql="true" />

Persistence.xml Configuration

To enable the hibernate audit logging you need to configure a property called ‘hibernate.ejb.interceptor’ in persistence.xml file and the value of this property should be the class that extends the Hibernate ‘EmptyInterceptor’.

<?xml version=”1.0” encoding=”UTF-8”?>
<persistence version="2.0"
         xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
         <persistence-unit name=" MyPersistentUnit ">
               
                 //JPA Entity classes are configured here
                 <class>com.mycom.entities.User </class>           

                 <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

                 <properties>
                 <property name="hibernate.ejb.interceptor"
                          value=" com.xxx.entities.baseentity.AuditLogInterceptor" />
                 </properties>
         </persistence-unit>
</persistence>

Audit Logging Interceptor Implementation

Hibernate provides an interceptor called ‘EmptyInterceptor’ with following methods.
  • onSave() – This method is called when an entity is saved, but the entity is not saved into database yet.
  • onFlushDirty() – This method is called when an entity is updated, the entity is not update into database yet.
  • onDelete () – This method is called when an entity is deleted , the entity is not deleted into database yet.
  • preFlush() – This method is called before the saved, updated or deleted entities are not committed to the database.
  • postFlush() – This method is called after the saved, updated or deleted entities are committed to database. This is called after preFlush() method.

To perform audit logging follow below steps:
  • Create data base table to capture audit data:
          Audit [ Row_ID, Old_Value, New_Value, Column_Changed, Table_Changed,
                    Transaction_Id, User_ID]
  • Create JPA entity say ‘AuditTrail’ for above table
  • Create class ‘AuditLogInterceptor’ by extending Hibernate ‘EmptyInterceptor’.
  • Override interceptor methods in ‘AuditLogInterceptor’
  • Capture required information into AuditTrail entity and save entity

public class AuditLogInterceptor extends EmptyInterceptor {  
    
  private List<AuditTrail> auditTrailList = new ArrayList<AuditTrail>();    
   . . . . . .
 
   // First Parameter: The entity which is being updated     
   // Second Parameter: The primary key of updated row 
   // Third Parameter:  Current states of updated entity    
   // Fourth Parameter: Previous states of updated entity  
   // Fifth Parameter: The variable names of updated entity
   // Sixth Parameter: The type of variables of updated entity
   @Override
   public boolean onFlushDirty(Object entity, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {                     
           // Get the table name from entity
           Class<?> entityClass = entity.getClass();
            Table tableAnnotation = entityClass.getAnnotation(Table.class);            
          
           for (int i = 0; i < currentState.length; i++) {              
                // Track changes only for the states which are String or Number types           
                 if(!(previousState[i] instanceof String
                     || previousState[i] instanceof Long
                     || previousState[i] instanceof BigDecimal
                      || previousState[i] instanceof Integer
                     || previousState[i] instanceof Timestamp))
                 {
                          continue;
                 }                
                // Check whether column value is updated
                 if(previousState[i] != null && currentState[i] != null
                   &&  !(previousState[i].equals(currentState[i]))){
                         
                  AuditTrail auditTrail = new AuditTrail();               
                 // Set updated table name
                 auditTrail.setTableName(tableAnnotation.name());
                 // Set updated column name
                 Column col = null;
                 try {                                                  
                        String filedName = propertyNames[i];
                        if(filedName.contains("serialVersionUID")){
                                  continue;
                        }
                        Character firstChar =  filedName.charAt(0);
                        firstChar = Character.toUpperCase(firstChar);
                        String filedNameSubStr = filedName.substring(1);
                        String methodName = "get"+ firstChar+filedNameSubStr;                       
                        Class[] parameterTypes = new Class[]{};                           
                        Method ueMethod = entityClass.getDeclaredMethod(methodName, parameterTypes);
                        col = ueMethod.getAnnotation(Column.class);                         
                    } catch (Exception e) {
                                e.printStackTrace();
                    }
                   if(col != null){
                          auditTrail.setColumnIdentifier(col.name());       
                   }               
                // Set old value
                if(previousState[i] != null){
                          auditTrail.setOldValue(previousState[i] == null  ? null :
                         previousState[i].toString());    
                }               
                // Set new value
                if(currentState[i] != null){
                          auditTrail.setNewValue(currentState[i] == null ? null:
                         currentState[i].toString());
                }               
                // Set database operation
                auditTrail.setOperation("Update");               
                // Set row primary key value
                auditTrail.setRowIdentifier(id.toString());  
                auditTrailList.add(auditTrail);                         
              }           
            }                        
        return false;
    }        
    @Override  
    public void postFlush(Iterator iterator) throws CallbackException {            
           // Set unique transaction id in all AuditTrail Entities
           String transId = UUID.randomUUID().toString();     
           for (AuditTrail auditTrailauditTrailList) {
               auditTrail.setTransactionId(transId);
           }   
          // Save ‘AuditTrail’ entity list into database using AuditDAO 
    }  
 } 

Audit logging Sequence Flow




Issue Faced during Audit Logging Implementation

I faced an interesting issue during audit logging implementation in my application. Let me share that issue detail.

I had ‘AbstractDAO’ and 'AuditDAO' class extends this ‘AbstractDAO’. 'AuditDAO' class is configured as ‘@Repository’. AbstractDAO’ has entity manager property which is initialized by Spring Container. I wanted to auto wire ‘AuditDAO’ in ‘AuditLogInterceptor’ to save ‘AuditTrail’ entity. But, this couldn’t happen. The reason was ‘AuditLogInterceptor’ was not defined as spring resource (like @Component or @Resources or @Repository). Hence's its property can’t be auto wired. Since, this interceptor is initialized by hibernate, I couldn't configure this as spring resource. Finally, I had to take the help of StackOverflow and got the idea to solve this problem. You can refer this issue and solution from here.