Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Thursday, June 9, 2016

My Review of Sanjay Patel’s Spring Course

Spring is the most popular Java framework for building web and enterprise applications. There are plenty of official documentation, books, and Training Courses available for Spring framework on web.

I got an opportunity to review Sanjay Patel‘s Spring Course Material which is divided into 3 modules.

http://www.naturalprogrammer.com/spring-tutorial/

The total course is divided into 3 modules covering various aspects of web application development using Spring/SpringBoot framework.
  • Module I : Spring Framework 4 And Dependency Injection For Beginners
  • Module II : Spring Framework for the Real World
  • Module III : Spring Framework REST API Development

Module I: Spring Framework 4 and Dependency Injection For Beginners

This module covers the basics of Spring Dependency Injection mechanism using Annotations and JavaConfig based approach using SpringBoot.

The material is structured in such a way that the readers can follow the course and practice in a step by step manner.

The following topics are covered in this Module:
  • Quick and brief introduction to Dependency Injection using Spring
  • Loading and binding properties from properties files
  • Using environment profiles
  • Brief introduction about using @Conditional
  • Sending Email
There are plenty of Spring core feature are there which can’t be covered in a single book or video.But I think it would be great to cover the most commonly used features Scopes, like LifeCycle methods @PostConstruct and @PreDestroy etc.

Overall, this module will be good for people who already have some basic knowledge on Spring. But for complete beginners it may be overwhelming to understand all these Spring concepts along with SpringBoot.

Module II: Spring Framework for the Real World

This module covers the most of the aspects of web application development. The explanation is straight forward and to the point.

This module explains the concepts by implementing various use-cases of typical User Management such as SignIn, SignUp, Forgot Password, Reset Password etc.

This module covers:
  • Implementing Controllers, Request Parameters binding
  • Performing Validations, Customizing Error Messages
  • Creating custom validation constraints
  • Exception Handling
  • Brief introduction to Spring Data JPA and Transaction Handling
  • Implementing Security using Spring Security
    • Configuring Spring Security
    • Form based Login, Remember Me, Password Encryption
    • Spring Security JSP Tag libraries
  • A quick introduction to Asynchronous processing using @Async
  • Scheduling tasks using @Scheduled

This module gives hands-on experience on using many of the Spring web application development tasks. This module also contains creating many commonly used utilities such as getting I18N messages, getting login user details etc which comes very handy.

We can also use JSP with SpringBoot jar type packaging as described in Spring Boot With JSPs in Executable Jars(https://dzone.com/articles/spring-boot-with-jsps-in-executable-jars-1)

Module III: Spring Framework REST API Development

This module covers building REST API using SpringBoot. This module contains excellent material covering most of the aspects required for building a good REST API.

This module covers:
  • Creating REST Endpoints using @RestController
  • Exception handling via @ControllerAdvice
  • Environment specific properties using Profiles
  • Using @ConfigurationProperties to bind properties
  • How to catch constraint violation exceptions
  • How to use reCAPTCHA
  • Securing REST API
    • Customizing Spring Security to support REST API
    • Switching User
    • Handling CSRF and CORS
    • This module filled with lot of interesting material required to build a Secured REST API.

However, I feel like there are few important things which are not covered:                        
  • No mention of Serializing JPA entities
  • Dealing with bi-directional JPA Entity relation serialization issues
  • Token based Security
Throughout the course author explain the concepts in clear and to the point manner. Also, the course is backed by an application SpringLemon which contains all the code used in this course.
Overall this course looks very to me and I strongly recommend this course if you are looking for a fast paced Spring course.

Tuesday, February 2, 2016

Retrying Method Execution using Spring AOP

One of my blog follower sends an email asking me to show an example of "RealWorld Usage of Spring AOP". He mentioned that in most of the examples the usage of Spring AOP is demonstrated for logging method entry/exit or Transaction management or Security checks.

He wanted to know how Spring AOP is being used in "Real Project for Real Problems". So I would like to show how I have used Spring AOP for one of my project to handle a real problem.

We won't face some kind of problems in development phases and only come to know during Load Testing or in production environments only.

For example:
  • Remote WebService invocation failures due to network latency issues
  • Database query failures because of Lock exceptions etc
In most of the cases just retrying the same operation is sufficient to solve these kind of failures.

Let us see how we can use Spring AOP to automatically retry the method execution if any exception occurs. We can use Spring AOP @Around advice to create a proxy for those objects whose methods needs to be retried and implement the retry logic in Aspect.

Before jumping on to implementing these Spring Advice and Aspect, first let us write a simple utility to execute a "Task" which automatically retry for N times ignoring the given set of Exceptions.

public interface Task<T> {
 T execute();
}


import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TaskExecutionUtil 
{
 
 private static Logger logger = LoggerFactory.getLogger(TaskExecutionUtil.class);

 @SafeVarargs
 public static <T> T execute(Task<T> task, 
        int noOfRetryAttempts, 
        long sleepInterval, 
        Class<? extends Throwable>... ignoreExceptions) 
 {
  
  if (noOfRetryAttempts < 1) {
   noOfRetryAttempts = 1;
  }
  Set<Class<? extends Throwable>> ignoreExceptionsSet = new HashSet<Class<? extends Throwable>>();
  if (ignoreExceptions != null && ignoreExceptions.length > 0) {
   for (Class<? extends Throwable> ignoreException : ignoreExceptions) {
    ignoreExceptionsSet.add(ignoreException);
   }
  }
  
  logger.debug("noOfRetryAttempts = "+noOfRetryAttempts);
  logger.debug("ignoreExceptionsSet = "+ignoreExceptionsSet);
  
  T result = null;
  for (int retryCount = 1; retryCount <= noOfRetryAttempts; retryCount++) {
   logger.debug("Executing the task. Attemp#"+retryCount);
   try {
    result = task.execute();
    break;
   } catch (RuntimeException t) {
    Throwable e = t.getCause();
    logger.error(" Caught Exception class"+e.getClass());
    for (Class<? extends Throwable> ignoreExceptionClazz : ignoreExceptionsSet) {
     logger.error(" Comparing with Ignorable Exception : "+ignoreExceptionClazz.getName());
     
     if (!ignoreExceptionClazz.isAssignableFrom(e.getClass())) {
      logger.error("Encountered exception which is not ignorable: "+e.getClass());
      logger.error("Throwing exception to the caller");
      
      throw t;
     }
    }
    logger.error("Failed at Retry attempt :" + retryCount + " of : " + noOfRetryAttempts);
    if (retryCount >= noOfRetryAttempts) {
     logger.error("Maximum retrial attempts exceeded.");
     logger.error("Throwing exception to the caller");
     throw t;
    }
    try {
     Thread.sleep(sleepInterval);
    } catch (InterruptedException e1) {
     //Intentionally left blank
    }
   }
  }
  return result;
 }

}

I hope this method is self explanatory. It is taking a Task and retries noOfRetryAttempts times in case method task.execute() throws any Exception and ignoreExceptions indicates what type of exceptions to be ignored while retrying.

Now let us create a Retry annotation as follows:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public  @interface Retry {
 
 public int retryAttempts() default 3;
 
 public long sleepInterval() default 1000L; //milliseconds
 
 Class<? extends Throwable>[] ignoreExceptions() default { RuntimeException.class };
 
}

We will use this @Retry annotation to demarcate which methods needs to be retried.

Now let us implement the Aspect which applies to the method with @Retry annotation.

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MethodRetryHandlerAspect {
 
 private static Logger logger = LoggerFactory.getLogger(MethodRetryHandlerAspect.class);
 
 @Around("@annotation(com.sivalabs.springretrydemo.Retry)")
 public Object audit(ProceedingJoinPoint pjp) 
 {
  Object result = null;
  result = retryableExecute(pjp);
     return result;
 }
 
 protected Object retryableExecute(final ProceedingJoinPoint pjp)
 {
  MethodSignature signature = (MethodSignature) pjp.getSignature();
  Method method = signature.getMethod();
  logger.debug("-----Retry Aspect---------");
  logger.debug("Method: "+signature.toString());

  Retry retry = method.getDeclaredAnnotation(Retry.class);
  int retryAttempts = retry.retryAttempts();
  long sleepInterval = retry.sleepInterval();
  Class<? extends Throwable>[] ignoreExceptions = retry.ignoreExceptions();
  
  Task<Object> task = new Task<Object>() {
   @Override
   public Object execute() {
    try {
     return pjp.proceed();
    } catch (Throwable e) {
     throw new RuntimeException(e);
    }
   }
  };
  return TaskExecutionUtil.execute(task, retryAttempts, sleepInterval, ignoreExceptions);
 }
}

That's it. We just need some test cases to actually test it.

First create AppConfig.java configuration class as follows:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AppConfig {

}

And couple of dummy Service beans.

import org.springframework.stereotype.Service;

@Service
public class ServiceA {
 
 private int counter = 1;
 
 public void method1() {
  System.err.println("----method1----");
 }
 
 @Retry(retryAttempts=5, ignoreExceptions={NullPointerException.class})
 public void method2() {
  System.err.println("----method2 begin----");
  if(counter != 3){
   counter++;
   throw new NullPointerException();
  }
  System.err.println("----method2 end----");  
 }
}

import java.io.IOException;
import org.springframework.stereotype.Service;

@Service
public class ServiceB {
 
 @Retry(retryAttempts = 2, ignoreExceptions={IOException.class})
 public void method3() {
  System.err.println("----method3----");
  if(1 == 1){
   throw new ArrayIndexOutOfBoundsException();
  }
 }
 
 @Retry
 public void method4() {
  System.err.println("----method4----");
 }
}

Finally write a simple Junit test to invoke these methods.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class RetryTest 
{
 @Autowired ServiceA svcA;
 @Autowired ServiceB svcB;
 
 @Test
 public void testA()
 {
  svcA.method1();
 }
 
 @Test
 public void testB()
 {
  svcA.method2();
 }
 
 @Test(expected=RuntimeException.class)
 public void testC()
 {
  svcB.method3();
 }
 
 @Test
 public void testD()
 {
  svcB.method4();
 }
}

Yeah, I know I could have written these test methods a bit better, but I hope you got the idea.

Run the JUnit tests and observe the log statement to verify whether the method retry is happening in case of Exception or not.

Case#1: When invoking ServiceA.method1() is invoked MethodRetryHandlerAspect won't be applied at all.

Case#2: When invoking ServiceA.method2() is invoked, we are maintaining a counter and throwing NullPointerException for 2 times. But we have marked that method to ignore NullPointerExceptions. So it will continue to retry for 5 times. But 3rd time method will be executed normally and exits the method normally.

Case#3: When invoking ServiceB.method3() is invoked, we are throwing ArrayIndexOutOfBoundsException but that method is marked to ignore only IOException only. So this method execution won't be retried and throws the Exception immediately.

Case#4: When invoking ServiceB.method4() is invoked, everything is fine so it should exit in the first attempt itself normally.

I hope this example demonstrate a good enough real world usage of Spring AOP :-)

