VOOZH about

URL: http://techforenterprise.blogspot.com/search/label/Spring

⇱ Tech for Enterprise: Spring


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

REST with Spring 3

World has moved on since I wrote the original article a few years ago. I plan to update the article shortly. But till I get around to doing the re-write, here is a link that has more updated information. https://examples.javacodegeeks.com/build-a-rest-api-with-spring-and-java-config/

// Below is the old original article for reference. 

In this article we will learn to create a basic REST service (hello world) using Spring 3, Logback, Maven, Tomcat, and Eclipse.

I have already written about Hello World with Spring 3 MVCHandling Forms with Spring 3 MVCJUnit, Logback, Maven with Spring 3Handling Form Validation with Spring 3 MVCIntroducing Spring Integration and Spring Integration with Gateways. This is an extension of the same series of Spring 3. It is not necessary, but it might be helpful for the audience to have a cursory glance at previous articles.

REST is best explained to a layman at How I Explained REST to My Wife. Clear, concise, conversational and informational. That's how articles ought to be. Easier said than done. For the geeky ones, here is the link to the PhD thesis by Roy, where he introduced the term REST. Google on if you want to know about the rest of REST :)

Spring 3 has excellent support, should you chose to go the REST way in your architecture. I highly recommend this article and the official documentation provided by SpringSource. Also there are some excellent material by IBM.

With that context setting done, let's roll up our sleeves and fire up the editor. We will learn as we code. To begin with, we will create a basic web application using Maven archetypes. Maven Tips is worth a quick read at this point, if you are not hands on with Maven.

File: \MavenCommands.bat

ECHO OFF 

REM =============================
REM Set the env. variables. 
REM =============================
SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.4\bin;
SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0
 
REM =============================
REM Standalone java web application. 
REM =============================
call mvn archetype:generate ^
 -DarchetypeArtifactId=maven-archetype-webapp ^
 -DinteractiveMode=false ^
 -DgroupId=foo.bar.spring3 ^
 -DartifactId=rest001

pause

If you run this batch file, it will give you a nice and functional web site, with correct folder structure, ready to be deployed on any of the many servlet containers (Tomcat 7 in my case), without writing a single line of code at all. If that alone does not make you check Maven website, I don't know what will (assuming of course that you don't use Maven already).

At this point I generally import it into Eclipse (I use STS and can honestly recommend it. Although I have to admit I am using 2.9.1 version for the current article and not the latest one, because that was being a bit twitchy. I am hoping this is temporary). If you are using standard Eclipse, consider investing time in getting m2e configured (with STS you get that pre-configured). I don't recall when was the last time I had used the standard build icon of Eclipse. My fingers type Alt+Shift+X, M  by muscle memory now, and I love m2e for making this seamless.

The next thing is to use Maven to get all requisite libraries.

File: \rest001\pom.xml

<!-- Unit test. --> 
<dependency> 
 <groupId>junit</groupId> 
 <artifactId>junit</artifactId> 
 <version>4.10</version> 
 <scope>test</scope> 
</dependency> 
 
<!-- Logging --> 
<dependency> 
 <groupId>ch.qos.logback</groupId> 
 <artifactId>logback-classic</artifactId> 
 <version>1.0.6</version> 
</dependency> 
 
<!-- A bridge between commons logging and slf4j. 
It is required for Spring classes. --> 
<dependency> 
 <groupId>org.slf4j</groupId> 
 <artifactId>jcl-over-slf4j</artifactId> 
 <version>1.6.1</version> 
 <scope>runtime</scope> 
</dependency> 
 
<!-- Spring MVC, without standard commons logging --> 
<dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-webmvc</artifactId> 
 <version>3.1.3.RELEASE</version> 
 <exclusions> 
 <exclusion> 
 <groupId>commons-logging</groupId> 
 <artifactId>commons-logging</artifactId> 
 </exclusion> 
 </exclusions> 
</dependency> 
 
<!-- JSTL --> 
<dependency> 
 <groupId>javax.servlet</groupId> 
 <artifactId>jstl</artifactId> 
 <version>1.2</version> 
</dependency>

I have put brief remarks on each of those dependencies. Hopefully it will be enough for you guess what they are for. If not, don't worry, we will find out soon.

Our next job is to configure our web application to handover all incoming requests to Spring (FrontController is it?). This is done quite easily.

File: \rest001\src\main\webapp\WEB-INF\web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">

 <!-- Register Spring servlet. -->
 <servlet>
 <servlet-name>spring</servlet-name>
 <servlet-class>
 org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <load-on-startup>1</load-on-startup>
 </servlet>
 
 <!-- Send all requests to Spring -->
 <servlet-mapping>
 <servlet-name>spring</servlet-name>
 <url-pattern>/</url-pattern>
 </servlet-mapping>
 
