Open Source RDBMS - Seamless, Scalable, Stable and Free

한국어 | Login |Register

Current Events
Join our developers event to win one of the valuable prizes!
posted 2 years ago
viewed 22496 times
Share this article

Spring Roo: Fast Java Application Development Tool

Spring Roo is a development tool that allows easy and fast Java Application development. Let’s develop a Java application by using Spring Roo.

What is Spring Roo?

Spring Roo is a development tool, not a framework. Although the name “Spring” often makes people think that it is a framework, it is a type of code creation tool. Java project does not provide any library to use during runtime, nor does it require any coding or architecture style. Therefore, it cannot be considered as a framework. Because of this, it is not right to compare it with Ruby on Rails or Play. Applications that can be developed by using Spring Roo are basically Spring-based Java (web) applications, GWT applications, Google App Engine applications and many more. Let’s look at an example to see how it speeds up the development process.

Spring Roo Installation

Spring Roo can be installed separately by downloading it, but it does not really need a special installation process. Just download and decompress it, and you are done. If Spring Tool Suite (STS) is already installed, you do not need to install Spring Roo separately because it is already included in the STS package.

Creating a Spring Roo Project

Figure 1: Creating a Spring Roo Project

Figure 1: Creating a Spring Roo Project.

Select New -> Project -> Spring Roo Project to create a Roo project. The earlier versions of Spring Roo could be processed from the console only, but after STS added the Spring Roo support feature, there is no need to work from the console. Once the project is created by using this menu, the project will show up in the STS Package Explorer, and you will be able to see the following Roo Shell at the bottom of STS.

Figure 2: Roo Shell

Figure 2: Roo Shell.

This view will replace the console from now on. By using the DSL provided by Roo, you can do different tasks here such as configuring JPA, creating entity class, adding a field to each entity, configuring an arithmetic relationship, creating a controller or creating a test.

Figure 3: Package Explorer.

Figure 3: Package Explorer.

The project is a normal Maven project structure, and applicationContext.xml, a Spring configuration file, can be seen here. Creating a Maven project, configuring basic Spring and filling in pom.xml with the Spring dependence takes a long time without Maven Archetype. Though I think this alone is worth having Spring Roo, most readers may not be satisfied with this. Especially, if you have Maven Archetype that you manage yourself or your company provides, the fast development support feature from Spring Roo may not seem great.

Let’s look at the Spring bean configuration file now.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" …>
    <context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
    <context:spring-configured/>
    <context:component-scan base-package="whiteship">
        <context:exclude-filter expression=".*_Roo_.*" type="regex"/>
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
</beans>

After removing the footnotes from the bean configurations in applicationContext.xml, only the above configurations remain. Amongst these, the most important part related to Spring Roo would be this: <context:spring-configured/>. Using this configuration allows Spring dependency injection to be used on objects not registered as beans in Spring ApplicationContext.

<context:spring-configured/> and Spring Roo

It is not a simple task to insert Spring managed dependency into an object not registered as beans. For example, if a Book object named “Book book=new Book();” is created somewhere, it would mean that a BookRepository type bean is inserted to this object. To do so, an additional task must be performed at the time the Book class’s creator is called. But this task cannot be carried out by Spring AOP. This task is possible only by using AspectJ, which provides all AOP features. Generator call Joinpoint for AspectJ (an AOP term, means a point where additional features can be added. Method call joinpoint is the only Joinpoint that can be used in Proxy-based Spring AOP.) can be used to insert a BookRepository type bean from Spring ApplicationContext by using the Spring dependency injection feature when Book class is created.

Spring Roo Architecture

So, why do we need these features in Spring Roo? That is because of the architecture Spring Roo has used until recently. Up to now, Spring Roo insisted on the active record pattern introduced in Patterns of Enterprise Application Architecture (PEAA). Active record pattern allows one line of DB to respond to an object, and DB operation is also held by the same object.

