Sunday, December 19, 2010

Spring 3 MVC - DynamicJasper Integration Tutorial

In this tutorial we will integrate DynamicJasper with a simple Spring 3 MVC application. We will provide a custom data source where DynamicJasper will retrieve its data. The application will be layered so that we can easily modify the features or implementations of our application.

What is DynamicJasper?
DynamicJasper (DJ) is an open source free library that hides the complexity of Jasper Reports, it helps developers to save time when designing simple/medium complexity reports generating the layout of the report elements automatically.

Source: http://dynamicjasper.com/

What is JasperReports?
JasperReports is the world's most popular open source reporting engine. It is entirely written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

Source: http://jasperforge.org/projects/jasperreports

Similar with our previous tutorial. We will setup our Spring 3 MVC application first. If you need a review with Spring MVC, I suggest you read the other tutorials I've posted. Or you can also Google for related tutorials.

Here's a screenshot of the report document that we will be generating:

This is just basic. You can add and show more features with Jasper and DynamicJasper. For now, we'll stick with the basics.

Our first task is to setup the main controller that will handle the download request.

MainController

This controller declares two mappings:
/download - for showing the download page
/download/xls - for retrieving the actual Excel report

Examine the doSalesReportXLS() controller method. It has a reference to a download service named downloadService. This service handles the actual report processing. Later, we'll discuss that in-depth.

The /download mapping will display the downloadpage view which resolves to /WEB-INF/jsp/downloadpage.jsp

downloadpage.jsp

This is a simple JSP. It has an HTML link for downloading the report. Notice the URL points to /krams/main/download/xls. The same mapping we have in the MainController.

Here's a screenshot of this page:

Next, we enable Spring MVC in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams

In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml

This XML config declares a view resolver. All references to a JSP name in the controllers will map to a corresponding JSP in the /WEB-INF/jsp location.

By convention, we must declare an applicationContext.xml

applicationContext.xml

This XML config declares three beans to activate the Spring 3 MVC programming model.

Let's return back to DynamicJasper.

If you remember back in the MainController we declared a reference to a DownloadService which is automatically injected by Spring.

The DownloadService is a delegate. All reporting processing is handled by this service.

DownloadService

To generate the report, we call the downloadXLS() method. This generates an Excel report. Let's examine further how the report is generated:

1. Retrieve an instance of our datasource:
SalesDAO datasource = new SalesDAO();
JRDataSource ds = datasource.getDataSource();

The datasource can come from a variety of sources like from an in-memory list, database, and alike. Later, we'll show what's inside this SalesDAO

2. Generate the Jasper layout:
ReportLayout layout = new ReportLayout();
DynamicReport dr = layout.buildReportLayout();

The layout is like the template of your report. It's basically the design of how you want the report to look like. Our Jasper layout is actually generated on the fly by DynamicJasper. That's the main purpose of DynamicJasper. It will dynamically, programmatically generate the layout. This is useful for generating tabular reports which are mostly used for professional applications. If you need to manually design or create an artistic layout, I advise you try layouting using Jasper's native JRXML format. DynamicJasper can also use a JRXML template, but that's beyond the scope of this tutorial.

3. Compile the Jasper layout into a JasperReport object:
JasperReport jr = DynamicJasperHelper.generateJasperReport(dr, new ClassicLayoutManager(), params);

The JasperReport object is the compiled version of your layout that can be understood by Jasper. Imagine it like this: the layout is for humans, while the compiled object is for the computer.

4. Create the Jasper print:
JasperPrint jp = JasperFillManager.fillReport(jr, params, ds);

This basically fills the JasperReport with contents from the datasource.

5. Export the report to your desired format. For this tutorial we will export it as an
Excel document.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Exporter exporter = new Exporter();
exporter.export(jp, baos);

Here we pass an instance of a ByteArrayOutputStream and a JasperPrint object.

6. Set the response header and content type:
String fileName = "SalesReport.xls";
response.setHeader("Content-Disposition", "inline; filename="+ fileName);
response.setContentType("application/vnd.ms-excel");
response.setContentLength(baos.size());

Make sure you set the correct contentType.

7. Write the report to the output stream:
writeReportToResponseStream(response, baos);

Now, let's examine the remaining classes.