Monday, June 15, 2015

A Developers Perspective on Spring vs JavaEE

In Java community Spring vs JavaEE is a never ending debate. In such debates people form two groups consisting of evangelists, architects and hard core fans of one platform and debate endlessly. Those who participate in the debates may be architects who are responsible for platform selection. But what would developers think about this Spring vs JavaEE debate?

I am a Java developer who uses both Spring and JavaEE and I am not part of Spring or JavaEE fan club. Here I would like to share my own thoughts on this epic Spring vs JavaEE debate.

1. Business(sometimes political) Aspects
In many organizations technology selection may not completely depends on developers choice. More specifically if you are working in so called giant enterprise organizations there are high chances that there is an Architecture Team who will decide what platform/language/framework/libraries to use in the projects.

In addition to that, large enterprises also considers the following aspects while choosing the technology platform:

  • Maturity of the platform/language/framework/libraries
  • Commercial support
  • Licensing cost etc etc

As a developer I can hardly influence the decision making process for any of the above aspects, especially when I am a developer in offshore development center. So I don't worry too much about these things.

2. If you are really good at Spring/JavaEE then learning the other one shouldn't be difficult
I am always surprised when someone says I am JavaEE expert but I can't understand Spring or vice-versa. Both JavaEE and Spring work on the same core APIs (Servlet, JPA, JMS, BeanValidation etc), the difference is who is gluing the things together, Spring or AppServer.

Even though there are some different APIs for things like dependency injection (Spring DI, CDI), REST (JAX-RS, SpringMVC) etc they look and behave pretty similar to each other.

May be someone can say CDI is more typesafe than Spring DI. Doesn't Spring and CDI behaves similarly when:

  • Injection using @Autowired or @Inject works fine if there is only one Spring/CDI Bean
  • Injection fails when there are more than one Spring or CDI bean implementations by throwing errors saying "Found more than one eligible beans that can be inject"
  • Use @Produces or @Bean annotated method to provide custom made objects as bean providers

As long as they are behaving similarly I don't care whether they are implemented in more typesafe manner or used String based mappings in their internal implementations.

How can one be expert in Spring and can't understand JavaEE and vice-versa?? How much time it can take for a Spring expert to learn JavaEE??!!

3. Which is more "Average Joe developer" friendly
I think by now many people should have realized that success of a technology may not be completely depends on its merits, but also based on developers adoption. The most important thing to realize is "Not every software developer is a rock star developer. There are more average joe developers than passionate, tech ninjas". So in order to people adapt any framework it should be "Average Joe Developer" friendly.

I think Spring is doing pretty good job at it by providing more tools like SpringBoot, User Guides etc. Spring Security, Spring Integration, Spring XD, Spring Social addresses the modern business needs very well. Also think about various templates provided by Spring which makes easy to do things without worrying about boilerplate coding.

JavaEE is also doing very well by introducing JBossForge, Wildfly Swarm etc to quickly get started. I came across few JavaEE based frameworks like Picketlink which addresses Security requirements, but I felt it is much more complex than it should be.

The point I am trying to convey is "You can do pretty much everything in JavaEE that you can do with Spring". The difference is which is giving more out-of-the-box to average joe developer.

4. Lame arguments without context
Whenever Spring vs JavaEE debate arises people form two groups and debate endlessly.  Unfortunately the debates focus on some useless or outdated points.

XML heavy: 
JavaEE fans first start saying Spring is XML heavy and I hate XML blah blah blah. If you are still using Spring older than version 2.5 and assuming it is still same XML based then my friend you should wake up and head to http://spring.io

EJBs are bad (or) JSF is bad
Spring fans jump on to bashing EJB and JSF as if they are same as EJB 2.x or JSF 1.x. If they really look at EJB 3.x and JSF 2.x then they wouldn't argue on this at all. Don't judge EJB 3.x with your 6 years back EJB2.x experience.

Heavy weight or light weight
My interpretation of this 'weight' thing is based on runtime foot print. To my knowledge, when you deploy your managed beans into JavaEE container then container will proxy it and inject all enterprise services (Transactions, Security etc) and in case of Spring it will be done by Spring AOP.
I don't have any metrics to say which is more heavy weight Container Proxy or SpringAOP Proxy, but I guess there may not be significant difference.

Some people consider the size of war file as its 'weight'. In that case compare (JavaEE AppServer + war) size with (SpringApp with 126 jars) and see which is light weight :-)

JavaEE is standards based
Come on guys!!!!

Vendor lock-in
I think choosing a platform which doesn't make you stick with one particular vendor is good. But going with an option purely based on the ability to move to a different implementation is not correct. How many times in an year you switch from one server to another? Choosing a platform which doesn't lock you with a vendor is a 'nice to have' but it should not be major factor to choose your platform.

We don't need external libraries
This is called "Arguing for the sake of arguing". Show me any real application without having any dependencies. If you say I will develop my own logging library, I will write my own HTTP client, I will develop my own common-utilities then you need to look for a little bit more lazy architect/developers who doesn't have "Re-invent all the wheels" sickness.

5. Don't look at the crowd and say "You are all idiots because you are using X, you should migrate to Y".
This is a common pattern that I observe on many community sites, especially on Reddit. Just post anything related to JavaEE vs Spring thing and there will be two groups who bash the other group like anything because other group are not using their favorite platform.

Think for a minute. If Spring is not any good why so many people use it and love it. If JavaEE is not good why so many people switch from Spring to JavaEE. There is so many good things in each platform. Respect others for choosing whatever option they choose. If possible ask them the reasons why they went with one over the other and learn if you miss anything.

Just saying "You all are idiots for not using my favorite option" doesn't make them use your favorite technology. In fact it triggers the thought to come up with list of points why your favorite platform sucks.

If you really want them to switch to your favorite platform then show the reasons with code examples. Show them how easy it is to develop applications using your favorite platform with sample applications. Write more articles on commonly facing issues and how to resolve them. Get the "Average Joe Developer" on-board onto your favorite platform.

As an enthusiastic Java developer I read the Spring vs JavaEE discussions hoping there might be few things which I don't know such as "in which areas one is better than the other". But I find 70% of discussions goes on lame arguments which is not very interesting to me.

I wish Spring and JavaEE camps to fight more and more and made their platform superior than the other. End of the day, no matter who win the debate ultimately developers will have more powerful platforms.


Wednesday, July 2, 2014

SpringBoot: Introducing SpringBoot

SpringBoot...there is a lot of buzz about SpringBoot nowadays. So what is SpringBoot?

SpringBoot is a new spring portfolio project which takes opinionated view of building production-ready Spring applications by drastically reducing the amount of configuration required. Spring Boot is taking the convention over configuration style to the next level by registering the default configurations automatically based on the classpath libraries available at runtime.
Well.. you might have already read this kind of introduction to SpringBoot on many blogs. So let me elaborate on what SpringBoot is and how it helps developing Spring applications more quickly.

