Deploying Grails Application to CloudFoundry

July 24, 2011 Leave a comment

Here I am sharing the steps to deploy Grails Application to CloudFoundry.

Step 1: Install CloudFoundry Plugin

install-plugin cloud-foundry

Step 2: Configure Credential
Create $HOME/.grails/settings.groovy and configure your CloudFoundry credential there. Putting your credential in settings.groovy makes it available to all your Grails projects. The alternative is to configure in BuildConfig.groovy or Config.groovy which makes it available to that specific project only. Using settings.groovy is better as it keep the credential out of source control. In Windows, $HOME= C:\Users\<username>.

grails.plugin.cloudfoundry.username = ''
grails.plugin.cloudfoundry.password = ''

Step 3: Verify Credential
Check whether the credential is working by executing the following command:

cf-info

You will see a similar print out as shown below

VMware's Cloud Application Platform
For support visit support@cloudfoundry.com
Target: http://api.cloudfoundry.com (v0.999)
User:     <your_username>
Usage:    Memory   (128.0M of 2.0G total)
Services (0 of 16 total)
Apps     (1 of 20 total)

Step 4: Deploy Grails Application
Now, deploy your Grails application by executing the following command:

cf-push

If you decided to deploy your application with a different name, use the option –appname

cf-push --appname=other-name

During deployment you will be prompted with the following questions. The mysql service can be provisioned at later stage using the cf-create-service.

You're running in the development environment but haven't specified a war file, so one will be built with development settings. Are you sure you want to do proceed? ([y], n)
Application Deployed URL: 'grails-qotd-extjs.cloudfoundry.com'?
Would you like to create and bind a mysql service? ([y], n)

Step 5: Verify Application Deployment
To check your deployment, execute the command below:

cf-apps

You will see a similar print out as shown below

+-----------------+----+---------+----------------------------------+----------+
| Application     | #  | Health  | URLs                             | Services |
+-----------------+----+---------+----------------------------------+----------+
| <app-name>      | 1  | RUNNING | <app-name>.cloudfoundry.com      |          |
+-----------------+----+---------+----------------------------------+----------+

Categories: Groovy & Grails Tags: ,

Customizing Spring Security Login using ExtJS in Grails Apps

July 20, 2011 3 comments

I’ve been wanting to learn Grails for sometime and finally had the time to try out this web application framework. Grails is a very impressive framework, it is really about productivity and simplicity. Some of the benefits are scaffolding, testing framework, easy to create plugin and seamless integration with Spring and Hibernate. As part of my first attempt, I am customizing the Spring Security Login using ExtJS in a simple Grails application. The focus here is on the integration with Spring Security and ExtJS rather than Grails. I am using SpringSource Tool Suite (STS 2.7.1) to develop the demo application. The application is to display Quotes randomly and ability to maintain them. Let’s begin the integration and customization steps.

Step 1: Install the Spring Security Plugin

Spring Security is not built-in Grails, to begin the integration execute the following Grails command.

install-plugin spring-security-core

Step 2: Generate Domain Classes

 This step will create basic domain classes needed to store user information and the controller that handle the authentication. After executing the command below you will see several files being added to your project, such as LoginController, auth.gsp, denied.gsp, User, Role, UserRole, RequestMap. The domain class name for user and role is up to you to define and if you have an existing user domain, you must decide to integrate it (possibly by extending your domain class to the generated user class). Just a note that the RequestMap is an option and will look into it at later step.

s2-quickstart org.xaab.qotd User Role RequestMap

Step 3: Define URL mapping for login and logout

In order the make the login and logout controller reachable, the URL mappings must be added into UrlMapping.groovy

class UrlMappings {
	static mappings = {
		...
		"/login/$action?"(controller: "login")
		"/logout/$action?"(controller: "logout")
	}
}

Step 4: Add Access Control to the Controller

The need for this step depends on how you wants to control the access. You can use @Secured annotation to limit access to certain part of the application. In this example, I am not using annotation to limit the access, instead I define dynamics request maps which is shown in the Step 5. The following code is just an example of how @Secured can be used in the controller.

package org.example
import grails.plugins.springsecurity.Secured

class PostController {
    ...
    @Secured(['ROLE_USER'])
    def followAjax = { ... }

    @Secured(['ROLE_USER', 'IS_AUTHENTICATED_FULLY'])
    def addPostAjax = { ... }

    def global = { ... }

    @Secured(['ROLE_USER'])
    def timeline = { ... }

    @Secured(['IS_AUTHENTICATED_REMEMBERED'])
    def personal = { ... }
}

Step 5: Add Dynamic Request Maps

The request maps class was generated in Step 2 and used to limit access by defining the access control at the URL. Here I create the request map in BootStrap.groovy for demo purpose, in your actual application this may be defined in configuration file or database. I don’t think you should choose between using annotation and request map. You can strike balance by implementing both to handle general and fine-grain access control.