The ReportLayout
This is a custom wrapper to DynamicJasper's FastReportBuilder. The purpose of this class is to encapsulate the layout of the report. This isn't mandatory. You can remove the contents of buildReportLayout() and place it along with the DownloadService. Take note we're encapsulating a DynamicJasper feature here, not a Jasper. So if you have specific questions about these, make sure to search the DynamicJasper forums.

The Exporter
This is a custom wrapper to Jasper's JRXlsExporter. The purpose of this class is to encapsulate the exporting of the report to different formats. This isn't mandatory. You can remove the contents of export() and place it along with the DownloadService. Take note we're encapsulating a Jasper feature here, not a DynamicJasper. So if you have specific questions about these, make sure to search the Jasper forums.

The datasource
Here we provide a custom datasource made from in-memory list of Sales items. We use the DAO name here to indicate that the data can come from a DAO or other persistence means.

SalesDAO

Our datasource returns a list of Sales. This is a simple Data Transfer Object for containing our data from the database.

Sales

Our application is now finished. We've managed to setup a simple Spring 3 MVC application. Then we added reporting using DynamicJasper. We've divided our application's concerns in various layers: controllers, services, DAO, layout, and exporter so that we can easily change implementation and custom processing. We've also leveraged Spring's MVC programming model via annotation.

To access the download page, enter the following URL:
http://localhost:8080/spring-djasper-integration/krams/main/download


If you want to download the report directly, enter the following URL:
http://localhost:8080/spring-djasper-integration/krams/main/download/xls

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-mvc-dynamicjasper-integration-tutorial/

You can download the project as a Maven build. Look for the spring-djasper-integration.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and Jasper, feel free to read my other tutorials in the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring 3 MVC - DynamicJasper Integration Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Saturday, December 18, 2010

Spring Security 3 - MVC Integration Tutorial (Part 2)

In this tutorial we will add Spring Security 3 support to our previous Spring MVC 3 application. We will create a separate but configurable security layer, and authenticate our users using a custom service provider. This is Part 2 of our Spring Security 3 - MVC Integration Tutorial. If you haven't read part one, make sure to read it first: Spring Security 3 - MVC Integration Tutorial (Part 1)

Note: I suggest reading the following tutorial as well which uses the latest Spring Security 3.1
Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA

What is Spring Security?
Spring Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development. If you're not using Spring for developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity with Spring - and in particular dependency injection principles - will help you get up to speed with Spring Security more easily.

Source: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/introduction.html#what-is-acegi-security
Let's start by creating a special controller that handles the login and logout requests.

LoginLogoutController
package org.krams.tutorial.controller;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Handles and retrieves the login or denied page depending on the URI template
 */
@Controller
@RequestMapping("/auth")
public class LoginLogoutController {
        
 protected static Logger logger = Logger.getLogger("controller");

 /**
  * Handles and retrieves the login JSP page
  * 
  * @return the name of the JSP page
  */
 @RequestMapping(value = "/login", method = RequestMethod.GET)
 public String getLoginPage(@RequestParam(value="error", required=false) boolean error, 
   ModelMap model) {
  logger.debug("Received request to show login page");

  // Add an error message to the model if login is unsuccessful
  // The 'error' parameter is set to true based on the when the authentication has failed. 
  // We declared this under the authentication-failure-url attribute inside the spring-security.xml
  /* See below:
   <form-login 
    login-page="/krams/auth/login" 
    authentication-failure-url="/krams/auth/login?error=true" 
    default-target-url="/krams/main/common"/>*/
  if (error == true) {
   // Assign an error message
   model.put("error", "You have entered an invalid username or password!");
  } else {
   model.put("error", "");
  }
  
  // This will resolve to /WEB-INF/jsp/loginpage.jsp
  return "loginpage";
 }
 
 /**
  * Handles and retrieves the denied JSP page. This is shown whenever a regular user
  * tries to access an admin only page.
  * 
  * @return the name of the JSP page
  */
 @RequestMapping(value = "/denied", method = RequestMethod.GET)
  public String getDeniedPage() {
  logger.debug("Received request to show denied page");
  
  // This will resolve to /WEB-INF/jsp/deniedpage.jsp
  return "deniedpage";
 }
}
This controller declares two mappings:
/auth/login - shows the login page
/auth/denied - shows the denied access page
Each mapping will resolve to a specific JSP page.

Here are the JSP pages:

loginpage.jsp

This is a simple HTML form and input elements. If you need a review, please visit the HTML Forms and Input tutorials from w3schools. We have two text input elements:
j_username
j_password
These are Spring's placeholder for the username and password respectively.