Spring framework was created by Rod Johnson when many of the Java developers are struggling with EJB 1.x/2.x for building enterprise applications. Spring framework makes developing the business components easy by using Dependency Injection and Aspect Oriented Programming concepts. Spring became very popular and many more Spring modules like SpringSecurity, Spring Batch, Spring Data etc become part of Spring portfolio. As more and more features added to Spring, configuring all the spring modules and their dependencies become a tedious task. Adding to that Spring provides atleast 3 ways of doing anything :-). Some people see it as flexibility and some others see it as confusing.

Slowly, configuring all the Spring modules to work together became a big challenge. Spring team came up with many approaches to reduce the amount of configuration needed by introducing Spring XML DSLs, Annotations and JavaConfig.

In the very beginning I remember configuring a big pile of jar version declarations in <properties> section and lot of <dependency> declarations. Then I learned creating maven archetypes with basic structure and minimum required configurations. This reduced lot of repetitive work, but not eliminated completely. 

Whether you write the configuration by hand or generate by some automated ways, if there is code that you can see then you have to maintain it.

So whether you use XML or Annotations or JavaConfig, you still need to configure(copy-paste) the same infrastructure setup one more time.

On the other hand, J2EE (which is dead long time ago) emerged as JavaEE and since JavaEE6 it became easy (compared to J2EE and JavaEE5) to develop enterprise applications using JavaEE platform.
Also JavaEE7 released with all the cool CDI, WebSockets, Batch, JSON support etc things became even more simple and powerful as well. With JavaEE you don't need so much XML configuration and your war file size will be in KBs (really??? for non-helloworld/non-stageshow apps also :-)).
Naturally this "convention over configuration" and "you no need to glue APIs together yourself, JavaEE appServer already did it" arguments became the main selling points for JavaEE over Spring. Then Spring team addresses this problem with SpringBoot :-).
Now its time to JavaEE to show whats the SpringBoot's counterpart in JavaEE land :-) JBoss Forge?? I love this Spring vs JavaEE thing which leads to the birth of powerful tools which ultimately simplify the developers life :-).

Many times we need similar kind of infrastructure setup using same libraries. For example, take a web application where you map DispatcherServlet url-pattern to "/", implement RESTFul webservices using Jackson JSON library with Spring Data JPA backend. Similarly there could be batch or spring integration applications which needs similar infrastructure configuration.

SpringBoot to the rescue. SpringBoot look at the jar files available to the runtime classpath and register the beans for you with sensible defaults which can be overridden with explicit settings. Also SpringBoot configure those beans only when the jars files available and you haven't define any such type of bean. Altogether SpringBoot provides common infrastructure without requiring any explicit configuration but lets the developer overrides if needed.

To make things more simpler, SpringBoot team provides many starter projects which are pre-configured with commonly used dependencies. For example Spring Data JPA starter project comes with JPA 2.x with Hibernate implementation along with Spring Data JPA infrastructure setup. Spring Web starter comes with Spring WebMVC, Embedded Tomcat, Jackson JSON, Logback setup.

Aaah..enough theory..lets jump onto coding.

I am using latest STS-3.5.1 IDE which provides many more starter project options like Facebbok, Twitter, Solr etc than its earlier version.

Create a SpringBoot starter project by going to File -> New -> Spring Starter Project -> select Web and Actuator and provide the other required details and Finish.


This will create a Spring Starter Web project with the following pom.xml and Application.java

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.sivalabs</groupId>
 <artifactId>hello-springboot</artifactId>
 <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

 <name>hello-springboot</name>
 <description>Spring Boot Hello World</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.1.3.RELEASE</version>
  <relativePath/>
 </parent>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>  
 </dependencies>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <start-class>com.sivalabs.springboot.Application</start-class>
  <java.version>1.7</java.version>
 </properties>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

</project>
package com.sivalabs.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Go ahead and run this class as a standalone Java class. It will start the embedded Tomcat server on 8080 port. But we haven't added any endpoints to access, lets go ahead and add a simple REST endpoint.
@Configuration
@ComponentScan
@EnableAutoConfiguration
@Controller
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    } 
 
 @RequestMapping(value="/")
 @ResponseBody
 public String bootup()
 {
  return "SpringBoot is up and running";
 }
}

Now point your browser to http://localhost:8080/ and you should see the response "SpringBoot is up and running".

Remember while creating project we have added Actuator starter module also. With Actuator you can obtain many interesting facts about your application. 

Try accessing the following URLs and you can see lot of runtime environment configurations that are provided by SpringBoot. 


SpringBoot actuator deserves a dedicated blog post to cover its vast number of features, I will cover it in my upcoming posts. 

I hope this article provides some basic introduction to SpringBoot and how it simplifies the Spring application development. More on SpringBoot in upcoming articles.

Tuesday, February 11, 2014

Book Review: Enterprise Application Development with Ext JS and Spring


I was asked to review "Enterprise Application Development with Ext JS and Spring" book by Packtpub guys and here is my review on the book. Actually now I am working on a project which is being developed using ExtJS and I thought of buying this book. But surprisingly on the very next day I was asked to review this book and gave me the ebook :-).



Book WebSite URL: http://www.packtpub.com/enterprise-application-development-with-extjs-and-spring/book

Personally I like the books which explains any technology/framework/library by taking a sample application and building the application progressively chapter by chapter. Enterprise Application Development with Ext JS and Spring book followed the same pattern and covered all levels of project development using Spring and ExtJS completely starting from Development environment setup with NetBeansIDE, Maven and Glassfish server to writing unit testing and building production ready ExtJS code using SenchaCmd.

We can find plenty of examples on Spring and ExtJS on the web, but the real challenge is stitching them together and building a real application. With this book you can build the bits and pieces (core services, UI components etc) and integrate them by following the step by step instructions as described in the book and finally create a working application.

The sample application "Task Time Tracker" is developed using Spring, JPA/EclipseLink and ExtJS. Each of these technologies are themselves huge topics and one can't cover all these topics indetail .
But the author did a fantastic job of explaining all the concepts using to build the application as much as possible.

Highlights:

  • Clear development environments steps for setting up JDK, NetbeansIDE, Maven and Glassfish, even novice users can get it done by simply following the steps.
  • You can build the application progressively chapter by chapter with proper flow, there no jumps or deviations from sequence.
  • Very detailed explanation on creating RESTful services using SpringMVC with JSON support.
  • Author explained writing JUnit tests for repositories and services with complete code examples encouraging to follow TDD.
  • Explained ExtJS MVC philosophy and build the Task Time Tracker application UI following MVC pattern.
  • Demonstrated how to use SenchaCmd to make the application production ready.


Overall I find it as a wonderful book to have if you are developing web applications using Spring/ExtJS. I would give 5 out of 5 star rating for this book.

Monday, May 27, 2013

Deploying BroadleafCommerce 2.0 on JBoss AS 7

First 2 steps are not really related to Broadleaf specific, but mentioned to make it easy to follow(copy/paste) the steps.

Step#1: Configure DataSources in JBoss AS.


<datasource jta="true" jndi-name="java:jboss/datasources/BroadleafDS" pool-name="BroadleafDS_Pool" enabled="true" use-java-context="true" use-ccm="true">
 <connection-url>jdbc:mysql://localhost:3306/broadleaf</connection-url>
 <driver>mysql</driver>
 <security>
  <user-name>root</user-name>
  <password>admin</password>
 </security>
 <timeout>
  <idle-timeout-minutes>0</idle-timeout-minutes>
  <query-timeout>600</query-timeout>
 </timeout>
</datasource>
<datasource jta="true" jndi-name="java:jboss/datasources/BroadleafSecureDS" pool-name="BroadleafSecureDS_Pool" enabled="true" use-java-context="true" use-ccm="true">
 <connection-url>jdbc:mysql://localhost:3306/broadleaf</connection-url>
 <driver>mysql</driver>
 <security>
  <user-name>root</user-name>
  <password>admin</password>
 </security>
 <timeout>
  <idle-timeout-minutes>0</idle-timeout-minutes>
  <query-timeout>600</query-timeout>
 </timeout>
</datasource>
<datasource jta="true" jndi-name="java:jboss/datasources/BroadleafCmsDS" pool-name="BroadleafCmsDS_Pool" enabled="true" use-java-context="true" use-ccm="true">
 <connection-url>jdbc:mysql://localhost:3306/broadleaf</connection-url>
 <driver>mysql</driver>
 <security>
  <user-name>root</user-name>
  <password>admin</password>
 </security>
 <timeout>
  <idle-timeout-minutes>0</idle-timeout-minutes>
  <query-timeout>600</query-timeout>
 </timeout>
</datasource>

Step#2: Update core/src/main/resources/META-INF/persistence.xml as follows to use DataSources configured in JBossAS7.

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
             version="2.0">
             
    <persistence-unit name="blPU" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafDS</non-jta-data-source>
        <exclude-unlisted-classes/>
    </persistence-unit>
    
    <persistence-unit name="blSecurePU" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafSecureDS</non-jta-data-source>
        <exclude-unlisted-classes/>
    </persistence-unit>

    <persistence-unit name="blCMSStorage" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafCmsDS</non-jta-data-source>
        <exclude-unlisted-classes/>
    </persistence-unit>
