October 2007 Archives

Parancoe Controller Tutorial

In this tutorial we will cover the necessary steps to create a Controller in the Parancoe Web framework.

Introduction

First of all you have to know that Parancoe uses the Spring MVC framework.

In Spring MVC all HTTP requests are routed to the DispatcherServlet. This particular servlet, by examining the url, decides which Controller can manipulate the request.

Controllers are a core part of Spring MVC and the Parancoe Web Framework tries to ease the process of defining and mapping those objects to urls.

The steps necessary to define and use a Controller are:

Let’s see those steps through an example. Suppose that your application needs to manage a sort of administration control. The easy way to develop such a component is to write an object that manages all the request coming from /admin/*.html.

Write the controller class

Writing the controller class is simple: you have to extend from BaseMultiActionController in this way:


package org.parancoe.basicWebApp.controllers;
public abstract class AdminController 
           extends BaseMultiActionController {
    ...
}

BaseMultiActionController extends from Spring MultiActionController and adds some facilities for logging and error handling. If you are not familiar with MultiActionController, Spring site has a well documented tutorial on it here .

Annotate the controller class with url mappings

The problem now is to link our controller to urls like /admin/*.html. To do so we can use an annotation directly in the controller class:

package org.parancoe.basicWebApp.controllers;

@UrlMapping("/admin/*.html")
public abstract class AdminController 
           extends BaseMultiActionController {
    ...
}

In this way all urls matching /admin/*.html will be routed to AdminController.

The annotations defined for url mapping are three:
  • @UrlMapping: receives a string containing the url definition;
  • @MultiUrlMapping: allows to define multiple mappings for the same controller. For example @MultiUrlMapping("/admin/*.html", "/admin/*.jsp");
  • @DefaultUrlMapping: sets the default Parancoe convention on url mappings.

The default convention used in @DefaultUrlMapping works in this way. If you define a controller with class name AdminController and if you annotate it with @DefaultUrlMapping, Parancoe will associate it with the url /admin/*.html.

In the same way if you define a controller called MyFantasticApplicationAdminController it would be associated with urls like /my/fantastic/application/admin/*.html.

If you don’t specify any url in @UrlMapping, Parancoe will default the url in the same way of @DefaultUrlMapping. So the behaviour of this two annotations is the same: @UrlMapping("") == @DefaultUrlMapping.

Autodiscovery of controllers

Now that you have defined and annotated your controller it’s time to register it in Spring Context. This task can be accomplished in two ways. The first one is the Spring normal way: you define your controller in parancoe-sevlet.xml like this:


<bean id="adminController" 
      class="org.parancoe.basicWebApp.controllers.AdminController" 
      parent="abstractController"/>

The other way is to let Parancoe find and define controllers for you. To do so you need to write in your parancoe-servlet.xml:


<parancoe-web:define-controllers 
    basePackage="org.parancoe.basicWebApp.controllers" 
    parent="abstractController"/>
This tag has two attribute:
  • basePackage: this is the package in which Parancoe searches your controllers;
  • parent: is the abstract controller from which your controller derives. This attribute is not mandatory, the default behavior is to use abstractController, provided by the framework.

If you use this second way, it would be easy to add another controller to your web application: simply put it in basePackage, and Parancoe will discover and configure it for you.

If you want to use this second way, remember to add this namespace to your parancoe-servlet.xml:

xmlns:parancoe-web="http://www.parancoe.org/schema/parancoe-web" 
xsi:schemaLocation="http://www.parancoe.org/schema/parancoe-web 
   http://www.parancoe.org/schema/parancoe-web.xsd" 

...to be continued.

Continue Reading…

Posted by Andrea Nasato on Oct 02, 2007

Parancoe Security

In this tutorial I’ll show you how to configure your parancoe web application in order to secure it.

Introduction

Security in parancoe has been implemented using Acegi framework. Acegi Security is sub-project of spring framework, it provides security services for J2EE software applications, especially if they are built using Spring. We chose to implement security in parancoe using the plugin way, so you are free to use the security parancoe features in your parancoe web application and, above all, you have NOT to define the filter used by acegi in the web.xml because it uses an Handlerinterceptor to call the chains of filters.

The security plugin manages security aspects restricted to authentication and authorization processes. The default configuration of the plugin provides:

  • Form-based authentication
  • Authorization based on protected url associated to roles

If the user asks for a protected resources the plugin intercepts the request, verify if the user is authenticated and if he is not forwards him to the login page (provided by the archetype). If the user is authenticated but he is not in any of the roles associated to the protected resourse he will be redirected to the accessDeniedpage (still provided by the archetype).

Standard Configuration

In order to use the security plugin you have to declare it as dependency in your pom.xml application file, that is the pom file that the parancoe web archetype creates for you.

    <dependency>
            <groupId>org.parancoe</groupId>
            <artifactId>parancoe-plugin-security</artifactId>
            <version>0.3.2</version>
            <scope>compile</scope>
    </dependency>
Refer to the last version relased of the security plugin. In order to associate the protected url (resources) to the roles you define in you web application you have to edit the parancoe-servlet.xml file and add the pluginSecurityFilterDefinitions definition. Here the configuration used for jugevents application.

<bean name="pluginSecurityFilterDefinitions" 
 class="java.lang.String">
        <constructor-arg>
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /adminjugger/**=ROLE_ADMIN
                /people/**=ROLE_ADMIN, ROLE_PARANCOE
                /event/edit*=ROLE_ADMIN, ROLE_JUGGER
                /event/delete*=ROLE_ADMIN, ROLE_JUGGER
                /event/participants*=ROLE_ADMIN, ROLE_JUGGER
                /admin/**=ROLE_ADMIN
                /**=IS_AUTHENTICATED_ANONYMOUSLY
            </value>
        </constructor-arg>
    </bean>
The informations concerning users, roles are stored in three tables of the database which the plugin creates automatically for you.
  • PSEC_USER: informations about username, password, enabled;
  • AUTHORITY: defines all the roles of your application;
  • USER_AUTHORITY: represents the relation between users and roles.

You have to fill with the users and the roles that you’ll use in the application. At this point you are done, we have only edited the pom.xml and the parancoe-servlet.xml file and now we have a secure web application. It’s easy, it’s the parancoe way.

Configuration for existing database

If you need to retrieve informations about security from an existing database and you don’t want to create the tables described above you have to edit the parancoe-servlet.xml and add the userDetailsService configuration. Here the configuration used in the plugin.

<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
        <property name="usersByUsernameQuery">
            <value>select username, password, enabled FROM psec_user WHERE username = ?</value>
        </property>
        <property name="authoritiesByUsernameQuery">
            <value>select username, role from psec_user u, authority a, user_authority ua 
            where u.username = ? and u.id = ua.user_id and a.id = ua.authority_id</value>
        </property>
    </bean>      
You have to replace the usersByUsernameQuery and authoritiesByUsernameQuery queries with your database specific queries.

Presentation

The plugin uses the acegi tag library to implement dynamic menu based on the user logged. Please refer to the acegi documentation to understand how to use use them.

...to be continued.

Continue Reading…

Posted by Enrico Giurin on Oct 01, 2007