When the form is submitted, it will be sent to the following action URL:
j_spring_security_check
Take note of the EL expression
${error}
This is used for displaying invalid credentials during login. The value is derived from the returned model of the controller. See our controller declaration below.

Next we create the access denied page. This page will be displayed if the user is trying to access an unauthorized page. For example, a regular user tries to access an admin only page will get an access denied page.

deniedpage.jsp


Here's how the JSP pages should look like:

loginpage.jsp


deniedpage.jsp


We've finished the login/logout controller and the associated JSP views. We will now enable Spring Security in our application.

To enable it, we need to the following steps:
1. Add a DelegatingFilterProxy in the web.xml
2. Declare a custom XML config named spring-security.xml

In the web.xml we declare an instance of a DelegatingFilterProxy. This basically filters requests based on the declared url-pattern.

web.xml

Notice the url-patterns for the DelegatingFilterProxy and DispatcherServlet. The Spring Security is placed at the root-path
/*
Whereas, Spring MVC is placed at a sub-path
/krams/*
We also referenced two important XML configuration files:
spring-security.xml 
applicationContext.xml
spring-security.xml contains configuration related to Spring Security.

spring-security.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:security="http://www.springframework.org/schema/security"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/security 
   http://www.springframework.org/schema/security/spring-security-3.0.xsd">
 
 <!-- This is where we configure Spring-Security  -->
 <security:http auto-config="true" use-expressions="true" access-denied-page="/krams/auth/denied" >
 
  <security:intercept-url pattern="/krams/auth/login" access="permitAll"/>
  <security:intercept-url pattern="/krams/main/admin" access="hasRole('ROLE_ADMIN')"/>
  <security:intercept-url pattern="/krams/main/common" access="hasRole('ROLE_USER')"/>
  
  <security:form-login
    login-page="/krams/auth/login" 
    authentication-failure-url="/krams/auth/login?error=true" 
    default-target-url="/krams/main/common"/>
   
  <security:logout 
    invalidate-session="true" 
    logout-success-url="/krams/auth/login" 
    logout-url="/krams/auth/logout"/>
 
 </security:http>
 
 <!-- Declare an authentication-manager to use a custom userDetailsService -->
 <security:authentication-manager>
         <security:authentication-provider user-service-ref="customUserDetailsService">
           <security:password-encoder ref="passwordEncoder"/>
         </security:authentication-provider>
 </security:authentication-manager>
 
 <!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
 <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

 <!-- A custom service where Spring will retrieve users and their corresponding access levels  -->
 <bean id="customUserDetailsService" class="org.krams.tutorial.service.CustomUserDetailsService"/>
 
</beans>
The elements are self-documenting. If you're using an IDE, like Eclipse or STS, try pointing your mouse to any of these elements and you will see a short description of the element.

Notice that the bulk of the security configuration is inside the http element. Here's what we observe:

1. We declared the denied page URL in the
access-denied-page="/krams/auth/denied"

2. We provided three URLs with varying permissions. We use Spring Expression Language (SpEL) to specify the role access. For admin only access we specified hasRole('ROLE_ADMIN') and for regular users we use hasRole('ROLE_USER'). To enable SpEL, you need to set use-expressions to true

3. We declared the login URL
login-page="/krams/auth/login"

4. We declared the login failure URL
authentication-failure-url="/krams/auth/login?error=true"

5. We declared the URL where the user will be redirected if he logs out
logout-success-url="/krams/auth/login"

6. We declared the logout URL
logout-url="/krams/auth/logout"

7. We declared an authentication-manager that references a custom user-service

8. We declared a custom user-service

9. We also declared an Md5 password encoder:

When a user enters his password, it's plain string. The password we have in our database (in this case, an in-memory lists) is Md5 encoded. In order for Spring to match the passwords, it need's to encode the plain string to Md5. Once it has been encoded, then it can compare passwords.

Let's focus for a moment to the custom user-service.

To allow Spring to use our custom database schema, we need to provide a custom user-service. This service must implement Spring's UserDetailsService interface.

CustomUserDetailsService
package org.krams.tutorial.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.krams.tutorial.dao.UserDAO;
import org.krams.tutorial.domain.DbUser;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

/**
 * A custom service for retrieving users from a custom datasource, such as a database.
 * <p>
* This custom service must implement Spring's {@link UserDetailsService}
 */
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {
 
 protected static Logger logger = Logger.getLogger("service");

 private UserDAO userDAO = new UserDAO();
 
 /**
  * Retrieves a user record containing the user's credentials and access. 
  */
 public UserDetails loadUserByUsername(String username)
   throws UsernameNotFoundException, DataAccessException {
  
  // Declare a null Spring User
  UserDetails user = null;
  
  try {
   
   // Search database for a user that matches the specified username
   // You can provide a custom DAO to access your persistence layer
   // Or use JDBC to access your database
   // DbUser is our custom domain user. This is not the same as Spring's User
   DbUser dbUser = userDAO.searchDatabase(username);
   
   // Populate the Spring User object with details from the dbUser
   // Here we just pass the username, password, and access level
   // getAuthorities() will translate the access level to the correct role type

   user =  new User(
     dbUser.getUsername(), 
     dbUser.getPassword().toLowerCase(),
     true,
     true,
     true,
     true,
     getAuthorities(dbUser.getAccess()) );

  } catch (Exception e) {
   logger.error("Error in retrieving user");
   throw new UsernameNotFoundException("Error in retrieving user");
  }
  
  // Return user to Spring for processing.
  // Take note we're not the one evaluating whether this user is authenticated or valid
  // We just merely retrieve a user that matches the specified username
  return user;
 }
 
 /**
  * Retrieves the correct ROLE type depending on the access level, where access level is an Integer.
  * Basically, this interprets the access value whether it's for a regular user or admin.
  * 
  * @param access an integer value representing the access of the user
  * @return collection of granted authorities
  */
  public Collection<grantedauthority> getAuthorities(Integer access) {
   // Create a list of grants for this user
   List<grantedauthority> authList = new ArrayList<grantedauthority>(2);
   
   // All users are granted with ROLE_USER access
   // Therefore this user gets a ROLE_USER by default
   logger.debug("Grant ROLE_USER to this user");
   authList.add(new GrantedAuthorityImpl("ROLE_USER"));
   
   // Check if this user has admin access 
   // We interpret Integer(1) as an admin user
   if ( access.compareTo(1) == 0) {
    // User has admin access
    logger.debug("Grant ROLE_ADMIN to this user");
    authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
   }

   // Return list of granted authorities
   return authList;
   }
}
This custom service implements the loadUserByUsername() method and provides a getAuthorities() method for retrieving authorities.

