Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Your Next Java Web App: Less XML, No Long Restarts, Fewer Hassles (Part 3)

Note: This tutorial continues from Part 2 and is gonna show you how to code Java without any of the traditional B.S., like tons of XML and app server restarts. It’s split into 3 parts so that your brain doesn’t freak out at a 50-meter long webpage. Enjoy!

Part 1 | Part 2 | Part 3

DOWNLOAD THE PDF


——————————

Enough with the setup, let’s write some code!

Once upon a time, Sun started with the PetStore sample application and Spring continued it with the PetClinic. Now that the cute little goblins have been bought and cared for, let’s publish their pictures for the whole world to see – introducing Snoutbook!

I didn’t want to use something trivial, but didn’t want too much complexity either. I finally settled for a three-class model: owners, pets and pictures. While simple, it still allows for demonstrating one-to-many and many-to-one relationships.

The application itself also is simple at first. It consists of only three screens: Owners list, addPet form and Pet’s profile.

Developing with JRebel

Disclaimer: I work on the JRebel team at ZeroTurnaround, but before I worked at ZT I used JRebel in every project I could.

Using JRebel puts app development on the fast track. I can add new model classes, decorate them with JPA annotations and see the results in the browser immediately after pressing F5. Same goes for adding things like new Spring beans and form controllers. The only time throughout this entire process that I needed to start the app server again was when a Windows update forcibly restarted my computer.

Note: When starting the app server from within Eclipse, you need to disable automatic publishing and enable the JRebel agent on the server page. When starting the container from a command line, I need to make sure the JVM argument -javaagent:path/to/jrebel.jar gets passed to the JVM that is running the server. It’s usually the startup script such as catalina.bat, or the MAVEN_OPTS system property when using mvn jetty:run for example.

You also need rebel.xml, a configuration file makes JRebel to monitor the folder where Eclipse is compiling the classes to and reloading them as necessary. Just so you know, rebel.xml is best generated in Eclipse by right-clicking on the project and selecting JRebel->Generate rebel.xml...

JRebel also monitors the web resources directory, which means that I don’t need to run the build scripts for any change I’m making. As long as the “build automatically” option is selected in Eclipse, all I need to do is save the file (whether it’s Java, JSP or CSS file), ALT-TAB to the browser and hit refresh.

The generated rebel.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.zeroturnaround.com"
  xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">

  <classpath>
    <dir name="${rebel.workspace.path}/HelloWeb/target/classes">
    </dir>
    <dir name="${rebel.workspace.path}/HelloWeb/src/main/resources">
    </dir>
  </classpath>

  <web>   
    <link target="/">
      <dir name="${rebel.workspace.path}/HelloWeb/src/main/webapp">
      </dir>
    </link>
  </web>

</application>

The interesting part here is ${rebel.workspace.path}, which gets substituted with the real path when starting the server. This means that you can commit the file to a version control system and not worry about different team members having different workspace locations.

Model classes

I’m starting with Owner and Pet classes for now and add the Picture class later (again, with JRebel this is all done without restarting the application).

@Entity
public class Owner {

  @Id
  @GeneratedValue  
  private Long id;

  private String name;

  @OneToMany (cascade=CascadeType.ALL, mappedBy="owner")
  private List pets;

 //getters and setters omitted

}

@Entity
public class Pet {

  @Id
  @GeneratedValue
  private Long id;

  private String name;
  private Date dateBorn;  
  private boolean alive;

  @ManyToOne
  @JoinColumn(name="owner")
  private Owner owner;

  //getters and setters omitted

}

I don’t need to add JPA annotations to every field, as JPA uses convention over configuration and assumes the field name maps to column “name”. The relationship between the Owner and a Pet is one-to-many and many-to-one respectively. That’s it. In case your tables and column names correspond closely to class names and their fields, you only need to explicitly annotate the classes and identify fields & relationships.

Adding a controller

Spring finds and instantiates the controller bean automatically since the class is annotated with @Controller and our WebappConfig class was annotated with @ComponentScan("com.zt.helloWeb"). The dependency to the yet-to-be-written SnoutDao object is provided automatically, I don’t even need to add a setter function.

@Controller
public class SnoutContoller {

  @Autowired
  private SnoutDao dao;

  @RequestMapping("/owners")
  public String listOwners (Model model) {
    List owners = dao.getOwners();    
    model.addAttribute("owners", owners);

    return "owners";
  }

}

Spring finds and instantiates the controller bean automatically since the class is annotated with @Controller and our WebappConfig class was annotated with @ComponentScan("com.zt.helloWeb"). The dependency to yet-to-be-written SnoutDao object is provided automatically, I don’t even need to add a setter function.