</persistence>

Step#3: Update site/src/main/webapp/WEB-INF/applicationContext.xml as follows:

<bean id="blMergedDataSources" class="org.springframework.beans.factory.config.MapFactoryBean">
 <property name="sourceMap">
  <map>
   <entry key="java:jboss/datasources/BroadleafDS" value-ref="webDS"/>
   <entry key="java:jboss/datasources/BroadleafSecureDS" value-ref="webSecureDS"/>
   <entry key="java:jboss/datasources/BroadleafCmsDS" value-ref="webStorageDS"/>
  </map>
 </property>
</bean>

Now if you deploy the app you will get the following error:

ERROR Error creating bean with name 'blMergedDataSources' defined in resource loaded from byte array: Cannot resolve reference to bean 'webDS' while setting bean property 'sourceMap' with key [TypedStringValue: value [java:jboss/datasources/BroadleafDS], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webDS': Post-processing of the FactoryBean's object failed; nested exception is java.lang.IllegalArgumentException: warning no match for this type name: org.broadleafcommerce.profile.core.service.CustomerAddressService [Xlint:invalidAbsoluteTypeName]

 Step#4: Create jboss-deployment-structure.xml in site/src/main/webapp/WEB-INF/ folder.


<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
   <deployment>
      <dependencies>
         <module name="org.jboss.ironjacamar.jdbcadapters" />
      </dependencies>
      <exclusions>
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.log4j"/>
            <module name="org.jboss.logging"/>
            <module name="org.jboss.logmanager"/>
            <module name="org.jboss.logmanager.log4j"/>
            <module name="org.slf4j"/>
      </exclusions>
   </deployment>
</jboss-deployment-structure>

Now if you try to deploy the app you will get the following error because JBossAS7 comes with Hibernate4 and application is using some hibernate3 features.

 @CollectionOfElements
 @JoinTable(name = "BLC_CATEGORY_IMAGE", joinColumns = @JoinColumn(name = "CATEGORY_ID"))
 @MapKey(columns = { @Column(name = "NAME", length = 5, nullable = false) })
 @Column(name = "URL")
 @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
 @BatchSize(size = 50)
 @Deprecated
 protected Map<String, String> categoryImages = new HashMap<String, String>(10);

org.hibernate.MappingException: Could not determine type for: java.util.Map, at table: BLC_CATEGORY, for columns: [org.hibernate.mapping.Column(URL)] 

So let us install hibernate3 module in JBossAS7 and use it.

Step#5: Install Hibernate 3 module in JBoss AS 7. 

Copy the following jars(you can get these from site.war file) into jboss-as-7.1.1.FINAL/modules/org/hibernate/3/ folder.

 antlr-2.7.6.jar
 commons-collections-3.2.1.jar
 dom4j-1.6.1.jar
 hibernate-commons-annotations-3.2.0.Final.jar
 hibernate-core-3.6.10.Final.jar
 hibernate-entitymanager-3.6.10.Final.jar
 javassist-3.16.1-GA.jar 

Create module.xml in jboss-as-7.1.1.FINAL/modules/org/hibernate/3/ folder.

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.hibernate" slot="3">
    <resources>
        <resource-root path="hibernate-core-3.6.10.Final.jar"/>  
        <resource-root path="javassist-3.16.1-GA.jar"/>
        <resource-root path="antlr-2.7.6.jar"/>  
        <resource-root path="commons-collections-3.2.1.jar"/>  
        <resource-root path="dom4j-1.6.1.jar"/>  
        <!-- Insert other Hibernate 3 jars to be used here -->
  <resource-root path="hibernate-commons-annotations-3.2.0.Final.jar"/>
  <resource-root path="hibernate-entitymanager-3.6.10.Final.jar"/>
    </resources>
    <dependencies>
        <module name="org.jboss.as.jpa.hibernate" slot="3"/>
        <module name="asm.asm"/>
        <module name="javax.api"/>
        <module name="javax.persistence.api"/>
        <module name="javax.transaction.api"/>
        <module name="javax.validation.api"/>
        <!-- <module name="org.apache.ant"/> -->
        <module name="org.infinispan" optional="true"/>
        <module name="org.javassist"/>
        <module name="org.slf4j"/>
    </dependencies>
</module>

Step#6: Tell JBoss to use hibernate 3 module. Update core/src/main/resources/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
             version="2.0">
 <persistence-unit name="blPU" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafDS</non-jta-data-source>
        <exclude-unlisted-classes/>
        <properties>
         <property name="jboss.as.jpa.providerModule" value="org.hibernate:3" />
         <property name="jboss.as.jpa.managed" value="false" />
        </properties>
    </persistence-unit>
    
    <persistence-unit name="blSecurePU" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafSecureDS</non-jta-data-source>
        <exclude-unlisted-classes/>
        <properties>
         <property name="jboss.as.jpa.providerModule" value="org.hibernate:3" />
         <property name="jboss.as.jpa.managed" value="false" />
        </properties>
    </persistence-unit>

    <persistence-unit name="blCMSStorage" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:jboss/datasources/BroadleafCmsDS</non-jta-data-source>
        <exclude-unlisted-classes/>
        <properties>
         <property name="jboss.as.jpa.providerModule" value="org.hibernate:3" />
         <property name="jboss.as.jpa.managed" value="false" />
        </properties>
    </persistence-unit>
</persistence>
Enjoy :-)

Monday, October 29, 2012

A bunch of Maven Archetypes for Spring based Projects


Maven is a good project management tool which greatly reduces the amount of time we spend on creating java projects with proper structure. With so many predefined maven archetypes it is even easier to create projects by simply selecting the archetype based on the technologies we need and type(jar/war/ear) of project we want to create.

However sometimes those predefined archetypes structure may not suite well for our needs or we may need some more additions to the pre-configured dependencies/frameworks etc.

Also in Eclipse the default java compiler level is 1.5 and configuring it to 1.6 every time is frustrating.
So I thought of creating some custom archetypes for the most common combination of technologies/frameworks that I frequently use.

Yes, I am aware of AppFuse which provides lot more maven archetypes. But the structure I follow is a bit different, so I thought of creating archetypes which suites my needs/style :-)

Most of my projects are Spring based applications, so I have created the following templates so far:

1. Quickstart Java App : 
A Simple Java Application with JDK 1.6, SLF4J(Logback/Log4J) and failsafe plugin configuration.

2. Quickstart Web App:
A Simple Web Application with JDK 1.6, Servlet 2.5, SLF4J(Logback/Log4J) and failsafe plugin configuration.

3. Quickstart Spring App: 
A Java project with Spring 3.1.x, MySQL, JdbcTemplate and Log4j/Logback configuration.

4. Quickstart SpringMVC App: 
A Web project with SpringMVC 3.1.x,MySQL, JdbcTemplate, jQuery and Log4j/Logback configuration.

5. Quickstart SpringMVC-Tiles-SpringSecurity App: 
A Web project with SpringMVC 3.1.x, Apache Tiles, SpringSecurity 3.1.x, jQuery and Log4j/Logback configuration.

6. Quickstart SpringMVC-SiteMesh-SpringSecurity App: 
A Web project with SpringMVC 3.1.x, SiteMesh 2.x, SpringSecurity 3.1.x, jQuery and Log4j/Logback configuration.

7. Quickstart SpringMVC-JPA2(Hibernate) App:
A Web project with SpringMVC 3.1.x, JPA2(Hibernate4.x), SpringDataJPA, Apache Tiles, jQuery, SpringSecurity and Log4j/Logback configuration.

8. Quickstart SpringMVC-MyBatis App:
A Web project with SpringMVC 3.1.x, MyBatis, jQuery and Log4j/Logback configuration.

9. Quickstart Spring-JSF2(PrimeFaces)-JPA2(Hibernate) App:
A Web project with Spring 3.1.x, JSF2(PrimeFaces), JPA2(Hibernate),SpringDataJPA and Log4j/Logback configuration.


These are the archetypes so far I have completed and uploaded them onto my GitHub repository https://github.com/sivaprasadreddy/maven-archetype-templates

I have mentioned how to install them in your local repository in README file.

I am planning for writing some more template archetypes including SpringRESTFul Services, Spring-ApacheCXF App, Spring Integration, Spring-JavaEE6 etc.
Stay tuned :-)

Wednesday, October 24, 2012

MyBatis Tutorial : Part4 - Spring Integration



MyBatis Tutorial: Part1 - CRUD Operations
MyBatis Tutorial: Part-2: CRUD operations Using Annotations
MyBatis Tutorial: Part 3 - Mapping Relationships
MyBatis Tutorial : Part4 - Spring Integration

MyBatis-Spring is a subproject of MyBatis and provides Spring integration support which drastically simplifies the MyBatis usage. For those who are familiar with Spring's way of Dependency Injection process, using MyBatis-Spring is a very simple.