import org.xaab.qotd.*

class BootStrap {
    def springSecurityService

    def init = { servletContext ->
		...
		new Requestmap(url: '/**', configAttribute: 'IS_AUTHENTICATED_FULLY').save()
		new Requestmap(url: '/quote/**', configAttribute: 'ROLE_ADMIN,IS_AUTHENTICATED_FULLY').save()

		new Requestmap(url: '/js/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/css/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/images/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/ext-4.0.2/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/quote/random', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/login/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		new Requestmap(url: '/logout/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()
		...
    }
    def destroy = {
    }
}

Step 6: Amend related GSP to add login and logout link

Amend related GSP (random.gsp) to ensure you have the login and logout link. Since I used scaffolding, I must install the templates and ensure the GSP templates are modified.  Once scaffolding templates are installed, you will see the folders /src/templates/scaffolding/**. The files I modified in this sample application are create.gsp, edit.gsp, list.gsp & show.gsp.

install-templates

...</pre>
<div class="nav"><span class="menuButton">Next Quote</span> <span class="menuButton">Admin</span> <span class="menuButton">Login</span> <span class="menuButton"> (Logout)</span></div>
<pre>...

Step 7: Customize the auth.gsp to Add ExtJs Login Form

By now the integration is completed and if you used the test data in Step 10, you will be able to see the default login page. In order to customize it, copy the ExtJS source into /web-app and in this sample application I am using ExtJS 4.0.2. Start the customization by modifying the auth.gsp as shown below. Do take note on the naming of the fields as it is the convention used in Spring Security.

Login<script type="text/javascript" src="${resource(dir:'ext-4.0.2',file:'ext-all.js')}"></script><script type="text/javascript">// <![CDATA[
		var defLoginUrl = '${postUrl}';
		var homeUrl = '${createLink(uri: "/quote/random")}';

// ]]></script>
<script type="text/javascript">// <![CDATA[
Ext.onReady(function(){
	Ext.QuickTips.init();

	var loginForm = Ext.create('Ext.form.Panel',{
			url: defLoginUrl,
			title: 'Login',
			renderTo: 'login',
			frame: true,
			cls: 'my-form-class',
			width: 350,
			items: [{
					xtype: 'textfield',
					fieldLabel: 'Login',
					name: 'j_username'
			},{
					xtype: 'textfield',
					inputType: 'password',
					fieldLabel: 'Password',
					name: 'j_password'
			}, {
				xtype: 'checkbox',
				fieldLabel: 'Remember Me?',
				name: '_spring_security_remember_me',
				checked: false
			}],
			buttons: [{
					id: 'lf.btn.login',
					text: 'Login',
					handler: function() {
						fnLoginForm(loginForm);
					}
				},{
					id: 'lf.btn.reset',
					text: 'Reset',
					handler: function() {
						fnResetForm(loginForm);
					}
			}]
	});

});

function fnLoginForm(theForm)
{
	theForm.getForm().submit({
		success: function(form, action) {
			Ext.Msg.alert('Success', 'Login Successful!', function(btn, text) {
				if (btn == 'ok') {
					window.location = homeUrl; //optionally this can be part of the data return by the server.
				}
			});
		},
		failure: function(form, action) {
			Ext.Msg.alert('Warning', action.result.error);
		}
	});
} //end fnLoginForm

function fnResetForm(theForm)
{
	theForm.getForm().reset();
} //end fnResetForm
// ]]></script>

Step 8: Configure Authentication Success and Failure Handler

The ExtJS login form will perform HTTP post to submit the login data however it expects JSON data as response. The default method in the LoginController will not be able to handle this, thus you must define your own handler. Add your handler into Config.groovy as shown below. The handlers are implemented in LoginController in the next step.

grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/login/authSucccessExtJs'
grails.plugins.springsecurity.successHandler.alwaysUseDefault = true
grails.plugins.springsecurity.failureHandler.defaultFailureUrl = '/login/authFailExtJs?login_error=1'

Step 9: Implement the Handler in LoginController

After adding the handler, I suggest you remove or comment out the other methods to ensure they are not accessible.

import grails.converters.JSON

import javax.servlet.http.HttpServletResponse

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

class LoginController {

	/**
	 * Dependency injection for the authenticationTrustResolver.
	 */
	def authenticationTrustResolver

	/**
	 * Dependency injection for the springSecurityService.
	 */
	def springSecurityService
	...
		/**
	 * The ExtJS Authentication success handler
	 */
	def authSucccessExtJs = {
		render([success: true, username: springSecurityService.authentication.name] as JSON)
	}

	/**
	 * The ExtJS Authentication failure handler
	 */
	def authFailExtJs = {
			def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
			String msg = ''
			def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
			if (exception) {
				if (exception instanceof AccountExpiredException) {
					msg = SpringSecurityUtils.securityConfig.errors.login.expired
				}
				else if (exception instanceof CredentialsExpiredException) {
					msg = SpringSecurityUtils.securityConfig.errors.login.passwordExpired
				}
				else if (exception instanceof DisabledException) {
					msg = SpringSecurityUtils.securityConfig.errors.login.disabled
				}
				else if (exception instanceof LockedException) {
					msg = SpringSecurityUtils.securityConfig.errors.login.locked
				}
				else {
					msg = SpringSecurityUtils.securityConfig.errors.login.fail
				}
			}

			render([success: false, error: msg] as JSON)
	}
}

Step 10: Setup Test Data

So, you have integrated your Grails application, customized the login form using ExtJS. Now, setup the test data in BootStrap.groovy and launch the application (http://localhost:8080/grails-qotd-extjs).

import org.xaab.qotd.*

class BootStrap {
    def springSecurityService

    def init = { servletContext ->
		new Quote(author: "Unknown", content: "If you think sunshine brings you happiness, then you haven’t danced in the rain.").save()
		new Quote(author: "Lao Tzu", content: "An ant on the move does more than a dozing ox.").save()
		new Quote(author: "Tony Robbins", content: "It not knowing what to do, it’s doing what you know.").save()
		new Quote(author: "Bruce Lee", content: "Simplicity is the key to brilliance.").save()

		...

		def userRole = Role.findByAuthority('ROLE_USER') ?: new Role(authority: 'ROLE_USER').save(failOnError: true)
		def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role(authority: 'ROLE_ADMIN').save(failOnError: true)

		def adminUser = User.findByUsername('admin') ?: new User(
			username: 'admin',
			password: springSecurityService.encodePassword('admin'),
			enabled: true).save(failOnError: true)

		if (!adminUser.authorities.contains(adminRole)) {
			UserRole.create(adminUser, adminRole)
		}
    }
    def destroy = {
    }
}

Hope this tutorial helps and happy coding!

download source

References:

Custom Number Formatting in Flex.

July 12, 2011 3 comments

A quick intro before I start. I’m Rudy and I’m a new contributor here.

Lately I’m doing a lot of flex programming and although Adobe Flex is quite mature (It has reached version 4.5 this year), I feel that the language is still lack of support to business. One of the missing feature is Number/Currency Formatting that accepts pattern as a template format.

In Flex, we have <mx:CurrencyFormatter>[link]. However it does not accept Pattern. In addition, it’s implemented as a tag which does not allow to be invoked in ActionScript. However, in Java this capability is being implemented nicely using DecimalFormat [link].

Based on the reasons above I decided to create my own formatter that can be called from both ActionScript and mxml. Note that since this is just a quick hack, the code maybe a little bit messy.

Currently it able to cater currency symbol, percentage, # and 0. For example :

  • 1234.56 with pattern #,###.## has output 1,234.56
  • 1234.56 with pattern USD#,###.## has output USD 1,234.56
  • 1234.56 with pattern $#,###.## has output $ 1,234.56
  • 1.23 with pattern 000.000 has output 001,230
  • -12.34 with pattern USD0##.## has output -USD 012.34
  • 123.45 with pattern ###.##% has output 123.45%

Usage :

var nf:NumberFormatter = new NumberFormatter();
var number:Number = 1234.56;
nf.formatString = "#,###.##";
var resultFormatted:String = nf.format(number);

You can download the full code in http://goo.gl/xhBtM

Display JSON Data using ExtJS 4 Store

July 9, 2011 4 comments

I am sharing a short example of how to display JSON data using ExtJS 4 Store. In previous version of ExtJS, there is a small helper class call JsonStore which is used to simplify creation Stores from JSON data. In ExtJS 4 the class is no longer there. In this example, I am retrieving USGS data as JSON and display it in Grid as shown below.

USGS Data in Gri

As shown below in line 20, I use proxy of type JSONP in Ext.data.Store to retrieve the JSON data.

Ext.onReady(function(){
  Ext.define('UsgsList', {
    extend: 'Ext.data.Model',
    fields: [
       {name: 'fid',       type: 'int'},
       {name: 'title',     type: 'string'},
       {name: 'description',  type: 'string'},
       {name: 'link',      type: 'string'},
       {name: 'pubDate',    type: 'date'},
       {name: 'lat',      type: 'string'},
       {name: 'long',      type: 'string'}
    ],
    idProperty: 'fid'
});

var store = Ext.create('Ext.data.Store', {
    id: 'store',
    model: 'UsgsList',
    proxy: {
       type: 'jsonp',
       url: 'http://query.yahooapis.com/v1/public/yql',
    extraParams: {
       q: 'select * from rss where url="http://earthquake.usgs.gov/earthquakes/catalogs/eqs7day-M2.5.xml"',
       format: 'json'
   },
   reader: {
      root: 'query.results.item',
   }
 }
});

function renderTitle(value, p, record) {
   return Ext.String.format('<a href="{1}" target="_blank">{0}</a>',
   value,
   record.data.link
   );
}

var grid = Ext.create('Ext.grid.Panel', {
   width: 700,
   height: 500,
   title: 'USGS - M2.5+',
   store: store,
   loadMask: true,
   disableSelection: true,
   invalidateScrollerOnRefresh: false,
   viewConfig: {
     trackOver: false
   },
   // grid columns
   columns:[{
      xtype: 'rownumberer',
      width: 50,
      sortable: false
   },{
      id: 'title',
      text: "Title",
      dataIndex: 'title',
      flex: 1,
      renderer: renderTitle,
      sortable: false
   },{
      id: 'pubDate',
      text: "Published Date",
      dataIndex: 'pubDate',
      width: 130,
      renderer: Ext.util.Format.dateRenderer('n/j/Y g:i A'),
      sortable: true
   }],
   renderTo: Ext.getBody()
});

// trigger the data store load
store.load();
});

Categories: Sencha ExtJS Tags:

HTML5 @Google I/O 2011

June 22, 2011 Leave a comment

Just sharing some of the talk/presentations on HTML5 at Google I/O 2011. HTML5 seems to be moving fast and you will see some of the cool stuff in the “HTML5 versus Android” demo,

  • I/O BootCamp 2011: Getting Started with HTML5

 

  • HTML5 Showcase for Web Developers: The Wow and the How

 

  • HTML5 and What’s Next

 

  • GWT + HTML5: A web developers dream!

 

  • HTML5 vs. Android: Apps or Web Mobile Development?

 

  • HTML5 Today with Google Chrome Frame

 

  • Kick-Ass Game Programming with Google Web Toolkit

 

 

Categories: Uncategorized Tags:

Integrating JSR303 with Spring MVC 3 and ExtJS Forms

March 22, 2011 Leave a comment

Previously in Spring MVC and ExtJS Forms I created a simple data entry form and there was no data validation implemented. Typically data validation occurs throughout application layers, from presentation to persistence layer. Here I will be using JSR-303 Bean Validation, where the data validation is defined in the domain model and can be used thoughout application layers. I will walk through how to integrate data validation into Spring MVC and will be using Hibernate Validator 4.x – which is the reference implementation for JSR-303 – to integrate into my previous example.

What is JSR-303?

“This JSR defines a metadata model and API for JavaBean validation. The default metadata source is annotations,
with the ability to override and extend the meta-data through the use of XML validation descriptors.
The validation API developed by this JSR is not intended for use in any one tier or programming model. It is specifically
not tied to either the web tier or the persistence tier, and is available for both server-side application programming,
as well as rich client Swing application developers.” – JSR-303 Specification

The data validation is achieved by defining constraints in the beans. Constraints are defined by a combination of constraint annotation and a list of constraint validation implementations. The constraint annotation can be applied at field-level, property-level (getter), class-level. Currently there are 22 built-in constraints for example @NotNull to check that the annotated value is not null or @Size(min=, max=) to check whether the annotated value lies between the specified range. You can also create your own custom constraint to meet your specific requirement. The concept here is similar to database constraints where the constraint can be applied to table column.

For now, I will walk through how to use the built-in constraints only. As usual, I will start with the configuration required to make the project work. Open the Maven pom.xml and add the following dependencies and repository:

<!-- JSR 303 with Hibernate Validator -->
<dependency>
	<groupId>javax.validation</groupId>
	<artifactId>validation-api</artifactId>
	<version>1.0.0.GA</version>
</dependency>
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>4.1.0.Final</version>
</dependency>
...
<!-- For Hibernate Validator Repository -->
<repository>
	<id>org.jboss.repository.release</id>
	<name>JBoss Maven Release Repository</name>
	<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
	<snapshots><enabled>false</enabled></snapshots>
</repository>

In the example, the form is submitted to HomeController and the form is mapped to PersonalContact bean. I added 3 built-in constraints into the PersonalContact bean, @NotBlank, @Patter (using regular expression) and @Email. When message is not define in the constraint annotation, the validator will assign a default value. The second part of the code below shows the validation process. The HomeController is autowired to the Validator bean and the validation() is executed inside the add().

public class PersonalContact implements Serializable
{
	private static final long serialVersionUID = 1L;
	private Long id;

	@NotBlank(message="Please enter name")
	private String name;
               // using regular expression to define the constraint
	@Pattern(regexp="[0-9]{8}", message="Please enter 8 digit phone number")
	private String phone;

	@Email
	private String email;

	public PersonalContact() {}

	public PersonalContact(Long id, String name, String phone, String email) {
		super();
		this.id = id;
		this.name = name;
		this.phone = phone;
		this.email = email;
	}
	//getter & setter
}

@Controller
public class HomeController
{
	@Autowired
	private Validator validator;

	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		return "home";
	}

	@RequestMapping(value="/load", method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> load(PersonalContact input) {
	...
	}

	@RequestMapping(value="/add", method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> add(PersonalContact input, HttpSession session) {
		Map<String, Object> data = new HashMap<String, Object>();

		Set<ConstraintViolation<PersonalContact>> failures = validator.validate(input);
		if (!failures.isEmpty()) {
			//structure the response for ExtJS Form.
			data.put("success",Boolean.FALSE);
			data.put("errors", validationMessages(failures));
			data.put("errorMessage", "Add Failed!");
		} else {
			session.setAttribute(input.getName(), input);
			data.put("success",Boolean.TRUE);
		}

		return data;
	}
	//iterate to retrieve validation errors and store it in HashMap
	private Map<String, String> validationMessages(Set<ConstraintViolation<PersonalContact>> failures) {
		Map<String, String> failureMessages = new HashMap<String, String>();
		for (ConstraintViolation<PersonalContact> failure : failures) {
			failureMessages.put(failure.getPropertyPath().toString(), failure.getMessage());
		}
		return failureMessages;
	}
}

Since I used ExtJS forms, I must return JSON response in a specific format and the errors are mapped to the field and displayed as quicktips.


The spring-mvc-forms project is updated and available for download at myGit. Hope you find it useful. Happy coding! :)

References

{
   success: true,
   errors: { field1: 'error for field 1',
                 field2: 'error for field 2',
   	   ...
   }
}

Customizing Spring Security Login using ExtJS

March 20, 2011 4 comments
This tutorial will walk through the steps to customize Spring Security login page using Ext JS form. There are a few steps need to be done to customize the login form, because Ext JS form does not work in the same way as the standard HTML form. By default Ext Forms are submitted through Ajax and response packets are assumed to be JSON. I will be adding the customize login page into my previous example (in Spring 3 MVC and ExtJS Forms). I will walk through:
  1. configuration required to integrate with Spring Security 3 (3.0.5 to be exact),
  2. customize login page, and
  3. implement login handler to return JSON.
Step 1: Configuration required to integrate with Spring Security. If you are using the Spring MVC project template from STS, you will need to add dependencies to Spring Security by modifying the Maven pom.xml file. Add the following property and dependencies:

<properties>
	...
	<org.springframework.security-version>3.0.5.RELEASE</org.springframework.security-version>
	...
</properties>
<dependencies>
      ...
      <!-- Spring Security -->
      <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${org.springframework.security-version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
      </dependency>
    <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${org.springframework.security-version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
      </dependency>
    <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${org.springframework.security-version}</version>
      </dependency>
    <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${org.springframework.security-version}</version>
      </dependency>
      ...
</dependencies>

Now, create security context file. Let’s name it applicationContext-security.xml. For this tutorial I used in memory user service and declare user id and password as part of the authentication manager. In the configuration, I declared the form login URL and the login handler. The login page is pointing to the login controller which forward to login.jsp. While login handler beans are used to return JSON to Ext JS form. The interceptor defined that every URL must be authenticated except for login and resources (images,css,javascript). Remember to set the access permission of login page to permit all to avoid endless loop. It is a good practice to default all URL to isAuthenticate() and only permit the necessary URL.

<http use-expressions="true">
    <intercept-url pattern="/resources/**" filters="none"/>
    <intercept-url pattern="/app/login.do" access="permitAll()" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
      <form-login login-page="/app/login.do"
      			authentication-success-handler-ref="loginSuccessHandler"
      			authentication-failure-handler-ref="loginFailureHandler" />
      <logout invalidate-session="true" logout-success-url="/" logout-url="/j_spring_security_logout"/>
      <remember-me key="xaab.springmvclogin" />
      <session-management session-fixation-protection="newSession" >
          <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
      </session-management>
</http>
<!-- all password = password -->
<authentication-manager>
     <authentication-provider>
      	<password-encoder hash="md5" />
        <user-service>
            <user name="user1" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
            <user name="user2" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_USER,ROLE_TELLER" />
            <user name="user3" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_USER" />
            <user name="user4" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_USER" />
         </user-service>
      </authentication-provider>
</authentication-manager>

<beans:bean id="loginSuccessHandler" class="org.xaab.springmvc.LoginSuccessHandler" />
<beans:bean id="loginFailureHandler" class="org.xaab.springmvc.LoginFailureHandler" />

In order to activate the above configuration, you need to include the security context into the context parameter and include the security filter in web.xml.

<!-- part of web.xml -->
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/spring/root-context.xml
		/WEB-INF/spring/applicationContext-security.xml
	</param-value>
</context-param>

<filter>
      <filter-name>springSecurityFilterChain</filter-name>
      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Step 2: Customize login page. There are basic 3 elements in the default login page generated by Spring Security. They are:
  1. Form action: j_spring_security_check
  2. User name input: j_username
  3. Password input: j_password
Those are the form fields needed for the Ext login form. The UsernamePasswordAuthenticationFilter watches for a request to the virtual URL (/j_spring_security_check) used for form-based authentication, and attempts to authenticate the user. If necessary, You can customize it to use your own controller to authenticate. Take a look at the spring-mvc-login.js below. One thing to note is, this example redirect to a default URL upon successful login. It is done by modifying the window.location.

Ext.onReady(function(){
	Ext.QuickTips.init();

	var loginForm = new Ext.FormPanel({
		url: defLoginUrl,
		title: 'Login',
		renderTo: Ext.getBody(),
		frame: true,
		cls: 'my-form-class',
		width: 350,
		items: [{
			xtype: 'textfield',
			fieldLabel: 'Login',
			name: 'j_username'
	              },{
			xtype: 'textfield',
			inputType: 'password',
			fieldLabel: 'Password',
			name: 'j_password'
		}, {
			xtype: 'checkbox',
			fieldLabel: 'Remember Me?',
			name: '_spring_security_remember_me',
			checked: false
		}],
		buttons: [{
			id: 'lf.btn.login',
			text: 'Login',
			handler: function() {
				fnLoginForm(loginForm);
			}
		},{
			id: 'lf.btn.reset',
			text: 'Reset',
			handler: function() {
				fnResetForm(loginForm);
			}
		}]
	});

});
//Submit login and handler response
function fnLoginForm(theForm)
{
theForm.getForm().submit({
	success: function(form, action) {
		Ext.Msg.alert('Success', 'Login Successful!', function(btn, text) {
			if (btn == 'ok') {
				window.location = homeUrl;
			}
		});
	},
	failure: function(form, action) {
		Ext.Msg.alert('Warning', action.result.errorMessage);
	}
});
} //end fnLoginForm

function fnResetForm(theForm)
{
theForm.getForm().reset();
} //end fnResetForm

Step 3: Implement login handler to return JSON. Remember the authentication handlers declared in applicationContext-security.xml? now you will need implement it to handle succcess and failure case. For this purpose I used Jackson JSON processor and to include it add the dependency to pom.xml.

<!-- Jackson JSON Processor -->
<dependency>
	<groupId>org.codehaus.jackson</groupId>
	<artifactId>jackson-mapper-asl</artifactId>
	<version>1.7.4</version>
</dependency>

public class LoginSuccessHandler implements AuthenticationSuccessHandler
{
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication auth) throws IOException,
			ServletException {

		ObjectMapper mapper = new ObjectMapper();
		LoginStatus status = new LoginStatus(true, auth.isAuthenticated(), auth.getName(), null);
		OutputStream out = response.getOutputStream();
		mapper.writeValue(out, status);
	}

}

public class LoginFailureHandler implements AuthenticationFailureHandler
{
	public void onAuthenticationFailure(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException auth)
			throws IOException, ServletException {

		ObjectMapper mapper = new ObjectMapper();
		LoginStatus status = new LoginStatus(false, false, null, "Login failed. Try again.");
		OutputStream out = response.getOutputStream();
		mapper.writeValue(out, status);
	}

}
public class LoginStatus
{
  private final boolean success;
  private final boolean loggedIn;
  private final String username;
  private final String errorMessage;

  public LoginStatus(boolean success, boolean loggedIn, String username, String errorMessage) {
    this.success = success;
    this.loggedIn = loggedIn;
    this.username = username;
    this.errorMessage = errorMessage;
  }
}

Time to test drive the code. Lauch http://localhost:8080/spring-mvc-login/ in the browser and you will be redirected to the login page http://localhost:8080/spring-mvc-login/app/login.do.
Some of the things to improve on :
  • Use of SSL
  • Authenticate to LDAP
  • Securing “remember me” using Token.
Hope you find the tutorial useful. Happy coding! :)
Update: the source project is downloadable at myGit.

Spring 3 MVC and ExtJS Forms

March 16, 2011 2 comments

In my previous post Beginning Spring MVC 3, I shared a simple tutorial to start developing Spring MVC 3. It covered the tools required and the steps to setup the project. This tutorial will take a step further and walk through how to work with forms – Ext JS form to be specific – for loading of data and submission of data for processing. I will be assuming that you have the tools and project setup.

Step 1. The model. Here I assumed a single bean will represent the form and data model (for data access/persistence). The attributes in the bean are mapped to the form fields.

public class PersonalContact implements Serializable
{
	private static final long serialVersionUID = 1L;
	private Long id;
	private String name;
	private String phone;
	private String email;

	public PersonalContact() {}

	public PersonalContact(Long id, String name, String phone, String email) {
		super();
		this.id = id;
		this.name = name;
		this.phone = phone;
		this.email = email;
	}

	//regenerate the getter & setter using STS.
}

Step 2. The controller. Using the default “HomeController”, I added 2 methods to handle the load and add request. Both methods have simple implementation to illustrate the interaction between the form and Spring MVC. There is no data access/persistence code implemented here.

@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		logger.info("Welcome home!");
		return "home";
	}