The purpose of loadUserByUsername() method is to return an instance of a fully populated Spring User object. It's up to you how you retrieve the data. In this tutorial, we retrieve the user by searching a custom DAO.

The purpose of getAuthorities() method is to translate our custom access level to a Spring Security GrantedAuthority representation. Remember our custom database stores access levels as integers. Spring Security interprets authorities based on GrantedAuthority() representations.

We just perform a simple if-else condition and return the corresponding authority:

Our custom database is accessible through a dummy DAO implementation:

UserDAO
package org.krams.tutorial.dao;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.krams.tutorial.domain.DbUser;

/**
 * A custom DAO for accessing data from the database.
 *
 */
public class UserDAO {

 protected static Logger logger = Logger.getLogger("dao");
 
 /**
  * Simulates retrieval of data from a database.
  */
 public DbUser searchDatabase(String username) {
  // Retrieve all users from the database
  List users = internalDatabase();
  
  // Search user based on the parameters
  for(DbUser dbUser:users) {
   if ( dbUser.getUsername().equals(username)  == true ) {
    logger.debug("User found");
    // return matching user
    return dbUser;
   }
  }
  
  logger.error("User does not exist!");
  throw new RuntimeException("User does not exist!");
 }

 /**
  * Our fake database. Here we populate an ArrayList with a dummy list of users.
  */
 private List internalDatabase() {
  // Dummy database
  
  // Create a dummy array list
  List users = new ArrayList();
  DbUser user = null;
  
  // Create a new dummy user
  user = new DbUser();
  user.setUsername("john");
  // Actual password: admin
  user.setPassword("21232f297a57a5a743894a0e4a801fc3");
  // Admin user
  user.setAccess(1);
  
  // Add to array list
  users.add(user);
  
  // Create a new dummy user
  user = new DbUser();
  user.setUsername("jane");
  // Actual password: user
  user.setPassword("ee11cbb19052e40b07aac0ca060c23ee");
  // Regular user
  user.setAccess(2);
  
  // Add to array list
  users.add(user);
  
  return users;
 }
 
}
This dummy DAO doesn't really connect to a database. It just provides an in-memory list of users. If you just need to setup a simple in-memory user-service, please read my other tutorial Spring Security 3 - MVC: Using a Simple User-Service Tutorial