The annotation-based approach in SpringMVC departs significantly from the older Controller based approach where you had to implement ModelAndView#handleRequest(request, response).
Now the whole job is done via annotations and that gives tremendous flexibility when defining handler functions. You can add Model object in your argument list, but you don’t have to. You can also bind http request parameters to method arguments, which makes the code even cleaner. You can return a ModelAndView object if you like, but are also free to return a String object, which will denote the view script to be rendered.

You can return the output directly to the browser by adding a @ResponseBody annotation to the method. The flexibility here is almost unlimited, but it does not become vague or ambiguous. In a nutshell, my method listOwners is mapped to /owners URL, uses a Model argument for passing data to the view script easily and renders owners.jsp as a result.

DOWNLOAD THE PDF



The DAO

The SnoutDao’s humble beginnings:

@Repository
@Transactional
public class SnoutDao {

  @PersistenceContext
  private EntityManager entityManager;

  public List getOwners() {    
    return entityManager.createQuery("select o from com.zt.helloWeb.model.Owner o", Owner.class).getResultList();   
  }

}

Dao classes should have @Repository and @Transactional annotations. The @Repository annotation denotes a bean with a specialized role and @Transactional makes Spring manage transactions for you. Otherwise you would need to open/close sessions and transactions yourself manually.

Returning a list of objects from a database is a simple one-liner in this CRUD application. JPA provides a ton of options for retrieving your data from a database, but for now this will suffice.

JSP files, TLD’s and the like

The last piece of the puzzle is the view script

<%@ include file="/WEB-INF/layout/header.jsp" %>

<div id="content">
  <h1>Pet Owners</h1>
  <table id="petowners">
    <tr>
      <th>Name</th>
      <th>Pets</th>
    </tr>
    <c:forEach items="${owners}" var="owner">
      <tr>
        <td>${owner.name}</td>
        <td>
          <c:forEach items="${owner.pets}" var="pet">
            <a href="pet/${pet.id}">${pet.name}</a>  
          </c:forEach>
        </td>
      </tr>
    </c:forEach>
  </table>
  <button onclick="window.location='addPet'">Add Pet</button>
</div>

<%@include file="/WEB-INF/layout/footer.jsp" %>

The trick here is to make good use of various Tag Libraries. Think of them as frameworks for building HTML markup in view scripts. For more complex applications, it’s often a good idea to create your own as well, but in my case I’m sticking to the standard and Spring Framework ones. This makes it easy to iterate over a collection. I’m already generating links to other pages in my application (namely /pet/{id}), which I will add next.

I’m including header and footer.jsp files that contain the rest of the HTML markup that makes up a page. Header.jsp also contains the import statements for all the JSTL libraries:

<%@page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Snoutbook</title>
<link rel="stylesheet" href="/helloWeb/snout.css" />
</head>
<body>
<div id="blueBar"> </div>
 <div id="wrapper">
 <div id="container"> 
 <div id="top"><a href="/helloWeb/owners">snoutbook</a></div>

All that’s left is starting the server from within Eclipse and checking the result:

Moving along

Now it’s time to add the third entity “Picture”

@Entity
@Table(name="picture")
public class PetPicture {

  @Id
  @GeneratedValue
  private Long id;
  private String title;
  private String description;

  private Date dateTaken;

  @ManyToOne
  @JoinColumn (name="pet")
  private Pet pet;
  //getters and setters omitted
}

Note that this time the table name and the class name do not match, which is why I need the @Table annotation.

I also need to add the relationship to the Pet class:

@OneToMany (mappedBy="pet") 
private List<PetPicture> pics;

Next I’m adding the method to my SnoutController:

@RequestMapping("/pet/{petId}") 
 public String pet(@PathVariable Long petId, Model model) {
 Pet pet = dao.getPet(petId);
 model.addAttribute("pet", pet);

 return "viewPet";
 }

What just happened? I mapped part of the request URI as an input variable! This is achieved by using {varname} in request mapping and using a parameter with the same name in the method (together with @PathVariable annotation).

The addition to the SnoutDao is simple:

public Pet getPet(Long petId) {
  return entityManager.find(Pet.class, petId);
}

Finally, since I return viewPet from the method, I need to create a viewPet.jsp in the WEB-INF/views folder.

<%@ include file="/WEB-INF/layout/header.jsp" %>

<div id="content">
  <h1>Pet Details</h1>
  <table class="petDetails">
    <tr>
      <th scope="row">Name</th>
      <td>${pet.name}</td>
    </tr>
    <tr>
      <th scope="row">Owner</th>
      <td>${pet.owner.name}</td>
    </tr>
    <tr>
      <th scope="row">Date Born</th>
      <td>
        <fmt:formatDate value="${pet.dateBorn}" pattern="dd.MM.yyyy" />
      </td>
    </tr>
    <tr>
      <th scope="row">Alive</th>
      <td>${pet.alive}</td>
    </tr>
  </table>

  <div class="photos">
    <c:forEach items="${pet.pics}" var="pic">
      <div class="pic">
        <div class="del">
          <a href="/helloWeb/deletePic/${pic.id}">x</a>
        </div>
        <img class="img" src="/helloWeb/img/${pic.id}.jpg" alt="${pic.title}" />
        <h2>${pic.title}</h2>
        <p>${pic.description}</p>
      </div>

    </c:forEach>
    <div style="clear:both"> 
    </div>
  </div>