	@RequestMapping(value="/load", method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> load(PersonalContact input) {
		logger.info("Inside load");
		PersonalContact pc = new PersonalContact(1L, "Wowi", "89281932", "wo.wi@abcxyz.com");
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("success",Boolean.TRUE);
		data.put("data", pc);

		return data;
	}

	@RequestMapping(value="/add", method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> add(PersonalContact input, HttpSession session) {
		logger.info("Inside add");

		Map<String, Object> data = new HashMap<String, Object>();

		if (input.getName() == null) {
			data.put("success",Boolean.FALSE);
			data.put("errorMessage", "No Name?");
		} else if (session.getAttribute(input.getName()) != null) {
			data.put("success",Boolean.FALSE);
			data.put("errorMessage", "There is an existing data, unable to add. Please enter a different name");
		} else {
			session.setAttribute(input.getName(), input);
			data.put("success",Boolean.TRUE);
		}

		return data;
	}
}

Step 3. The view. Similar to the controller, I built on the default home.jsp. As you can see there isn’t much code in the JSP. The core UI codes are in the JavaScript (spring-mvc-forms.js). By default the response assumed to be in JSON. Do remember to add the Jackson into the pom.xml and set the header to “Accept” application/json.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
	<link href="<c:url value="/resources/lib/ext-3.3.1/resources/css/ext-all.css" />" rel="stylesheet" type="text/css" />
	<script type="text/javascript" src="<c:url value="/resources/lib/ext-3.3.1/adapter/ext/ext-base.js" />"></script>
	<script type="text/javascript" src="<c:url value="/resources/lib/ext-3.3.1/ext-all.js" />"></script>
	<script type="text/javascript">
		if (Ext.BLANK_IMAGE_URL.substr(0, 5) != 'data:') {
			Ext.BLANK_IMAGE_URL = '<c:url value="/resources/lib/ext-3.3.1/resources/images/default/s.gif" />';
		}
		var loadUrl = '<c:url value="/load" />';
		var addUrl = '<c:url value="/add" />';
	</script>
	<script type="text/javascript" src="<c:url value="/resources/js/spring-mvc-forms.js" />"></script>
	<style type="text/css">
		body {
		  	font: normal 12px helvetica,arial,verdana,tahoma,sans-serif;
		}
		.my-form-class {
			margin:  20px 30px;
		}
	</style>
</head>
<body>
</body>
</html>

Ext.onReady(function(){
	Ext.QuickTips.init();

	var mf = new Ext.FormPanel({
			url: addUrl,
			renderTo: Ext.getBody(),
			frame: true,
			cls: 'my-form-class',
			width: 350,
			items: [{
					xtype: 'textfield',
					fieldLabel: 'Name',
					name: 'name'
			},{
					xtype: 'textfield',
					fieldLabel: 'Phone No.',
					name: 'phone'
			},{
					xtype: 'textfield',
					fieldLabel: 'EMail',
					name: 'email'
			}],
			buttons: [{
					id: 'mf.btn.load',
					text: 'Load',
					handler: function() {
						fnLoadForm(mf);
					}
				},{
					id: 'mf.btn.add',
					text: 'Add',
					disabled: true,
					handler: function() {
						fnUpdateForm(mf);
					}
			},{
					id: 'mf.btn.reset',
					text: 'Reset',
					disabled: true,
					handler: function() {
						fnResetForm(mf);
					}
			}]
	});

});

function fnLoadForm(theForm)
{
	//for the purpose of this tutorial, load 1 record.
	theForm.getForm().load({
		url: loadUrl,
		headers: {Accept: 'application/json, text/javascript, */*; q=0.01'},
    waitMsg: 'loading...',
		params : {
			id: 1
		},
		success: function(form, action) {
			Ext.getCmp('mf.btn.add').setDisabled(false);
			Ext.getCmp('mf.btn.reset').setDisabled(false);
			Ext.getCmp('mf.btn.load').setDisabled(true);
		},
		failure: function(form, action) {
			Ext.Msg.alert('Warning', 'Error Unable to Load Form Data.');
		}
	});
} //end fnLoadForm
function fnUpdateForm(theForm)
{
	theForm.getForm().submit({
		success: function(form, action) {
			Ext.Msg.alert('Success', 'Data is stored in session.');
			form.reset();
		},
		failure: function(form, action) {
			Ext.Msg.alert('Warning', action.result.errorMessage);
		}
	});
} //end fnUpdateForm
function fnResetForm(theForm)
{
	theForm.getForm().reset();
	Ext.getCmp('mf.btn.add').setDisabled(true);
	Ext.getCmp('mf.btn.reset').setDisabled(true);
} //end fnResetForm

Now that all the components are ready, launch the example and to begin with click “load” button. The form will be pre-populated with example data. To try the form submission, click “add”. Hope you find the tutorial useful. Happy coding! :)

Update: the source project is downloadable at myGit.

Beginning Spring MVC 3

March 13, 2011 6 comments

It’s been awhile since I used Spring framework. It has evolved and gotten simpler & easier to work with. This tutorial will walk through how to setup a simple Spring MVC project and to return JSON object to client browser. In this tutorial I will be using SpringSource Tool Suite, its project template helps to reduce the time to get a Spring MVC project up and running.

In order to start the tutorial, you will need