Furthermore, we use a custom domain object DbUser to represent the user's credentials derived from the database. If you look at the CustomUserDetailsService again, we mapped DbUser to Spring's User object.

What's Spring User?
Models core user information retrieved by a UserDetailsService.

Implemented with value object semantics (immutable after construction, like a String). Developers may use this class directly, subclass it, or write their own UserDetails implementation from scratch.

Source: Spring Security 3 API for User
Here's DbUser:

DbUser
package org.krams.tutorial.domain;

/**
 * User domain
 */
public class DbUser {

 /**
  * The username
  */
 private String username;
 
 /**
  * The password as an MD5 value
  */
 private String password;
 
 /**
  * Access level of the user. 
  * 1 = Admin user
  * 2 = Regular user
  */
 private Integer access;
 
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public Integer getAccess() {
  return access;
 }
 public void setAccess(Integer access) {
  this.access = access;
 }
 
 
}
To access the common page, enter the following URL:
http://localhost:8080/spring-security-integrationkrams/main/common
To access the admin page, enter the following URL:
http://localhost:8080/spring-security-integrationkrams/main/admin
To login, enter the following URL:
http://localhost:8080/spring-security-integrationkrams/auth/login
To logout, enter the following URL:
http://localhost:8080/spring-security-integrationkrams/auth/logout

If you like to disable Spring Security in this application, just remove the following configuration in the web.xml:

That's it. We got a working Spring MVC 3 application that's secured by Spring Security. We've also managed to authenticate our users using a custom data provider.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring3-security-mvc-integration-tutorial/

You can download the project as a Maven build. Look for the spring-security-integration.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and Spring Security, feel free to read my other tutorials in the Tutorials section.

References:
Spring Security 3.1.0.M2 API
Spring Security Reference Documentation
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3 - MVC Integration Tutorial (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Friday, December 17, 2010

Spring Security 3 - MVC Integration Tutorial (Part 1)

In this tutorial we will integrate Spring Security with a simple Spring 3 MVC application. We will provide a custom data source where Spring Security should retrieve user credentials for authentication. Our design strategy is to make sure that Spring Security and Spring MVC are loosely coupled. This means we should be able to run our MVC application by itself. Then if we decide to add Spring Security we just enable it via XML configuration.

Note: I suggest reading the following tutorial as well which uses the latest Spring Security 3.1
Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA

What is Spring Security?
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications

Spring Security is one of the most mature and widely used Spring projects. Founded in 2003 and actively maintained by SpringSource since, today it is used to secure numerous demanding environments including government agencies, military applications and central banks. It is released under an Apache 2.0 license so you can confidently use it in your projects.

Source: http://static.springsource.org/spring-security/site/

Our first task is to setup our Spring 3 MVC application. We dive directly to the main controller.

MainController

This controller declares two mappings:
/main/admin 
/main/common
Each handler will resolve to a specific JSP page. The common JSP page is accessible by everyone, while the admin page is accessible only by admins. Right now, everyone has access to these pages because we haven't enabled Spring Security yet.

Next we enable Spring MVC in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams
For example, to access the commonpage.jsp, the complete URL should be http://localhost:8080/myapp/krams/main/common

In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml.

This XML config declares a view resolver. All references to a JSP name in the controllers will map to a corresponding JSP in the /WEB-INF/jsp location.

By convention, we must declare an applicationContext.xml

applicationContext.xml

This XML config declares three beans to activate the Spring 3 MVC programming model.

Our web application is almost done. The final piece is to create the JSP pages. We will create a commonpage.jsp for the common view and adminpage.jsp for the admin view.

commonpage.jsp

adminpage.jsp

Here's a screenshot of these JSP pages:





Our Spring 3 MVC application is now finish!

To access the common page, enter the following URL:
http://localhost:8080/spring-security-integration/krams/main/common 

To access the admin page, enter the following URL:
http://localhost:8080/spring-security-integration/krams/main/admin

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring3-security-mvc-integration-tutorial/

You can download the project as a Maven build. Look for the spring-mvc.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

Here's Spring Security - MVC Integration Tutorial (Part 2)
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3 - MVC Integration Tutorial (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share