First let us see the process of using MyBatis without Spring.

1. Create SqlSessionFactory using SqlSessionFactoryBuilder by passing mybatis-config.xml which contains DataSource properties, List of Mapper XMLs and TypeAliases etc.

2. Create SqlSession object from SqlSessionFactory

3. Get Mapper instance from SqlSession and execute queries.

4. Commit or rollback the transaction using SqlSession object.

With MyBatis-Spring, most of the above steps can be configured in Spring ApplicationContext and SqlSession or Mapper instances can be injected into Spring Beans. Then we can use Spring's TransactionManagement features without writing transaction commit/rollback code all over the code.


Now let us see how we can configure MyBatis+Spring integration stuff.

Step#1: Configure MyBatis-Spring dependencies in pom.xml
  
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.10</version>
   <scope>test</scope>
  </dependency>
  
  <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.1.1</version>
  </dependency>
  <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.1.1</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>3.1.1.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>3.1.1.RELEASE</version>
   <scope>test</scope>
  </dependency>
  <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.21</version>
             <scope>runtime</scope>
         </dependency>
  <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib-nodep</artifactId>
   <version>2.2.2</version>
  </dependency>


Step#2: You don't need to configure Database properties in mybatis-config.xml.

We can configure DataSource in Spring Container and use it to build MyBatis SqlSessionFactory.

Instead of SqlSessionFactoryBuilder, MyBatis-Spring uses org.mybatis.spring.SqlSessionFactoryBean to build SqlSessionFactory.

We can pass dataSource, Mapper XML files locations, typeAliases etc to SqlSessionFactoryBean.


 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <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>
 
 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="typeAliasesPackage" value="com.sivalabs.mybatisdemo.domain"/>
    <property name="mapperLocations" value="classpath*:com/sivalabs/mybatisdemo/mappers/**/*.xml" />
 </bean>

Step#3: Configure SqlSessionTemplate which provides ThreadSafe SqlSession object.

 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
   <constructor-arg index="0" ref="sqlSessionFactory" />
 </bean>

Step#4: To be able to inject Mappers directly we should register org.mybatis.spring.mapper.MapperScannerConfigurer and configure the package name where to find Mapper Interfaces.

 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
   <property name="basePackage" value="com.sivalabs.mybatisdemo.mappers" />
 </bean>

Step#5: Configure TransactionManager to support Annotation based Transaction support.
 
 <tx:annotation-driven transaction-manager="transactionManager"/>
 
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
 </bean>

Step#6: Update the Service classes and register them in Spring container.

package com.sivalabs.mybatisdemo.service;

import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sivalabs.mybatisdemo.domain.User;
import com.sivalabs.mybatisdemo.mappers.UserMapper;

@Service
@Transactional
public class UserService
{
 @Autowired
 private SqlSession sqlSession; //This is to demonstrate injecting SqlSession object
 
 public void insertUser(User user) 
 {
  UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  userMapper.insertUser(user);
 }

 public User getUserById(Integer userId) 
 {
  UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  return userMapper.getUserById(userId);
 }
 
}
package com.sivalabs.mybatisdemo.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sivalabs.mybatisdemo.domain.Blog;
import com.sivalabs.mybatisdemo.mappers.BlogMapper;

@Service
@Transactional
public class BlogService
{
 @Autowired
 private BlogMapper blogMapper; // This is to demonstratee how to inject Mappers directly
 
 public void insertBlog(Blog blog) {
  blogMapper.insertBlog(blog);
 }
 
 public Blog getBlogById(Integer blogId) {
  return blogMapper.getBlogById(blogId);
 }
 
 public List<Blog> getAllBlogs() {
  return blogMapper.getAllBlogs();
 }
}

Note: When we can directly inject Mappers then why do we need to inject SqlSession objects? Because SqlSession object contains more fine grained method which comes handy at times.

For Example: If we want to get count of how many records got updated by an Update query we can use SqlSession as follows:
int updatedRowCount = sqlSession.update("com.sivalabs.mybatisdemo.mappers.UserMapper.updateUser", user);
So far I didn't find a way to get the row update count without using SqlSession object.

PS: You can have your interface insert/update/delete methods returning int, then MyBatis returns the number of records updated as an integer.

Step#7 Write JUnit Tests to test UserService and BlogService.


package com.sivalabs.mybatisdemo;

import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sivalabs.mybatisdemo.domain.User;
import com.sivalabs.mybatisdemo.service.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringUserServiceTest 
{
 @Autowired
 private UserService userService;
 
    @Test
 public void testGetUserById() 
 {
  User user = userService.getUserById(1);
  Assert.assertNotNull(user);
  System.out.println(user);
  System.out.println(user.getBlog());
 }
        
    @Test
    public void testUpdateUser() 
    {
     long timestamp = System.currentTimeMillis();
  User user = userService.getUserById(2);
  user.setFirstName("TestFirstName"+timestamp);
     user.setLastName("TestLastName"+timestamp);
     userService.updateUser(user);
  User updatedUser = userService.getUserById(2);
  Assert.assertEquals(user.getFirstName(), updatedUser.getFirstName());
  Assert.assertEquals(user.getLastName(), updatedUser.getLastName());
 }
    
}
package com.sivalabs.mybatisdemo;

import java.util.Date;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sivalabs.mybatisdemo.domain.Blog;
import com.sivalabs.mybatisdemo.domain.Post;
import com.sivalabs.mybatisdemo.service.BlogService;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringBlogServiceTest 
{
 @Autowired
 private BlogService blogService;
 
 @Test
 public void testGetBlogById() 
 {
  Blog blog = blogService.getBlogById(1);
  Assert.assertNotNull(blog);
  System.out.println(blog);
  List<Post> posts = blog.getPosts();
  for (Post post : posts) {
   System.out.println(post);
  }
 }
    
    @Test
    public void testInsertBlog() 
    {
     Blog blog = new Blog();
     blog.setBlogName("test_blog_"+System.currentTimeMillis());
     blog.setCreatedOn(new Date());
     
     blogService.insertBlog(blog);
  Assert.assertTrue(blog.getBlogId() != 0);
  Blog createdBlog = blogService.getBlogById(blog.getBlogId());
  Assert.assertNotNull(createdBlog);
  Assert.assertEquals(blog.getBlogName(), createdBlog.getBlogName());
  
 }
    
}

Friday, October 12, 2012

Spring3+JPA2+JavaEE6AppServer = Confusion Over Configuration

Spring is great, JavaEE6 is great and latest JavaEE6 Application servers are also great. This post is not a rant on Spring Vs JavaEE6, but my experience of porting a Spring3+JPA2(Hibernate) application on JBoss AS-7.1 App Server.

My application requirement is very simple: Developing a couple of SOAP based webservices using Spring3.1 and JPA2(Hibernate) and host it on JBoss AS 7.1.

So I started creating a multi-module maven project with one jar module containing the service implementations using Spring & JPA and another war module which exposes those services as SOAP based webservices. But the key part is services needs to talk to multiple databases for some of the service methods.

 I am aware of JPA2 integration support from Spring without persistence.xml and cool packagesToScan attribute which makes life a bit easier. I configured 2 dataSources, 2 LocalContainerEntityManagerFactoryBeans, registered 2 JpaTransactionManagers and enabled Annotation based Transaction Management Support.


	<tx:annotation-driven transaction-manager="txnManager1"/>
	<tx:annotation-driven transaction-manager="txnManager2"/>
	
	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/><!-- This will throw error because it found multiple EntityManagerFactory beans -->
	
	<bean id="txnManager1" 
			class="org.springframework.orm.jpa.JpaTransactionManager"
       		p:entityManagerFactory-ref="emf1"/>
    
    <bean id="txnManager2" 
			class="org.springframework.orm.jpa.JpaTransactionManager"
       		p:entityManagerFactory-ref="emf2"/>       		
       
    <bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs1PU"></property>       	
       	<property name="dataSource" ref="dataSource1"></property>
       	<property name="jpaVendorAdapter">
       		<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
         			p:showSql="${hibernate.show_sql}"/>
       	</property>
       	<property name="jpaProperties">
       		<props>
       			<prop key="hibernate.dialect">${hibernate.dialect}</prop>
       			<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
       		</props>
       	</property>
       	<property name="packagesToScan" value="com.sivalabs.springdemo.entities"></property>
       	<property name="loadTimeWeaver">
          <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
        
    </bean> 
    
   	<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs2PU"></property>
       	<property name="dataSource" ref="dataSource2"></property>
       	<property name="jpaVendorAdapter">
       		<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
         			p:showSql="${hibernate.show_sql}"/>
       	</property>
       	<property name="jpaProperties">
       		<props>
       			<prop key="hibernate.dialect">${hibernate.dialect}</prop>
       			<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
       		</props>
       	</property>
       	<property name="packagesToScan" value="com.sivalabs.springdemo.entities"></property>
       	<property name="loadTimeWeaver">
          <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
        
    </bean> 
	
	<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${node1.jdbc.driverClassName}"></property>
		<property name="url" value="${node1.jdbc.url}"></property>
		<property name="username" value="${node1.jdbc.username}"></property>
		<property name="password" value="${node1.jdbc.password}"></property>
	</bean>
	
	<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${node2.jdbc.driverClassName}"></property>
		<property name="url" value="${node2.jdbc.url}"></property>
		<property name="username" value="${node2.jdbc.username}"></property>
		<property name="password" value="${node2.jdbc.password}"></property>
	</bean>