  1. JDK installed. SpringSource Tool Suite requires full JDK, and
  2. SpringSource Tool Suite (STS). The installer includes the IDE and tc Server Developer Edition.

Let’s start with creating the Spring MVC project in STS.

Step 1: Create a new project:  File -> New -> Spring Template Project. You will be prompted to download the template, go ahead and download.

Step 2: Define project and top-level package name, then click “Finish”

Step 3: After the project created you will see the file structure and default controller (HomeController). The dependencies are defined in pom.xml and you will need to add Jackson JSON Processor to complete the tutorial. Without the library you will get HTTP 406 when getting JSON object. Add the following to pom.xml.

<!-- Jackson JSON Processor -->
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-mapper-asl</artifactId>
 <version>1.6.4</version>
</dependency>


Step 4: Deploy the project into SpringSource tc Server. It cannot get easier then this.

Step 5: Deploy the project then start the server.


Step 6: Once the server is ready. Test you configuration by opening http://localhost:8080/spring-mvc-basic/ in your browser. That is all for the setup, now we move on to add a simple function to get JSON data and to get request information.

Step 7: Open HomeController and add 2 methods. The displayRequest() is a simple GET method which take an input parameter “input”, servlet request and request header. The content will be passed back to the view, in this case display.jsp. The 2nd method is getJsonData(), a simple method that return JSON object.