</web-app>

A couple of thing to note here.

 The header and the web-app section of this file is much beefier than the standard web.xml that Maven had created. You need this for JSTL to work. We will use JSTL later in the article.

 It is tempting to put the URL pattern as * instead of /. It works, but only till you get to the point of view resolution. At that point it refuses to find the view even with correct path. I just spent some humiliating amount of time chasing this issue. Avoid it.

Now, we have already asked the website to route all incoming requests to Spring servlet. We need to now configure the Spring servlet. Again, xml is the answer, although this one is going to be a bit chunky. Don't be afraid of the xml. I will explain that in plain english immediately after.

File: rest001\src\main\webapp\WEB-INF\spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

 <!-- Enables automatic scan for the class that has Spring annotations -->
 <context:component-scan base-package="foo.bar.controllers" />

 <!--To enable @RequestMapping process on type level -->
 <bean
 class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

 <!--To enable @RequestMapping process on method level -->
 <bean
 class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

 <!-- Content negotiation. -->
 <bean
 class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
 <property name="mediaTypes">
 <map>
 <entry key="xml" value="application/xml" />
 <entry key="html" value="text/html" />
 </map>
 </property>
 <property name="viewResolvers">
 <list>
 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
 <bean
 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <property name="viewClass"
 value="org.springframework.web.servlet.view.JstlView" />
 <property name="prefix" value="/WEB-INF/views/" />
 <property name="suffix" value=".jsp" />
 </bean>
 </list>
 </property>
 </bean>


</beans>


In plain english, this is what we have done. We have told Spring to look for Controllers in the package foo.bar.controllers. We have also said that the requests to the website, depending upon their format, could be hooked up with methods, wherein we will write code to handle those requests. Finally, we have in a oblique way (under the content negotiation bit) said that the views i.e. the stuff that shows up in browser (or other screens) should be served by jsp pages under WEB-INF/views directory.