After this I realized to bind Entitymanager with the correct PersistenceUnit I need to give persistenceUnitName to LocalContainerEntityManagerFactoryBean.

	
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
		<property name="persistenceUnits" >
	     <map>
	       <entry key="unit1" value="Sivalabs1PU"/>
	       <entry key="unit2" value="Sivalabs2PU"/>
	     </map>
		</property>
	</bean>
	
	<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs1PU"></property>
       	<property name="dataSource" ref="dataSource1"></property>
       	....
		....        
    </bean> 
    
   	<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs2PU"></property>
       	<property name="dataSource" ref="dataSource2"></property>
        ....
		....        
    </bean>

Then in my Service Bean EntityManagers and transaction managers are glued together as follows:

@Service
public class AdminUserService implements UserService
{
	@PersistenceContext(unitName="Sivalabs1PU")
	private EntityManager sivalabs1EM;
	@PersistenceContext(unitName="Sivalabs2PU")
	private EntityManager sivalabs2EM;
	
	@Override
	@Transactional("txnManager1")
	public List<User> getAllUsersFromSivalabs1DB() {
		return sivalabs1EM.createQuery("from User", User.class).getResultList();
	}

	@Override
	@Transactional("txnManager2")
	public List<User> getAllUsersFromSivalabs2DB() {
		return sivalabs2EM.createQuery("from User", User.class).getResultList();
	}
	
}

With this setup now I got the Exception saying "No persistence unit with name 'Sivalabs1PU' found".

Then after some googling I created  META-INF/persistence.xml file as follows:



<persistence>

   <persistence-unit name="Sivalabs1PU" transaction-type="RESOURCE_LOCAL">   		
   </persistence-unit>
   
   <persistence-unit name="Sivalabs2PU"  transaction-type="RESOURCE_LOCAL">   		
   </persistence-unit>
   
</persistence>

Now the persistence unit name error got resolved and got other Exception saying "User is not mapped [from User]". The User class is annotated with @Entity and is in "com.sivalabs.springdemo.entities" package which I configured to "packagesToScan" attribute. I didn't understand why "packagesToScan" attribute is not working which is working fine without persistence.xml. So for time being I configured entity classes in persistence.xml file.

<persistence>

   <persistence-unit name="Sivalabs1PU" transaction-type="RESOURCE_LOCAL">   	
		<class>com.sivalabs.springdemo.entities.User</class>   
   </persistence-unit>
   
   <persistence-unit name="Sivalabs2PU"  transaction-type="RESOURCE_LOCAL">   	
		<class>com.sivalabs.springdemo.entities.User</class>
   </persistence-unit>
   
</persistence>

Finally when I ran my JUnit Test which invokes AdminUserService methods everything looks good and working fine. Then I deployed the war file on JBoss AS 7.1 Server then again got a bunch of errors. JBoss is complaining that "Connection cannot be null when 'hibernate.dialect' not set" .... "[PersistenceUnit: Sivalabs1PU] Unable to build EntityManagerFactory".

After thinking for a couple of minutes, I understood that JBoss server is trying to do what it is supposed to do with "Convention Over Configuration" rules. JBoss is trying to create EntityManagerFactory because it found META-INF/persistence.xml in classpath. But as it doesn't contain jdbc connection details its throwing Error. 

Again after some googling I found we can rename persistence.xml to something else(spring-persistence.xml) and hook up this new name with Spring as follows:

	<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs1PU"></property>
		<property name="persistenceXmlLocation" value="classpath:META-INF/spring-persistence.xml"/>
       	<property name="dataSource" ref="dataSource1"></property>
       	....
		....        
    </bean> 
    
   	<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       	<property name="persistenceUnitName" value="Sivalabs2PU"></property>
		<property name="persistenceXmlLocation" value="classpath:META-INF/spring-persistence.xml"/>
       	<property name="dataSource" ref="dataSource2"></property>
        ....
		....        
    </bean>

Finally I got this application working on my JBoss AS 7.1 successfully(Still I don't know how many other holes are there that I haven't yet found).

But here I didn't understand few Spring concepts:
1. When I try to give persistenceUnitName why Spring is checking for that name to be existed in persistence.xml? Anyway that persistence.xml doesn't contain anything exception the unit-name!!

2. Why packagesToScan mechanism is failing when used with persistence.xml? Is it a Spring Bug?

Everything seems to be working fine except one thing is missing, a smile on my face which usually I have when working with Spring and Tomcat :-(

I like Spring framework very much and I am using it since 2006 and I do enjoy while writing Spring code. That doesn't mean I don't like CDI, EJB3, JAX-RS :-)

 Anyway, with all the above exercise I feel like Spring3+JPA2+JavaEE6AppServer=Confusion Over Configuration and it is my(an average java developer) opinion only.

Again say one more time : Spring is great, JavaEE6 is great and latest JavaEE6 Application servers are also great :-).

Tuesday, June 19, 2012

How I explained Dependency Injection to My Team

Recently our company started developing a new java based web application and after some evaluation process we decided to use Spring.

But many of the team members are not aware of Spring and Dependency Injection principles.
So I was asked to give a crash course on what is Dependency Injection and basics on Spring.

Instead of telling all the theory about IOC/DI I thought of explaining with an example.

Requirement: We will get some Customer Address and we need to validate the address.
After some evaluation we thought of using Google Address Validation Service.

 Legacy(Bad) Approach:

Just create an AddressVerificationService class and implement the logic.

Assume GoogleAddressVerificationService is a service provided by Google which takes Address as a String and Return longitude/latitude.

class AddressVerificationService 
{
   public String validateAddress(String address)
 {
 GoogleAddressVerificationService gavs = new GoogleAddressVerificationService();
  String result = gavs.validateAddress(address);  
  return result;
 }
}

Issues with this approach: 
 1. If you want to change your Address Verification Service Provider you need to change the logic.
 2. You can't Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 Due to some reason Client ask us to support multiple AddressVerificationService Providers and we need to determine which service to use at runtime.

To accomidate this you may thought of changing the above class as below:

class AddressVerificationService
{
//This method validates the given address and return longitude/latitude details.
 public String validateAddress(String address)
 {
  String result = null;
  int serviceCode = 2; // read this code value from a config file
  if(serviceCode == 1)
  {
   GoogleAddressVerificationService googleAVS = new GoogleAddressVerificationService();
   result = googleAVS.validateAddress(address);
  } else if(serviceCode == 2)
  {
   YahooAddressVerificationService yahooAVS = new YahooAddressVerificationService();
   result = yahooAVS.validateAddress(address);
  }
  return result;
 }
}

Issues with this approach: 


1. Whenever you need to support a new Service Provider you need to add/change logic using if-else-if.
 2. You can't Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 IOC/DI Approach: 

 In the above approaches AddressVerificationService is taking the control of creating its dependencies.
 So whenever there is a change in its dependencies the AddressVerificationService will change.

 Now let us rewrite the AddressVerificationService using IOC/DI pattern.

 class AddressVerificationService
 {
  private AddressVerificationServiceProvider serviceProvider;
  
  public AddressVerificationService(AddressVerificationServiceProvider serviceProvider) {
   this.serviceProvider = serviceProvider;
  }
  
  public String validateAddress(String address)
  {
   return this.serviceProvider.validateAddress(address);
  }
 }
 
 interface AddressVerificationServiceProvider
 {
  public String validateAddress(String address);
 }
 

Here we are injecting the AddressVerificationService dependency AddressVerificationServiceProvider.

Now let us implement the AddressVerificationServiceProvider with multiple provider services.

 class YahooAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using YAHOO AddressVerificationService");
   return yahooAVSAPI.validate(address);
  }  
 }

 class GoogleAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using Google AddressVerificationService");
   return googleAVSAPI.validate(address);
  }
 }
 
Now the Client can choose which Service Provider's service to use as follows:

 AddressVerificationService verificationService = null;
 AddressVerificationServiceProvider provider = null;
 provider = new YahooAVS();//to use YAHOO AVS
 provider = new GoogleAVS();//to use Google AVS
 
 verificationService = new AddressVerificationService(provider);
 String lnl = verificationService.validateAddress("HitechCity, Hyderabad");
 System.out.println(lnl);
 

For Unit Testing we can implement a Mock AddressVerificationServiceProvider.

 class MockAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using MOCK AddressVerificationService");
   return "<response><longitude>123</longitude><latitude>4567</latitude>";
  }
 }
 
 AddressVerificationServiceProvider provider = null;
 provider = new MockAVS();//to use MOCK AVS  
 AddressVerificationServiceIOC verificationService = new AddressVerificationServiceIOC(provider);
 String lnl = verificationService.validateAddress("Somajiguda, Hyderabad");
 System.out.println(lnl);
 