	@RequestMapping(value="/display", method=RequestMethod.GET)
	public String displayRequest(HttpServletRequest request,
		@RequestHeader(value="Accept") String accept,
		@RequestHeader("Accept-Encoding") String encoding,
		@RequestHeader("Accept-Charset") String charset,
                @RequestParam("input") String input,
                Model model)  {
	  logger.info("Calling displayRequest");
	  model.addAttribute("RemoteAddress", request.getRemoteAddr());
	  model.addAttribute("HeaderAccept", accept);
	  model.addAttribute("HeaderAcceptEncoding", encoding);
	  model.addAttribute("HeaderAcceptCharset", charset);
	  model.addAttribute("Output", input);
	  return "display";
	}

	@RequestMapping(value="/extractJson", method=RequestMethod.GET)
	public @ResponseBody Map<String,String> getJsonData(@RequestParam("input") String input)  {
	  logger.info("Calling extractJson");
	  person.put("name", "Simba");
	  person.put("website", "http://www.tanbh.net");
	  person.put("output", input);
	  return person;
	}

Step 8: Let’s work on the views now, by adding the link to call the controller “/display” and jQuery code to get JSON.

<!-- home.jsp -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
	<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.1.min.js"></script>
</head>
<body>
<h1>Hello Spring MVC 3!</h1>
<a href="<c:url value="/display?input=HelloWorldEcho" />">Click to Get Request Info</a>
<br/><br/>
<div id="result"></div>
</body>
</html>
<script type="text/javascript">
$(document).ready(function() {

	$.getJSON('<c:url value="extractJson?input=HelloWorldEcho" />', function(data) {
	    $('#result').append('Result from ajax/json<br/>');
	    $('#result').append('Name: ' + data.name);
	    $('#result').append('<br/>');
	    $('#result').append('Website: ' + data.website);
	    $('#result').append('<br/>');
	    $('#result').append('Input Parameter: ' + data.output);
	});
});
</script>

<!-- display.jsp -->
<%@ 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" %>
<%@ page session="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<strong><c:out value="Remote Address: ${RemoteAddress}"></c:out></strong><br/>
<strong><c:out value="Accept ${HeaderAccept}"></c:out></strong><br/>
<strong><c:out value="Accept-Encoding: ${HeaderAcceptEncoding}"></c:out></strong><br/>
<strong><c:out value="Accept-Charset: ${HeaderAcceptCharset}"></c:out></strong><br/><br/>
<strong><c:out value="Input Parameter: ${Output}"></c:out></strong><br/>

<br/>
<br/>
<br/>
<a href="<c:url value="/" />">Home</a>

</body>
</html>

Now save all the file and sit back and wait for tc Server to reload. Once reloaded, launch trigger http://localhost:8080/spring-mvc-basic/. I also observed, I need to restart the tc Server after compilation error in the controller. Anyway, you should see your result:

Update: the source is downloadable at myGit.

Categories: Spring MVC, SpringSource Tags:
Follow

Get every new post delivered to your Inbox.