</div>

<%@include file="/WEB-INF/layout/footer.jsp" %>

The result is here:

Creating Forms

The last step in building the purring network I’m willing to share is adding a new Pet.
I’m going skip ahead and show the final result first this time, and then detail the steps necessary to get there.

Yes, I know about fancy date pickers and date string parsing, but for education’s sake let’s use three distinct values for inserting a date.

There are several ways to accomplish this. Often form controls are directly bound to the underlying model class, but usually this creates problems and complexity (or it may not, YMMV). I like to create a separate form class that corresponds to the HTML and the user model. It is similar, but differnent from the program model (yes, I’m referencing Joel Splosky here – http://www.joelonsoftware.com/uibook/chapters/fog0000000058.html and http://www.joelonsoftware.com/uibook/chapters/fog0000000060.html).

The Form class in question looks like this:

public class PetForm {

  @NotEmpty
  @Length(min=1, max=32)
  private String name="breakfast";  

  @Range(min=1, max=31)
  private int dayBorn=1;

  @Range(min=0, max=11)
  private int monthBorn=0;

  @Range(min=1900, max=2038)
  private int yearBorn=1990;

  private Date dateBorn;

  private boolean alive=true;

  private long owner; 

  public void validate (Errors errors) {
    Calendar cal = new GregorianCalendar(yearBorn, monthBorn, dayBorn);
    dateBorn = cal.getTime();
    if (dateBorn.after(new Date())) {
      errors.rejectValue("dateBorn", null, "Date is in future");
    }    
  }

Often Spring tutorials advocate using separate Validator classes and sometimes it is a great idea. However, since I’m using a separate form Object, it makes sense to couple that with validation. I’m combining Spring MVC with bean validation here. This allows for declaring mundane and simple constraints declaratively, and then adding some additional complex validation where needed. There’s no point in validating String length manually when the annotation-based approach fits so neatly here. All that’s left for me to do is building the dateBorn value from its components and validating the result.

Form controller

The controller class is quite large, but it has to do some heavy lifting as well.

The controller has to first set up the form and later handle the submitted input.
I’m using a combination of @RequestMappings here. First I’m annotating the class itself with the URI path:

@RequestMapping("/addPet")
public class AddPetFormController

Next, I’m creating a method “setupForm” and make it handle GET requests only.

@RequestMapping(method = RequestMethod.GET)
 public String setupForm(Model model) { 
 PetForm form = new PetForm(); 
 model.addAttribute("petForm", form); 
 return "addPet";
 }

It is not required to pass all the data to the view script in a single method. By annotating a method with @ModelAttribute(“myAttributeName”), it is invoked and the result made available to the script. I’m using this approach to populate the Owner and Month selection boxes.

@ModelAttribute("owners")
  public Collection getOwners(){
    return dao.getOwners();
  }

  @ModelAttribute("monthNames")
  public Collection<Month> getMonthNames() {
    String[] names = new String[]{"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
    List answer = new ArrayList();
    for (int i=0; i<names.length; i++) {
      answer.add(new Month(i, names[i]));
    }

    return answer;
  }

class Month {
    private int id;
    private String label;

    public Month(int id, String label) {
      this.id=id;
      this.label = label;
    }

}

Note: It is not required to pass all the data to the view script in a single method. By annotating a method with @ModelAttribute(“myAttributeName”), it is invoked and the result is made available to the script. I’m using this approach to populate the Owner and Month selection boxes.

Handling the submit

@RequestMapping(method = RequestMethod.POST)
  public String handleSubmit(@Valid PetForm form, BindingResult result, SessionStatus status) {

    form.validate(result);

    if (result.hasErrors()) {
      return "addPet";
    }
    else {      
      Pet pet = new Pet();
      pet.setName(form.getName());
      pet.setAlive(form.isAlive());

      Calendar cal = new GregorianCalendar(form.getYearBorn(), form.getMonthBorn(), form.getDayBorn());
      pet.setDateBorn(cal.getTime());

      Owner o = dao.findOwner(form.getOwner());
      pet.setOwner(o);
      o.getPets().add(pet);
      dao.saveOwner(o);

      status.setComplete();
      return "redirect:owners";    
    }

  }

Keep in mind that the @Valid annotation here validates fields marked with bean validation annotations automatically. The validation process itself is simple – validators are invoked, passing the Errors object along, and the controller later checks whether something raised an error or not. If validation passes, the controller builds a model object from the PetForm and persists it.

Another good approach is using GET-POST-redirect approach, where the browser is redirected away after making a successful POST request. That prevents double entries when refresh is pressed in the browser.

Finally, the jsp file

<%@ include file="/WEB-INF/layout/header.jsp" %>

<div id="content">
  <h1>Add Pet</h1>
  <form:form action="addPet" method="POST" modelAttribute="petForm">
    <div>
      <label>Owner</label>
      <form:select path="owner" items="${owners}" itemValue="id" itemLabel="name" />
    </div>
    <div>
      <label>Name</label>
      <form:input path="name" cssErrorClass="error" />
    </div>
    <div>
      <label>Date Born</label>
      <form:input path="dayBorn" size="2" cssErrorClass="error" />
      <form:select path="monthBorn" items="${monthNames}" itemValue="id" itemLabel="label" />
      <form:input path="yearBorn" size="4" cssErrorClass="error" />
      <form:errors path="yearBorn">
        <span class="error">Illegal value</span>
      </form:errors>
      <form:errors path="dateBorn" cssClass="error" />
    </div>
    <div>
      <label> 
      </label>
      <form:checkbox path="alive" />
      <label>alive</label>
    </div>

    <button type="button" onclick="window.location='owners'">Back</button>
    <form:button value="Save" name="add">Save</form:button>
  </form:form>
</div>

<%@include file="/WEB-INF/layout/footer.jsp" %>

Do you see the ease of mapping collections to a <select> element together with ids and labels? I’m using Spring’s form tag library here for ease of use, where the association is done via path attribute. Errors are signalled using form:errors tag or cssErrorClass attribute on the form tags itself.

I prefer Spring’s approach due to the lack of magic involved. There is no fragile component tree and it is clear how state is stored. Even though I’m using Spring’s form tags, they resolve to simple HTML elements and to bind a variable to “name” field in the PetForm class, I could also use <input type=”text” name=”name” value=”” />.

The last six lines of code

needed in SnoutDao:

public void saveOwner(Owner o) {
    entityManager.persist(o);      
  }
  public Owner findOwner(Long id) {
    return entityManager.find(Owner.class, id);
  }

And it works!

And I still haven’t redeployed or restarted anything. At all. In fact, writing the content that you are reading now took more time than developing the app itself.

Thank you JRebel!

What’s coming next? Improvements!

The little cute application is far for being complete. There are still some snags I’m not happy with and will discuss them at some point later on. I particularly dislike the fact that the mvc and persistence config are both in the single AppConfig class. I’m going to change that. I also wish for a better way to address templating issues than <%@ include’ing (I’m not swearing, this is the actual syntax) header and footer files in view scripts. And I’m also going to address scaling up, when, for example, I wish to separate webapp from the core logic completely a provide the rest of the world with some kind of an API to fetch all those cute pictures programmatically.

Try it yourself!

I uploaded the sample app to BitBucket and you can explore the files in the Bitbucket repository
To clone the repo directly and start it up on your machine, install Mercurial and

hg clone https://bitbucket.org/arnelism/snoutbook

Thanks for reading, and if you feel like having a chat, please contact me at arnel@zeroturnaround.com!

DOWNLOAD THE PDF



  • James Cole

    Fantastic tutorial / article. I’ve been planning on trying out Spring 3.1 xml-less and Servlet 3.0 AND JRebel for a while.

    This is a great starting point; I like that you detailed all the annotations and classes and what they do (so many of the tutorials out there gloss over too many details).
    I’ll also be using WRO4J (which I’ve used before) and Thymeleaf (which I have not used before but looks awesome) to make a really slick project starting point during our next hackathon.

    Thanks so much. If JRebel works as well as it appears to during the 14 day trial, I’ll definitely be pushing for my company to buy the whole team licenses :)

  • JL

    Very nice and real life oriented tutorial! I’m looking forward for the “improvements” tutorial!

    3 little comments :

    – There are 2 sections that are repeated. The one starting with “Spring finds and instantiates” and the one starting with “It is not required to pass all”.

    – Shouldn’t “pics” be cascaded in the Pet class?

    – I think the Facebook/Twitter/Email/Phone icons that follow when your scroll the page on this site are really distracting!

    Thanks again!

  • md

    excellent article! i think the web.xml file is missing from repository

  • The sample app in BitBucket uses WebApplicationInitializer instead of web.xml.

  • skyzer

    thanks, great tut.
    waiting for your improvements part

  • Sandip Vashisth

    Thank Arnel sir, i tried this sample with jpa specification but i am getting error tha is…….
    java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.dialect.MySQL5Dialect

    Please help me to resolve it

  • Clyde Sales

    How did that WRO4J and Thymeleaf project go? Interested in using those in conjuction myself and hoping to hear some pitfalls…