Now we are at final piece of configuration. We need to tell logback, which we are going to use for logging (I am a bit of stickler when it comes to logging. You might want to read Log don't SOP, Logging revisited) what all to log and how.

File: \rest001\src\main\resources\logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
 <encoder>
 <pattern>%d %5p | %t | %-20logger{20} | %m %n</pattern>
 </encoder>
 </appender>

 <!-- Turn off 3rd party logging -->
 <logger name="org.springframework" level="OFF" />

 <root>
 <level value="DEBUG" />
 <appender-ref ref="CONSOLE" />
 </root>
</configuration>

Now we are all set to write a piece of code that will handle a REST style URI and respond to it. If you are hands on (even occasional coder) you will find that it does not take more than 10 - 15 minutes to have this bit up and running.

It is worth reflecting on this fact. Starting from an empty directory, to having all the bells and whistles in place to start writing a REST style webservice, complete with support for continuous integration, support for unit / integration testing, support for code quality software like Sonar, support for industrial strength logging like logback is not a trivial bit. Not too long back - say a decade back - it would take weeks to get this much framework configured, if not months. One can not help but appreciate the kind of efficiency that tools like Spring, JUnit, Logback, Eclipse etc have brought in to IT industry. And it also follows that hands on knowledge of the tools in market is that much crucial. It might be the difference between the success and failure of a project.

Anyway, rant aside, let's write the final pieces. A class.method() to handle the request.

File: \rest001\src\main\java\foo\bar\controllers\HelloWorld.java

@Controller
public class HelloWorld {
 private final static Logger logger = LoggerFactory
 .getLogger(HelloWorld.class);

 @RequestMapping(value="/greet/{name}", method = RequestMethod.GET)
 public String greet(@PathVariable String name, ModelMap model){
 model.addAttribute("name", name); 
 logger.debug("Greeting {}", name);
 return "greet"; 
 }
}

And a view to deliver the result.

File: \rest001\src\main\webapp\WEB-INF\views\greet.jsp

<html>
<head>
<title>REST with Spring 3</title>
</head>
<body>
Hello, ${name}. 
</body>
</html>

All done. Compile this and put it in Tomcat. You should be able to hit http://localhost:<portnumber>/rest001/greet/partha and have the web page greet you back. You will notice that there are no .jsp or .html or .do with the URL. These are the REST style URLs. In later articles we will look at more details, run some tests and look at some alternate ways for achieving REST style URLs.

With this I will close this article, but I will leave you are parting question to ponder upon. Are these the baby steps towards internet of things?

If you want to get in touch, you can look me up at Linkedin or Google+.

Handling Form Validation with Spring 3 MVC

This article is a part of a series on Spring 3. The earlier articles of this series were
Hello World with Spring 3 MVC
Handling Forms with Spring 3 MVC
Unit testing and Logging with Spring 3 Now lets dig a bit deeper into Spring. In this article we will learn to validate data that you have got from the forms. Let's look at the task of validation a little more closely.

Scenario 1: We might need to validate e.g. that the email provided does indeed look like an email (x@x.x format to be simplistic). This could be done by just running some scripts on the email field itself. That ought to be simple. We could write some javascript to be run on the browser itself. And also write the same validation on server side [Why? Read here]. This is true for all isolated validations e.g. check that the data is not null, check that the data is certain length etc etc.

Scenario 2: Wish life was that simple. Since we were discussing email validations, lets say one of the validations requires us to check that the email is of certain domains (say partner organizations) so that the system can email certain privileged information also. Let's say we need to check that the email is of format x@partner1.com, x@partner2.com or x@partner3.com. Trivial as it may be, this is an example of the type where the validation could not be run only on the data from the form itself. Whatever is the code for validation, it needs to know which domains are valid. And this data was not present in the data provided by end user in the form. If you flex your imagination a bit you could easily create use case where a business rules engine might be required (e.g. if the rules are too fluid) and / or you can throw in elements of internationalization (e.g. adult age is not 18 in all countries) or other complexities. These are non isolated validations and require accessing further information that is synchronously available. These validations could be coded in both server side and client side, although it is fair to say that it will lean more on server side.

Scenario 3: Again, wish life was that simple. Wile we are on the subject of validating emails, we might also need perhaps to check that the email is valid i.e. it is not a thisemail@doesnot.exist(I am not really sure that that email does not exist - or can not exist in future - but you get the idea I hope). We will need to send an email to that email id and perhaps ask the user to click and confirm. We need to interact asynchronously with some other system over SMTP. Again, lean on your imagination a bit and the whole pandora's box will burst open. Soon you are integrating over REST, SOAP, JMS, File Servers, and handling issues of security and authentication over distributed systems. I would bet most of the systems would go for server side validation in this area and client side validation - though technically possible - would not be used too often.

Scenario 4: And we have not yet breached the subject of same domain objects being populated not only from web based forms but also from feed files, JMS messages etc thereby needing the same validation logic being applied on multiple channels. What started off as a puny little form with a handful of innocent looking textboxes at the beginning of this discussion, has morphed into a monster.

Fortunately, JSR 303 or Bean Validation [Read more here] is there to rescue. It solves Scenario 1 and 4 mentioned above out of the box. And it supports you to solve Scenario 2 and 3. I will recommend you to read the section marked "How does this standard benefit users? What problems will it solve?" at this link.

This specification for java was requested in 2006 and by late 2009 it was released. In other words, the implementations available have already had a chance to mature over year. Spring 3, being a first class open source citizen, allows you to use this standard solution rather than reinvent the wheel. And should you absolutely need to reinvent the wheel (all professional apps need to write that myAppSpecificKickAssValidator()) Spring allows for that as well. Let's look at both scenarios one by one.

Add JSR 303 support to any Maven based project.

The JSR 303 is an open api. You can find it at this link. Anyone can implement that. There are implementations by hibernate, and apache bval to name a few. Let's go with the Hibernate implementation. You can see their jars at Maven Central at this link. The latest stable version at the time of writing this article is 4.3.0.Final. You just need to add this dependency in your pom. The api is also bundled with this implementation, hence you don't need to add that either.

File: pom.xml
<properties> 
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 [...]
<hibernate.validation.version>4.3.0.Final</hibernate.validation.version>
 [...]
</properties> 

<!-- Hibernate validations -->
<dependency> 
 <groupId>org.hibernate</groupId> 
 <artifactId>hibernate-validator</artifactId> 
 <version>${hibernate.validation.version}</version> 
</dependency> 
Just by adding this dependency you could go into your entity / form class and declare constraints. JSR 303 has a few standard constraints [listed here] which covers standard checks like NotNull. Hibernate adds a few more non standard custom constraints [listed here]. They are non standard, but quite handy e.g. a check for valid Email. Let's introduce both these checks on our ContactFrm.java. If you don't know where that came from, you most probably have not read the previous article of this series i.e. Handling Forms with Spring 3 MVC.

File: /org/academy/ui/spring3/forms/ContactFrm.java
package org.academy.ui.spring3.forms;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Email;

public class ContactFrm {

 @NotNull
 private String firstname;
 private String lastname;
 @Email
 private String email;
 private String telephone;

 // Getter and setters omitted for brevity. 
 [...]
}
Unit test

Until this point, our ContactFrm bean did not have any functionality in it and hence I did not bother to unit test it (although the TDD enthusiasts will shake their head at it). However, now just by adding a couple of annotations we have added functionality to the bean and that is unit testable (TDD enthusiasts can rejoice starting now). Let's add a unit test.

File: /src/test/java/org/academy/ui/spring3/forms/ContactFrmTest.java
package org.academy.ui.spring3.forms;

import static org.junit.Assert.*;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ContactFrmTest {
 private final static Logger logger = LoggerFactory
 .getLogger(ContactFrmTest.class);
 private static Validator validator;

 @BeforeClass
 public static void init() {
 validator = Validation.buildDefaultValidatorFactory().getValidator();
 }

 @Test
 public void test() {
 Set<ConstraintViolation<ContactFrm>> errors;
 ContactFrm contactFrm = new ContactFrm();

 errors = validator.validate(contactFrm);
 printErrors(errors);
 // We are expecting 1 error here.
 // Just the NotNull.
 assertEquals(1, errors.size());
 errors.clear();

 contactFrm.setFirstname("partha");
 errors = validator.validate(contactFrm);
 printErrors(errors);
 // We are not expecting any errors here.
 assertEquals(0, errors.size());
 errors.clear();

 contactFrm.setEmail("this can not be a valid email");
 errors = validator.validate(contactFrm);
 printErrors(errors);
 // We are expecting 1 errors here.
 assertEquals(1, errors.size());
 errors.clear();

 contactFrm.setEmail("this@mightbevalid.email");
 errors = validator.validate(contactFrm);
 printErrors(errors);
 // We are not expecting any errors here.
 assertEquals(0, errors.size());
 errors.clear();

 }
 
 // Utility function to print out errors from validation. 
 private void printErrors(Set<ConstraintViolation<ContactFrm>> errors) {
 if (errors.size() > 0) {
 for (ConstraintViolation<ContactFrm> error : errors) {
 logger.debug(error.getMessage());
 }
 } else {
 logger.debug("There were no errors to print.");
 }
 }

}
You will notice I did not need to use any Hibernate, Spring or JSR specific code to unit test. It is just a simple JUnit. In my mind, the fact that I could add validations on a POJO by just adding a couple of annotations and then I could unit test that with the standard unit testing framework without any tweaks, is a huge step deal. And we are just getting started.

Unit test - using Spring capabilities.

Of course it is reassuring that we could do complete validation and unit testing without relying on Spring. However we would miss the point of this exercise entirely if we don't explore how easy it is to bring this all together using Spring, in our website. We will start by adding all the required Spring dependencies to our project and stripping them off the commons logging as explained in the previous article. File: /pom.xml
<dependency>                                         
  <groupId>org.springframework</groupId>           
  <artifactId>spring-context</artifactId>          
  <version>${org.springframework.version}</version>
  <exclusions>                                     
    <exclusion>                                  
      <groupId>commons-logging</groupId>       
      <artifactId>commons-logging</artifactId> 
    </exclusion>                                 
  </exclusions>                                    
</dependency>                                        

[...]

<dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-test</artifactId> 
 <version>${org.springframework.version}</version>
 <scope>test</scope> 
 <exclusions> 
 <exclusion> 
 <groupId>commons-logging</groupId> 
 <artifactId>commons-logging</artifactId> 
 </exclusion> 
 </exclusions> 
</dependency> 
Now, add the @RunWith and @ContextConfiguration magic in the unit test, as as explained in the previous article.

File: /src/test/java/org/academy/ui/spring3/forms/ContactFrmTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ContactFrmTest {
 private final static Logger logger = LoggerFactory
 .getLogger(ContactFrmTest.class);

 @Autowired
 private Validator validator;

 // This is no more required as Spring does it for us. 
 // @BeforeClass
 // public static void init() {
 // validator = Validation.buildDefaultValidatorFactory().getValidator();
 // }

[The rest of the code omitted as it remains same.]
Now, all that remains is for us to tell Spring what it should Autowire in the validator. This we do using configuration rather than code.

File: /src/test/resources/org/academy/ui/spring3/forms/ContactFrmTest-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <bean id="validator"
 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
</beans>
There you are all set. You could now use "mvn -e clean install" to run this entire code and unit test it. If you were feeling too demanding you could use "mvn -e site" to create a nice HTML website which will report on the code coverage.

That's it for this article. Happy coding.

Want to read more?

Here are the links to earlier articles in this series.
Hello World with Spring 3 MVC
Handling Forms with Spring 3 MVC
Unit testing and Logging with Spring 3

And, of course these are highly recommended
Home page of JSR 303
Home page of Hibernate Validator
Interview with lead developer of Hibernate Validation - Emmanuel Bernard
Spring's official documentation on validation

If you want to get in touch, you can look me up at Linkedin or Google + .

JUnit, Logback, Maven with Spring 3

In this series we have already learnt to set up a basic Spring MVC application and learnt how to handle forms in Spring MVC. Now it is time to take on some more involved topics. However, before we venture into deeper waters, let's get some basics set up.

Unit testing
I am no TDD evangelist. There I said it. I have never ever been able to write any software where for every piece of code, I have written a test first and then code. If you have done so and are gainfully employed by coding, please do let me know. I would seriously like to know you better. Seriously.

My difference in opinion with TDD ends there. Apart from writing test before code - which somehow I simply can't get my brain to work with - I am a huge supporter of unit testing. I am a firm believer of using JUnit to test all functionality (public but non getter setter, methods). I am a huge fan of using cobertura to report on code coverage. I am a huge fan of maven which allows me to bring this all together in a nice HTML report with just one command.

I will use JUnit 4 for this series. Let's add the dependencies.

File: \pom.xml
<properties> 
 <junit.version>4.10</junit.version>
</properties> 

<!-- Unit testing framework. --> 
<dependency> 
 <groupId>junit</groupId> 
 <artifactId>junit</artifactId> 
 <version>${junit.version}</version>
 <scope>test</scope> 
</dependency> 

And let's add a dumb class to demonstrate testing.

File: /src/main/java/org/academy/HelloWorld.java
package org.academy;

public class HelloWorld {
 private String message = "Hello world. Default setting."; 
 public String greet(){
 return message; 
 }
 
 public String getMessage() {
 return message;
 }
 public void setMessage(String message) {
 this.message = message;
 }
}
And finally the JUnit to test it.

File: src/test/java/org/academy/HelloWorldTest.java
package org.academy;

import static org.junit.Assert.*;

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class HelloWorldTest {

 @Autowired
 HelloWorld helloWorld;
 
 private final static Logger logger = LoggerFactory
 .getLogger(HelloWorldTest.class);

 @Test
 public void test() { 
 logger.debug(helloWorld.greet());
 assertEquals(helloWorld.greet(), "Hello world, from Spring.");
 }
}
You would have noticed that the helloWorld within the unit test have never been initialized in the code. This is the bit of IoC magic of Spring. To make this work, we have used @RunWith, @ContextConfiguration and @Autowired. And I have also given Spring enough information to be able to create an instance of HelloWorld and then inject it to HelloWorldTest.helloWorld. Also, the assertEquals is checking for a very different message than what is actually hard coded in the HelloWorld class. This was done in a xml file mentioned below. Please do note the location of the file within Maven structure.

File: /src/test/resources/org/academy/HelloWorldTest-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <bean id="helloWorld" class="org.academy.HelloWorld">
 <property name="message" value="Hello world, from Spring." />
 </bean>
</beans>
There are multiple ways I could have provided this configuration file to the unit test. @RunWith(SpringJUnit4ClassRunner.class) is a nice thing to add but is not mandatory. What I have provided here is just the vanilla approach that works in most cases, but I encourage the audience to experiment.

Unit test coverage / code coverage.
I don't feel there is enough said about the importance of automated / semi automated / easy way of reporting on code coverage - both for individual developers and technical heads. Unless you are practising TDD religiously (which by the way I have mentioned before I personally have never been able to), it is absolutely impossible for even an individual developer to know if all logic branches of a code are covered by unit test. I am not even going to talk about how a technical head of a team / organization is going to ensure that his product(s) are sufficiently unit tested. I personally believe, any software product which is not sufficiently unit tested and test coverage reported, is an unacceptable risk. Period. Admittedly a bit of a hard stance, but that's how it is.

A bit of my conviction for the hard stance comes from the fact that it is so darn easy to report on test coverage. I will use cobertura in this example. You need to add cobertua to Maven pom.

File: pom.xml
<!-- Reporting --> 
<plugin> 
 <groupId>org.apache.maven.plugins</groupId> 
 <artifactId>maven-site-plugin</artifactId> 
 <version>3.0</version> 
 <configuration> 
 <reportPlugins> 
 <!-- Reporting on success / failure of unit tests --> 
 <plugin> 
 <groupId>org.apache.maven.plugins</groupId> 
 <artifactId>maven-surefire-report-plugin</artifactId> 
 <version>2.6</version> 
 </plugin> 
 <!-- Reporting on code coverage by unit tests. --> 
 <plugin> 
 <groupId>org.codehaus.mojo</groupId> 
 <artifactId>cobertura-maven-plugin</artifactId> 
 <version>2.5.1</version> 
 <configuration> 
 <formats> 
 <format>xml</format> 
 <format>html</format> 
 </formats> 
 </configuration> 
 </plugin> 
 </reportPlugins> 
 </configuration> 
And once you have done this, and added JUnit, and added an actual JUnit test, you just need to run
mvn -e clean install site
to create a nice looking HTML based code coverage report. This report will allow you to click through source code under test and give you nice green coloured patches for unit tested code and red coloured patches for those that slipped through the cracks.

Logging
Log4j is good, Logback is better. Just don't use System.out.println() for logging.

You could go a long way without proper logging. However, I have spent far too many weekends and nights chasing down production issues, with business breathing down my neck, wishing there was some way to know what was happening in the app rather than having to guess all my way. Now a days, with mature api like slf4j and stable implementation like logback, a developer needs to add just one extra line per class to take advantage of enterprise grade logging infrastructure. It just does not make sense not to use proper logging right from the beginning of any project.

Add slf4j and logback to Maven dependencies.

File: \pom.xml.
[...]
<logback.version>1.0.6</logback.version> 
<jcloverslf4j.version>1.6.6</jcloverslf4j.version>
[...]
<!-- Logging --> 
<dependency> 
 <groupId>ch.qos.logback</groupId> 
 <artifactId>logback-classic</artifactId>
 <version>${logback.version}</version> 
</dependency> 
[...]
<dependency> 
 <groupId>org.slf4j</groupId> 
 <artifactId>jcl-over-slf4j</artifactId> 
 <version>${jcloverslf4j.version}</version>
</dependency> 
[...] 
Ensure that Spring's default logging i.e. commons logging is excluded. If you are wondering if logback is really this good that I claim it to be why did Spring not opt for it to start with. In my defense, here is a link at Spring's official blog where they say "If we could turn back the clock and start Spring now as a new project it would use a different logging dependency. Probably the first choice would be the Simple Logging Facade for Java (SLF4J),..."

File: \pom.xml.
 
<dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-context</artifactId> 
 <version>${org.springframework.version}</version>
 <exclusions> 
 <exclusion> 
 <groupId>commons-logging</groupId> 
 <artifactId>commons-logging</artifactId> 
 </exclusion> 
 </exclusions> 
</dependency> 

[...] 

<dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-test</artifactId> 
 <version>${org.springframework.version}</version>
 <scope>test</scope> 
 <exclusions> 
 <exclusion> 
 <groupId>commons-logging</groupId> 
 <artifactId>commons-logging</artifactId> 
 </exclusion> 
 </exclusions> 
</dependency> 
Provide configuration for logback.

File: /src/main/resources/logback.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
 <encoder>
 <pattern>%d %5p | %t | %-55logger{55} | %m %n</pattern>
 </encoder>
 </appender>

 <logger name="org.springframework">
 <level value="INFO" />
 </logger>

 <root>
 <level value="DEBUG" />
 <appender-ref ref="CONSOLE" />
 </root>
</configuration>
 
Finally, add the magic one liner at the beginning of each class that needs logging (that ought to be all classes).

File: src/test/java/org/academy/HelloWorldTest.java
[...] 
private final static Logger logger = LoggerFactory 
 .getLogger(HelloWorldTest.class); 
[...]
logger.debug(helloWorld.greet());
[...]
There you are all set up. In the next section we will start working with the data that we collected from user using forms. We will start by validating form data.

Till then, happy coding.

Want to read more?

Here are the links to earlier articles in this series.
Hello World with Spring 3 MVC
Handling Forms with Spring 3 MVC

And, of course these are highly recommended
Spring 3 Testing with JUnit 4.
Running unit tests with the Spring Framework
@RunWith JUnit4 with BOTH SpringJUnit4ClassRunner and Parameterized
Issue with Junit and Spring.
If you want to get in touch, you can look me up at Linkedin or Google + .

Handling Forms with Spring 3 MVC

This article is a part of a series of articles written about Spring 3. The previous article of this series is available here. I recommend you read - or at least browse quickly - the previous article before reading further.

In this article we take another baby step towards Spring MVC. [Aside: A pdf by the originator of the term MVC.] Building from the previous article, let's add code necessary to add "Contacts" to the application. First thing, we will need to add some UI component to initiate the process. For simplicity's sake let it be a simple link.

File: /springwebapp001/src/main/webapp/index.jsp
[...]
<a href="contacts/addNew.html"> Add new contact.</a><br/> 
[...]
As you would notice, we have pointed this link to "contacts/addNew.html". This means that we need something - a controller and / or a method that is looking for this request. Let us create a controller that will field all requests starting with "contacts".

File: src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
package org.academy.ui.spring3.controllers; 
 
import org.academy.ui.spring3.forms.ContactFrm; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Controller; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.servlet.ModelAndView; 
 
@Controller 
@RequestMapping(value = "/contacts") 
public class ContactCtlr { 
 private final static Logger logger = LoggerFactory 
 .getLogger(ContactCtlr.class); 
[...]
}
Spring also has to know that it has to scan for a particular package for controllers.

File: /springwebapp001/src/main/webapp/WEB-INF/spring-servlet.xml
[...]
<context:component-scan base-package="org.academy.ui.spring3.controllers" /> 
[...]
Having set this we will need a method in the ContactCtlr to field GET requests for /addNew.html. [Aside: What is the difference between GET and POST request? Read here.]

File: src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
[...]
private final String addNewView = "Contacts/AddNew"; 
 
@RequestMapping(value = "/addNew", method = RequestMethod.GET)
public String addNewContact() { 
 logger.debug("Display form to add a new contact."); 
 return addNewView; 
} 
[...]
Here we have simply directed the control to "Contacts/AddNew" which boils down to /springwebapp001/src/main/webapp/WEB-INF/views/Contacts/AddNew.jsp.

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Add New Contact</title>
</head>
<body>
<form:form method="post" commandName="contact" action="addNew.html">
<table>
<tr>
<td colspan="2">Add a new contact.</td>
</tr>
<tr>
<td><form:label path="firstname">First Name</form:label></td>
<td><form:input path="firstname" /></td>
</tr>
<tr>
<td><form:label path="lastname">Last Name</form:label></td>
<td><form:input path="lastname" /></td>
</tr>
<tr>
<td><form:label path="email">Email</form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><form:label path="telephone">Telephone</form:label></td>
<td><form:input path="telephone" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Add Contact" /></td>
</tr>
</table>
</form:form>
</body>
</html>
This form will need to be backed by a java pojo which will hold all the form elements mentioned in the jsp.

File: /springwebapp001/src/main/java/org/academy/ui/spring3/forms/ContactFrm.java
package org.academy.ui.spring3.forms;

public class ContactFrm {
 private String firstname; 
 private String lastname; 
 private String email; 
 private String telephone;
 
 public String getFirstname() {
 return firstname;
 }
 public void setFirstname(String firstname) {
 this.firstname = firstname;
 }
 public String getLastname() {
 return lastname;
 }
 public void setLastname(String lastname) {
 this.lastname = lastname;
 }
 public String getEmail() {
 return email;
 }
 public void setEmail(String email) {
 this.email = email;
 }
 public String getTelephone() {
 return telephone;
 }
 public void setTelephone(String telephone) {
 this.telephone = telephone;
 }

}
From the AddNew.jsp you can see the form expects someone to handle a call to "addNew.html". As before, lets get back to the controller and add a method that handles a POST request to "addNew.html". Please note that this is a POST request as opposed to the GET request which we have handled before.

File: /springwebapp001/src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
[...]
@RequestMapping(value = "/addNew", method = RequestMethod.POST) 
public ModelAndView addNewContact( 
 @ModelAttribute("contact") ContactFrm contactFrm, 
 BindingResult result) { 
 logger.debug("Adding a new contact. {}", contactFrm.getFirstname());
 // Some code to work on the data received from the user. 
 return new ModelAndView(addNewView, "contact", new ContactFrm()); 
}
[...]
Lo and behold, if you compile and run this app in any servlet container i.e. Tomcat, you will get a link, that will lead to a Form, that will allow you to put in data, that will transport that data to a java controller at server end, and come back to the form for more. Those of the audience who have designed and developed web applications before MVC frameworks came into being will have moist eyes for sure. Even if you have worked with the early frameworks for MVC, Struts to name the most successful one, will rue the hours spend in getting the three components (M,V and C) together, that now we can get done in under 10 minutes. Software development has definitely come a long way.

In the next section we will add unit testing and logging to this application. Happy coding.

Want to read more?

Here is the link to earlier article in this series.
Hello World with Spring 3 MVC


And, of course these are highly recommended
Struts - The only other MVC framework that I can recommend
Difference between GET and POST
The origin of the term MVC

If you want to get in touch, you can look me up at Linkedin or Google + .

Hello World with Spring 3 MVC


I owe my introduction to Spring to this article by Martin Fowler, way back in 2005. Since then I have tinkered with many a IoC frameworks including GuicePicoContainerNanoContainer etc. While I have enjoyed working with IoC in general, I must say Spring has been and continues to be my choice of IoC container for all enterprise grade application development for well over 5 years now. 

The latest version of Spring i.e. Spring 3 has been out for a while now. The latest minor version 3.1.1 was released less than a week back, at the time of writing this article. So, as I generally do with latest releases of a few software like Spring, Hibernate, Maven etc I redid - perhaps for the 1000th time - a hello world example with Spring. However, this time I thought I will share this, with the hope that novices in Spring will find the article useful. Keeping in mind the intended audience I felt that an article on Spring MVC will be more useful. 

Before I go any further, I must mention that there is no dearth of articles on this subject on net. A few of them are highly recommendable e.g. this one. In my article - unlike the other ones that I have read - I intend to use Eclipse only as an editor and Maven for most of build and dependency management related activities. I am sure others would have written similarly as well. If you know of any good article please let me know and I will mention them here as well. 

Without further ado, lets start by creating a vanilla web application using Maven.

File: C:\partha\codeRepo\MavenCommands.bat

ECHO OFF 

REM =============================
REM Set the env. variables. 
REM =============================
SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.3\bin;
SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0


REM =============================
REM Create a vanilla web applicaiton. 
REM =============================
call mvn archetype:create ^
 -DarchetypeArtifactId=maven-archetype-webapp ^
 -DarchetypeGroupId=org.apache.maven.archetypes ^
 -DgroupId=org.academy ^
 -DartifactId=springwebapp001 

pause

This would create a web application springwebapp001. You could deploy that in any servlet container and should be able to hit http://yourmachinename:portnumber/springwebapp001/. It should show you whatever is available at /springwebapp001/src/main/webapp/index.jsp.

Now we will Spring dependencies which will allow us to hijack the http hits to the website. I find this article very informative at this step. It gives you a laundry list of all Spring dependencies. There are a few things worth pointing out though. If you were looking for only Spring MVC, it is not immediately apparent that you could just include dependency for Spring MVC and not the entire list. What is also missed is that you need JSTL as well. Lastly, I think it could have been also mentioned that Spring comes preloaded with commons logging which in my opinion is well and truly on it's way out - relinquishing it's seat to Logback or Log4j. So, net net, my version of dependency section in pom looks like this.

File: \springwebapp001\pom.xml

[...]

 

[...]

 
 

[...]

 
 

[...]

 
 
 

We have got all dependencies in place now and we should be able to do a mvn -e clean install without any hiccups. Once we have done that, now is the time to get Spring into the game. We need to hijack all hits for *.html and hand it to Spring.

File: /src/main/webapp/WEB-INF/web.xml

[...]
 
 
[...]
This means that our application would look for a spring-servlet.xml, where we need to tell Spring what it needs to do with the hits that it intercepts.

File: /src/main/webapp/WEB-INF/spring-servlet.xml


Here we have told Spring to look for controllers in org.academy.spring3.controllers package. Lets add one then.

File: /src/main/java/org/academy/spring3/controllers/HelloWorld.java
@Controller
public class HelloWorld {
 private final static Logger logger = LoggerFactory.getLogger(HelloWorld.class); 
 
 @RequestMapping("/helloworld")
 public ModelAndView hello(){
 logger.debug("In the controller."); 
 return new ModelAndView("HelloWorld", "message", "Hello world from Spring3."); 
 }
}
In this controller we have told Spring to intercept any call to helloworld.html and hand over control to hello(). In this method, we have created a model. The model contains an object called "message" which has a string "Hello world from Spring3.". This model is handed over to a view called "HelloWorld". If you look back at spring-servlet.xml you will see "HelloWorld" translates to /src/main/webapp/WEB-INF/views/HelloWorld.jsp. Let's add some code to that.

File: /src/main/webapp/WEB-INF/views/HelloWorld.jsp

<html>
<head>
<title>Spring 3.0 MVC</title>
</head>
<body>
${message}
</body>
</html>
This code is going to complain a bit on compilation because we have not provided configuration to logback. The following file should do the trick.

File: /src/main/resources/log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# configure A1 to spit out data in console
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout 
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n 
Finally, we just need a convenient way to call the helloworld.html. Let's modify index.jsp.

File: /src/main/webapp/index.jsp

<html>
<html>
<body>
<h2>Spring 3</h2>
 Hello world.
</body>
</html> 
That's it. Compile and deploy in any servlet container. You have a Spring 3 MVC bare bones example up and running. Give it a go. Happy coding.
Want to read on? May I suggest ...



If you want to get in touch, you can look me up at Linkedin or Google + .
Subscribe to: Posts (Atom)