With this approach we elemenated the issues with above Non-IOC/DI based approaches.
 1. We can provide support for as many Provides as we wish. Just implement AddressVerificationServiceProvider and inject it.
 2. We can unit test using Dummy Data using Mock Implementation.


So by following Dependency Injection principle we can create interface-based loosely-coupled and easily testable services.

Tuesday, June 12, 2012

RESTEasy Tutorial Part 3 - Exception Handling


RESTEasy Tutorial Series

RESTEasy Tutorial Part-1: Basics

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy Tutorial Part 3 - Exception Handling

Exception Handling is an obvious requirement while developing software application. If any error occured while processing user request we should show the user an error page with details like brief exception message, error code(optional), hints to correct the input and retry(optional) and actual root cause(optional). This is applicable to RESTful web services also.

But putting try-catch-finally blocks all around the code is not a good practice. We should design/code in such a way that if there is any unrecoverable error occured then the code should throw that exception and there should an exception handler to catch those exceptions and extract the error details and give a proper error response to the client with all the error details.

RESTEasy provides such ExceptionHandler mechanism which simplifies the ExceptionHandling process.

In this part I will show you how we can use RESTEasy's ExceptionHandlers to handle Exceptions.

Step#1: Create Application Specific Exceptions.
Step#2: Create ExceptionHandlers by implementing ExceptionMapper interface.

Step#3: Update UserResource.getUserXMLById() method to validate user input and throw respective exceptions.

Step#4: Test the UserResource.getUserXMLById() service method by issueing following requests.



Important things to note:
As Spring is creating the necessary objects we should let Spring know about @Provider classes to get them registered with RESTEasy. We can do this in two ways.

a)Annotate Provider classes with @Component

b)Using component-scan's include-filter.

<context:component-scan base-package="com.sivalabs.springdemo">
         <context:include-filter expression="javax.ws.rs.ext.Provider" type="annotation"/>
</context:component-scan>

Wednesday, June 6, 2012

RESTEasy Tutorial Part-2: Spring Integration


RESTEasy Tutorial Series

RESTEasy Tutorial Part-1: Basics

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy Tutorial Part 3 - Exception Handling


RESTEasy provides support for Spring integration which enables us to expose Spring beans as RESTful WebServices.

Step#1: Configure RESTEasy+Spring dependencies using Maven.



Step#2: Configure RESTEasy+Spring in web.xml



Step#3: Create a Spring Service class UserService and update UserResource to use UserService bean.


Step#4: Same JUnit TestCase to test the REST Webservice described in Part-1.

Important Things to Keep in mind:
1. org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap Listener should be registered before any other listener.