Active Record pattern is chosen because of the convenience in application development. Since all requests are processed by simple calls like “Controller -> Domain Object,” everything is easier. But, after some people pointed out that the testing is difficult because the static method which is not preferred by Spring is used to implement the finder, the location to set the transaction boundaries is ambiguous, and there are a number of dependencies inserted into the entity object (see http://moleseyhill.com/blog/2009/07/13/active-record-verses-repository/), they have changed their strategy recently.

Figure 4: New application layering and persistence choices in Spring Roo.

Figure 4: New application layering and persistence choices in Spring Roo.
(Source: http://blog.springsource.org/2011/09/14/new-application-layering-and-persistence-choices-in-spring-roo/)

General service and repository class structure architecture is supported from Spring Roo 1.2 M1, which recently released by SpringSource. Because of that, Active Record pattern can be used selectively (default value is Active Record pattern style). Now let’s learn how to configure JPA and create an Entity.

JPA Configuration

Figure 5: JPA Configuration.

Figure 5: JPA Configuration.

You are prompt to configure DB related to JPA supplier. Configure JPA. Enter the following into the field.

jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY

I have not manually entered a single command after “jpa setup.” After entering “jpa setup,” I simply selected the suggested commands provided when you press Ctrl+Space. In this way, you can enter long commands without memorizing them. Entering this command:

  • brings the dependencies for hsqldb1.8.0.10 and Hibernate 3.6.7;
  • corrects the contents of applicationContext.xml;
  • and creates persistence.xml file.

How long would it take to do these tasks manually? It would take several minutes to find the dependency information, and another several minutes to add the bean and transaction configurations to use for applicationContext JPA. It would require more time after that to create the JPA configuration file, persistence.xml, and to add basic configurations. But all these tasks were completed within seconds. This is the beauty of fast development offered by Spring Roo.

In applicationContext.xml, DataSource, TrasactionManager, tx:annotation-driven and EntityManagerFactory bean have been registered, while the hibernate configurations, which is a JPA implementation, has been added in persistence.xml. For the DataSource configuration, the registered context:property-placeholder was used, when the project was created, to move the bean configuration value to the outside as a property file. So, if you want to change the DB to a different one, change it to the configurations compatible with the DB that is will use the contents of database.properties file.

Adding an Entity

When creating an entity, you can select one from the two previously mentioned architecture types. In this example, I will use the class type architecture, which is used often in Java. Enter the following in the field.

entity --class ~.domain.Book --activeRecord false

Type “ent” and press Ctrl+Space. The keyword “entity” will be automatically completed. Press Ctrl+Space again, and “--class” will be automatically added. You need to enter “~.domain.Book” manually. The character “~” here stands for the basic package that was configured when Spring Roo project was created. Enter these commands and run them to create as an active record pattern. Since we want to create a class type structure here, type “” then press Ctrl+Space. The list of options that can be used additionally will be generated. You can select activeRecord option from this list. Then enter Ctrl+Space again to generate the list of activeRecord option values, and choose false.

Figure 6: Adding an Entity.

Figure 6: Adding an Entity.

A domain class called “Book” has been created, along with two AspectJ files. Let’s look at the code created here.

package whiteship.domain;

import org.springframework.roo.addon.entity.RooJpaEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooJpaEntity
public class Book {
}

It seems to be an empty class with three annotations attached to it. But in this class, toString() and getter/setter is ready to be auto-generated. @RooJavaBean and @RooToString fill the role. @RooJpaEntity adds the necessary ID, version member variables and such for JPA entity. So after creating the main method inside the Book class and creating the Book object, setId/getID and setVersion/getVersion can be verified.

@RooJavaBean
@RooToString
@RooJpaEntity
public class Book {
    public static void main(String[] args) {
        Book book = new Book();
        book.setId(1l);
        book.getVersion();
    }
}

You might be wondering how this happened. We will come back to this later, but let’s complete the application first.

Adding a Field

The main method was created as a test, so let’s delete the codes and add a field. Enter the following to the Roo Shell.

field string --fieldName name --class whiteship.domain.Book

Then the Book class codes will change as the followings:

@RooJavaBean
@RooToString
@RooJpaEntity
public class Book {
    private String name;
}

Of course, this is simple enough and can be coded directly without using Roo Shell, but I wanted to show you how you can use this feature. Here are the commands used in Roo Shell so far.

jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY entity --class ~.domain.Book --activeRecord false field string --fieldName name --class whiteship.domain.Book

You can gather these commands and reuse them as a script file. After gathering the Roo commands, create a script file and save it in “sample.roo” format to run the scripts by using “script --file filename” command.

Creating a Repository

Now, let’s make a repository. Run the following command in Roo Shell. Use the auto-complete feature and hints by pressing Ctrl+Space whenever necessary. If you cannot see options like “--entity,” press Ctrl+Space after typing “” to see the additional options.

repository jpa --interface ~.modules.book.BookRepository --entity ~.domain.Book

@RooRepositoryJpa(domainType = Book.class)
    public interface BookRepository {
}

At this moment, basic CRUD and data access operation for searching are implemented. The functions that almost always need to be implemented can be implemented by using Spring Data JPA.

Implementing a Service

We will make a service now. Run the following command in Roo Shell.

service --interface ~.modules.book.BookService --entity ~.domain.Book

You should be quite familiar with the Roo commands by now. You can probably predict the result codes to a certain degree as well. As expected, there are not many codes.

@RooService(domainTypes = { whiteship.domain.Book.class })
public interface BookService {
}

public class BookServiceImpl implements BookService {
}

With this, the implementation of the entity, repository and service is done.

Implementing a Controller

Currently, a web column for Roo can be implemented by using three technologies. The codes can be generated with GWT, Spring Web Flow and Spring MVC. Here, we will generate Spring MVC codes. Run the following command in Roo Shell.

web mvc setup

Doing so will add the necessary dependency to Spring MVC, add Spring web configuration and create various resources required for the basic view. Many features are added at this time. You can check webmvc-config.xml to see which features have been added. Now, let’s generate controller code. Run the following command in Roo Shell. The command line is long, but if you use Ctrl+Space, you should have no problem entering the command.

web mvc scaffold --class ~.modules.book.BookController --backingType ~.domain.Book --path /book

Run this command, and you are ready to run the web application.

Running a Web Application

There are several ways to run a web application from STS. While you can use the servers view, if you have progressed this far, you can see that the tomcat and jetty plugins are installed in pom.xml. Run the application by using the jetty maven plugin. Right-click Project and click Run As -> Maven Build, and enter “jetty:run” in the Goal field, then click Run.

Once the server starts, just enter http://localhost:8080 in the browser, and you will see the 404 error page as well as the link to roo_sample application link. If you like typing, of course, you can enter the entire “http://localhost:8080/project_name" yourself.

Figure 7: Running a Web Application.

Figure 7: Running a Web Application.

Let’s check the basic CRUD functions in this application. They should work fine.

All the Magic is in ITD & Mixin

Here are the Java codes generated so far.

Figure 8: Project code structure.

Figure 8: Project code structure.

In these very few files, there are only a few lines of codes, as you can see. You can say that there are none of them. How can these basic CRUD functions work with only a few annotations? If you have experience in making frameworks that provide these options, you would know these functions are not so complicated. I also have experience where I created a framework providing the basic CRUD functions by using GenericDao, GenericService, GenericController, etc. and just declaring the class and interface. While it was good to create the basic CRUD functions quickly, I always had some frustrations because of the excessive “inheritances.” The interface and class provided by the framework from every module controller, service and DAO codes had to be inherited. Since the inheritance had to be accepted, the controller, service and DAO were no longer POJO class, and as the Generic type declaration for the class declaration part were too complicated, the code readability decreased as well. However, Spring Roo solved this problem very neatly.

In AspectJ, there is a feature called “Inter-Type Declaration (ITD),” also referred to as “Mixin”. This feature is not a concept existing only in AspectJ, but a concept that is commonly used in a dynamic language. As Java generally supports only singular inheritance, it cannot inherit multiple common features. In Mixin, on the other hand, features are created to be commonly used by several objects. These features can be added by inserting them into the objects. Spring Roo uses this kind of ITD. Using ITD does not require inheritance anymore. Since the codes generated by the user and the codes provided by Spring Roo can be completely separated, you can still generate codes with Spring Roo after generating codes with Spring Roo and changing them. You can hide the basic codes that need to be generated with Spring Roo’s ITD, and leave only the business logic related codes.

If you are curious which codes are added to ITD, it can be checked from the cross reference view.

Figure 9: Cross Reference View.

Figure 9: Cross Reference View.

This is the cross reference screen when the editor opened BookController class. You might be wondering to which AspectJ file these codes are added. AspectJ file is also created by Spring Roo, and those codes are basically hidden. This is to let you focus only on the business logic related codes, but you can change the corresponding codes to change the basic CRUD functions if necessary. It is easy to find AsepctJ file. Click the inverted triangle-shaped menu on the upper right hand corner of Package Explorer, then click Filters.

Figure 10: Finding AspectJ file.

Figure 10: Finding AspectJ file.

Initially, “Hide generated Spring Roo ITDs” is checked. Disable it, then click OK to display AspectJ file in Package Explorer.

Figure 11: View AspectJ file in Package Explorer.

Figure 11: View AspectJ file in Package Explorer.

I will wrap up the introduction to Spring Roo here.

By Baek Kee Seon, Web Platform Development Lab, NHN Corporation.



comments powered by Disqus