Source Allies Logo

Sharing Our Passion for Technology

& Continuous Learning

<   Back to Blog

Spring Roo Sample App Tutorial

In this blog, I will start creating a web application used to organize bookmarks. Because only certain bookmarks are of interest to specific groups of people, I will use groups in our LDAP server to control which users see which groups of bookmarks.

The entire blog will be released in posts staggered over time. Part 1 will focus on initial setup of Roo, the core web application and authentication with a directory server. Subsequent posts will refine the Spring Roo application.

What is Roo?

It's a great rapid prototyping tool because prototypes don't need to be scrapped to proceed with fleshing out the application if a prototype proves itself.

Roo gives you Spring best practices, Rails-like scaffolding, an interactive shell, no additional run-time dependencies, and a big productivity boost while not locking you into yet another framework. You can re-use your existing Spring/JPA/Hibernate knowledge, while getting the productivity gains from Roo.

Setting up Roo

  • wget http://s3.amazonaws.com/dist.springframework.org/milestone/ROO/spring-roo-1.0.0.RC3.zip
  • unzip spring-roo-1.0.0.RC3.zip
  • sudo ln -s ~/Frameworks/spring-roo-1.0.0.RC3/bin/roo.sh /usr/bin/roo
  • mkdir ~/Workspaces/intranetlinks; cd ~/Workspaces/intranetlinks

Starting our Project

Once in your new project directory, type 'roo'. Then once in the Roo shell, execute these commands. See this guide for an explanation of what these commands do:

project --topLevelPackage com.sourceallies.links
persistence setup --provider HIBERNATE --database MYSQL
database properties set --key database.password --value password
database properties set --key database.username --value username
database properties set --key database.url --value jdbc:mysql://localhost:3306/intranetlinks

entity --name ~.domain.LinkCategory
field string name --notNull --sizeMin 1 --sizeMax 255

entity --name ~.domain.Link
field string name --notNull --sizeMin 1 --sizeMax 60
field string url --notNull --sizeMin 1 --sizeMax 255
field string ldapSecurityGroup --notNull --sizeMin 1 --sizeMax 60
field reference --class ~.domain.Link --fieldName category --type ~.domain.LinkCategory

logging setup --level DEBUG

controller scaffold --name ~.web.LinkCategoryController --entity ~.domain.LinkCategory
controller scaffold --name ~.web.LinkController --entity ~.domain.Link

finder list --class com.sourceallies.links.domain.Link
finder add --finderName findLinksByCategory --class ~.domain.Link

security setup
test integration
perform test
perform eclipse

Then of course, create your local database inside the MySQL shell:

create database intranetlinks;
create user 'username'@'localhost' IDENTIFIED BY 'password';
grant all privileges on intranetlinks.* to 'username'@'localhost' with grant option;

Next, unless you're using Roo 1.0.0.RC4 (not available at the time of this blog post), you'll need to add the following config to near the bottom of your pom.xml (to fix this bug).

<profiles>
       <profile>
 <id>jaxb</id>
       <activation>
            <jdk>1.5</jdk>
        </activation>
        <dependencies>
               <dependency>
                    <groupId>javax.xml.bind</groupId>
                    <artifactId>jaxb-api</artifactId>
                    <version>2.1</version>
                </dependency>
               <dependency>
                    <groupId>com.sun.xml.bind</groupId>
                    <artifactId>jaxb-impl</artifactId>
                    <version>2.1.3</version>
                </dependency>
         </dependencies>
  </profile>
</profiles>

Then pull the JAXB JAR into your build by executing this maven command (outside of the Roo shell):

mvn package clean

Finally, per a prior blog, replace the body of your src/main/resources/META-INF/spring/applicationContext-security.xml with this:

    <http>
    	<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
        <logout logout-url="/static/j_spring_security_logout"/>
        <intercept-url pattern="/admin/**" access="ROLE_ADMIN"/>
        <intercept-url pattern="/member/**" access="IS_AUTHENTICATED_REMEMBERED" />
        <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/static/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/images/**" filters="none" />
        <intercept-url pattern="/styles/**" filters="none" />
	<intercept-url pattern="/link/form" access="ROLE_INTRANETLINKS-ADMINS" />
	<!-- We're doing REST, only allow GETs to normal users -->
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="DELETE"/>
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="POST"/>
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="PUT"/>
        <intercept-url pattern="/link/**" access="IS_AUTHENTICATED_REMEMBERED" />
        <intercept-url pattern="/login/**" filters="none" />
	<intercept-url pattern="/**" access="ROLE_USERS"  />
	 <anonymous />
    </http>

    <ldap-server id="ldapServer" url="ldap://yourdirectoryserver:338899/" />

   <authentication-manager>
    <ldap-authentication-provider server-ref="ldapServer"
       user-search-base="ou=people,dc=sourceallies,dc=com"
       user-search-filter="(uid={0})"
       group-role-attribute="cn"
       group-search-base="ou=groups,dc=sourceallies,dc=com"
       group-search-filter="(memberUid={1})"
       role-prefix="ROLE_" />
   </authentication-manager>

Note that in Spring Security 3.0, Authentication Providers must now be declared from within the authentication-manager element (more information here).

Then add a few more dependencies to your pom.xml

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>org.springframework.security.ldap</artifactId>
        <version>3.0.0.RC1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core</artifactId>
        <version>1.3.0.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core-tiger</artifactId>
        <version>1.3.0.RELEASE</version>
    </dependency>

This will allow you to use Spring LDAP and also conditionally render pieces of your application like this:

<security:authorize ifAllGranted="ROLE_SUPERVISOR">
    <li id="finder_findlinksbycategory_menu_item">
        <c:url value="/link/find/ByCategory/form" var="finder_findlinksbycategory_menu_item_url"/>
        <a href="${finder_findlinksbycategory_menu_item_url}">
            <spring:message arguments="Category" code="global.menu.find"/>
        </a>
    </li>
</security:authorize>

Finally, run the following command to startup Tomcat and start refining your UI.

mvn tomcat:run