2. You should configure resteasy.servlet.mapping.prefix <context-param> if the HttpServletDispatcher servlet url-pattern is anything other than /*

3. While using Spring integration set resteasy.scan to false or don't configure resteasy.scan parameter at all.
    Otherwise you may get REST Resource instances(UserResource) from RestEasy instead of Spring container. While running JUnit Tests I observed this random behavior.

4. You should register REST Resource as Spring bean by annotating with @Component or @Service.

Monday, April 9, 2012

What additional features do JavaEE6 have to move from Spring?

I am a senior java developer who has to work on the technologies chosen by the application architect.
At the maximum I can express my opinion on a particular technology, I can't make/influence technology selection decision. So I don't have a choice of moving from Spring to JavaEE6 or from JavaEE6 to Spring on my official projects.

I strongly believe that as a Java developer I have to keep updated on (at least few) latest technologies.
So I(many java developers) generally follow java community websites or blogs to have an idea on whats going on in java community. Specifically I do follow updates from some Java Champions or well known popular authors because they might have better vision on what is next big thing in Java space.

Few years back I have seen so many people talking about Spring. Then I started learning Spring and still I just love it. I have been using JavaEE5 for a couple of years and I didn't find any feature which Spring is not providing. But recently I am seeing so many articles on "Moving from Spring to JavaEE6" for every couple of days. So I thought of giving it a try, I installed NetBeans7.1, Glassfish3.1 and did a simple POC. Its wonderful, I am able to write a simple app in just 10 min.
Yes, JavaEE6 improved a lot over it predecessors.

But again I am not seeing anything new which I can't do with Spring.
OK, let me share my thoughts on the criteria that is chosen by "Moving from Spring to JavaEE6" article authors.

1. So many Jars in WEB-INF/lib
Spring application has its dependencies in WEB-INF/lib and JavaEE6 app will have in server lib.
Even for Spring app, we don't need to go and manually download all those Jars, we can use Maven/Ivy or even we can start with an archetype template with all dependencies configured. And its only onetime Job.
I am not sure will there be any performance improvement by having jars in server lib instead of WEB-INF/lib. If that is the case we can place Spring app dependencies in server lib.

What I am missing here?

2. Type-safe Dependency Injection
From Spring 2.5 we have annotation based DI support using @Autowired and if you are still saying Spring is XML based please take a look at Spring 3.x.
If you want to give a custom-name to spring bean(in case of multiple implementation for same Interface), you can.
How is it different from JavaEE6's CDI @Injext and @Named?

3. Convention Over Configuration
EJB3 methods are transactional by default, just slap it with @Stateless.
In Spring we can create a custom StereoType, say @TransactionalServe, like

@Service
@Transactional
public @interface TransactionalServe
{

}
and we can achieve Convention Over Configuration.
Did I miss anything here?

4. Spring depends on JavaEE
Of course Spring depends on JavaSE and JavaEE. Spring is just making the development easier.
You can always use JavaEE APIs like JSF, JPA, JavaMail etc with Spring in easier way.
Did anybody said Spring came to completely vanish JavaEE?? No.

5. Standards based, App Server Support, License blah blah blah.
These are the things that developers don't have much(any) control.
From a developer perspective, we love whatever makes development easier.

So I am not seeing any valid reason to migrate an existing Spring app to JavaEE6. Till now I didn't find one thing which CDI can do and Spring can't do. For green field projects just to have depency injection we might not need Spring as we already have CDI in-built in JavaEE6.

Does JavaEE6 address any of the following:
1. Batch Processing: Almost all the big enterprises have some batch jobs to run. Does JavaEE6 have any support for implementing them.
Do you suggest to use Spring Batch or start from scratch in vanilla JavaEE6.
2. Social Network Integration: These days it became very common requirement for web apps to integrate with Social Network sites.
Again what do you have in JavaEE6 for this?
3. Environment Profiles: In Spring I can have my mock services enabled in Testing profile and my real services in Production profile.
I am aware of @Alternative, but can we configure more than 2 Alternatives without using String based injection?
4. Web application Security: What is Spring-security's counter part in JavaEE6?
5. What about integration with NoSQL, Flex, Mobile development etc?

JavaEE6 got CDI now, so suddenly Spring become legacy!!!!

Conclusion: Yeah JavaEE6 has cool stuff now(lately??) but it is not going to replace Spring anyway. Long live Spring.

Wednesday, November 23, 2011

Why I love Spring and I hate JBoss technologies

I am using Spring framework for the last 3 years and I am very happy while working with Spring.
In the very beginning when I started learning Spring I felt like "OMG, without doing much by myself I am getting so much of functionality".

Once I configure basic infrastructure setup like DataSource, JMS, Email Config etc I am able to perform the actual tasks like database operations or sending emails using Templates very easily. I just liked Spring framework magic even without fully understanding how it works.

Later I started digging into internals of Spring by looking at the source code and got a fair idea on Spring framework and I just loved it and now I addicted to Spring.

When I asked myself what makes me to like Spring so much I got the following reasons:

1. The most important reason for why I like Spring so much is its least surprise principle. In most of the times Spring behaves as expected and as documented in its reference documentation. For the beginners Spring has a number of sample applications for each of its modules like Spring core, MVC, Spring Data JPA etc. They just work fine. You run the Maven build and run the application it just work as expected.

2. Detailed error descriptions. When Spring throws an error it will give you very detailed description about why the error occurred. This saves a lot of time and allows the developers to proceed further without getting frustrated in the beginning itself.
  
3. Spring is moving towards the future(unlike JavaEE trying to catch the present).
   Recently I spent sometime on Groovy and Grails and they are amazing. We all know Spring is the underlying technology on which Grails is built.

   Suppose if an application can be developed by writing 1000 lines of code with Spring we can develop with 250 lines of code and with Grails we can finish it in 100 lines.

   Of course the number of lines is not a good metric to evaluate the quality of a framework, what I am saying is Grails already had built in support for the regular use cases. For example we can develop Rich User Interfaces using RichUI plugin very easily.
  
I can list down other 100 reasons why I like it so much but these are the immediate things that comes to my mind.

Now why I hate JBoss:

Long time back I got to work on JSF1.x and at that time I tried to change my platform from Java to anything else which doesn't have JSF :-). But by Gods grace I got rid of the situation and still working on Java platform. After that I never tried JSF.

Recently I am seeing many blogs like "How to migrate from Spring to JEE6", "Time to Migrate from Spring to JEE6", "Do we need Spring when JEE6 is providing everything". I know JEE6 far far better than earlier versions and it has many features inbuilt that Spring is providing.

I felt like "Oh..JEE6 becomes that simple...I should give it a try". Then I spent sometime on reading JEE6, yeah now using JEE6 is pretty simple. I started doing very simple POC using JSF2, EJB3, CDI, JPA using Glassfish server. Amazingly with in 30 min I was able to complete the POC and its up and running. Wowwww..

Then I started doing another POC using JSF2, EJB3, CDI, JPA but this time using JBoss6 as I thought of using RichFaces4(I know I can deploy RichFaces on Glassfish also but still I thought of using JBoss6).
I followed their reference documentation and added the richfaces jars to classpath and deployed the application and then the show started.

It gave errors as it depends on some Google classes which are not there on classpath. Then I search for the jar containing those classes and got so many jars list containing those classes. I tried with each jar and nothing worked.

After a while I thought of downloading richfaces sample applications assuming either sample apps contains those jars or it may declare those dependencies in pom.xml. I downloaded the richfaces samples and eagerly unzipped it and opened the pom.xml for the dependencies. I doesn't declare the dependencies in the pom and it is referencing to a parent pm file. I thought oh ok, dependencies might be declared in parent pom file. Then i checked parent pom...f*ck..parent pom file is not there in the downloaded bundle. WTF.

Then after googling for 20 min finally i found one article on what are the dependencies for using richfaces-4. Finally i was able to run my application.

By that time I was frustrated and my zeal to experiment on various cool UI widgets that RichFaces is giving was evaporated.

The reason why I am telling all this is
"I agree JBoss AS is great open source app server that comes for free, JBoss technologies like RichFaces, Drools etc etc may be awesome. But with your poor documentation, negligence on usability the developers are getting frustrated before tasting the sweetness of your great technologies. By poor documentation what I mean is when Richfaces depends on some other jars why don't you mention it in the documentation. You should mention it and if you can mention the maven dependency that would be great. By 'negligence on usability' what I mean is you gave a sample applications zip file referencing a parent pom file which is not bundled in that zip. Once you uploaded the samples if at-least once any of you tried to download and use the samples you might realize the absence of parent pom. You just uploaded samples without checking at-least once."

With all this how I feel is unless my employer insisted me to use JSF/RichFaces/EJB3 I will never use them.
When two(JEE6/Spring) technologies can do the same thing I would go with the technology(Spring) which just works as expected.

I wonder if anyone can write an application using JSF/EJB/CDI without having Google and StackOverFlow(because you will definitely face weird issues and after struggling so much of time you will find a solution in StackOverflow) :-)
 

But I can write an application with just Spring reference documentation :-).

"SPRING ROCKS"

Tuesday, November 15, 2011

Interesting (very old) thread on Spring licence change

While surfing internet today i came across very old thread discussing on Spring licence change and I enjoyed reading the thread :-)

http://www.theserverside.com/news/thread.tss?thread_id=50727#268860

I don't worry even if Spring becomes a commercial software because Spring source code already taught me how to write better code.

Thanks to Rod Johnson &  Team for the wonderful framework.

Thanks,
Siva

Monday, October 10, 2011

Spring and Quartz Integration Using Custom Annotation

We know Spring has support for integrating with Quartz framework.
But as of now Spring supports only static xml declarative approach only.
If you want to see how to integrate Spring+Quartz you can refer Spring + Quartz Integration .

As part of my pet project requirement I got to schedule the Jobs dynamically and I though of following 2 options:
1. Using Annotations for providing Job Metada
2. Loading the Job Metadata from Database

For now I thought of going ahead with Annotation based approach and I want to integrate it with Spring as well.
Here is how I did it.

1. Create a Custom Annotation QuartzJob

package com.sivalabs.springsamples.jobscheduler;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Scope("prototype")
public @interface QuartzJob 
{
 
 String name();
 String group() default "DEFAULT_GROUP";
 String cronExp();
}

2. Create an ApplicationListener to scan for all the Job implementation classes and schedule them using Quartz scheduler.

package com.sivalabs.springsamples.jobscheduler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.JobDetailBean;

public class QuartJobSchedulingListener 
    implements ApplicationListener<ContextRefreshedEvent>
{ 
 @Autowired
 private Scheduler scheduler;
 
 @Override
 public void onApplicationEvent(ContextRefreshedEvent event)
 {
  try 
  {
    ApplicationContext applicationContext = event.getApplicationContext();
    List<CronTriggerBean> cronTriggerBeans = this.loadCronTriggerBeans(applicationContext);
    this.scheduleJobs(cronTriggerBeans);
  } 
  catch (Exception e) 
  {
    e.printStackTrace();
  }
 }
 
 private List<CronTriggerBean> loadCronTriggerBeans(ApplicationContext applicationContext)
 {
   Map<String, Object> quartzJobBeans = 
    applicationContext.getBeansWithAnnotation(QuartzJob.class);
  
   Set<String> beanNames = quartzJobBeans.keySet();
  
   List<CronTriggerBean> cronTriggerBeans = new ArrayList<CronTriggerBean>();
  
   for (String beanName : beanNames) 
   {
     CronTriggerBean cronTriggerBean = null;
     Object object = quartzJobBeans.get(beanName);
     System.out.println(object);
     try 
     {
      cronTriggerBean = this.buildCronTriggerBean(object);
     } 
     catch (Exception e) 
     {
      e.printStackTrace();
     }
   
     if(cronTriggerBean != null)
     {
      cronTriggerBeans.add(cronTriggerBean);
     }
   }
   return cronTriggerBeans;
 }
 
 public CronTriggerBean buildCronTriggerBean(Object job) throws Exception
 {
   CronTriggerBean cronTriggerBean = null;
   QuartzJob quartzJobAnnotation = 
     AnnotationUtils.findAnnotation(job.getClass(), QuartzJob.class);
     
   if(Job.class.isAssignableFrom(job.getClass()))
   {
     System.out.println("It is a Quartz Job");
     cronTriggerBean = new CronTriggerBean();
     cronTriggerBean.setCronExpression(quartzJobAnnotation.cronExp());    
     cronTriggerBean.setName(quartzJobAnnotation.name()+"_trigger");
     //cronTriggerBean.setGroup(quartzJobAnnotation.group());
     JobDetailBean jobDetail = new JobDetailBean();
     jobDetail.setName(quartzJobAnnotation.name());
     //jobDetail.setGroup(quartzJobAnnotation.group());
     jobDetail.setJobClass(job.getClass());
     cronTriggerBean.setJobDetail(jobDetail);   
   }
   else
   {
    throw new RuntimeException(job.getClass()+" doesn't implemented "+Job.class);
   }
   return cronTriggerBean;
 }
 
 protected void scheduleJobs(List<CronTriggerBean> cronTriggerBeans)
 {
  for (CronTriggerBean cronTriggerBean : cronTriggerBeans) 
  {
    JobDetail jobDetail = cronTriggerBean.getJobDetail();
    try 
    {
     scheduler.scheduleJob(jobDetail, cronTriggerBean);
    } 
    catch (SchedulerException e) 
    {
     e.printStackTrace();
    }   
  }
 }
}

3. Create a customized JobFactory to use Spring beans as Job implementation objects.

package com.sivalabs.springsamples.jobscheduler;

import org.quartz.Job;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public class SpringQuartzJobFactory extends SpringBeanJobFactory
{
 @Autowired
 private ApplicationContext ctx;

 @Override
 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception 
 {
     @SuppressWarnings("unchecked")
  Job job = ctx.getBean(bundle.getJobDetail().getJobClass());
     BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
     MutablePropertyValues pvs = new MutablePropertyValues();
     pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap());
     pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());
     bw.setPropertyValues(pvs, true);
     return job;
 } 
}

4. Create the Job implementation classes and Annotate them using @QuartzJob


package com.sivalabs.springsamples.jobscheduler;

import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

@QuartzJob(name="HelloJob", cronExp="0/5 * * * * ?")
public class HelloJob extends QuartzJobBean
{  
 @Override
 protected void executeInternal(JobExecutionContext context)
   throws JobExecutionException
 {
  System.out.println("Hello Job is running @ "+new Date());
  System.out.println(this.hashCode());  
 }
}


5. Configure the SchedulerFactoryBean and QuartJobSchedulingListener in applicationContext.xml


 
 
 
 
 
  
   
  
 
 


6. Test Client

package com.sivalabs.springsamples;

import org.quartz.Job;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sivalabs.springsamples.jobscheduler.HowAreYouJob;
import com.sivalabs.springsamples.jobscheduler.InvalidJob;

public class TestClient
{
 public static void main(String[] args)
 {
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  System.out.println(context);  
 }

}