Friday, December 31, 2010

Spring MVC 3 - Tiles 2 Integration Tutorial

In this tutorial we will build a simple Spring MVC 3 application that utilizes templates using the Apache Tile 2 framework. We will create a template version of our pages, and compare it with non-template versions of the same pages. We will split the content, style, and template of these pages logically.

What is Apache Tiles 2?
Apache Tiles is a templating framework built to simplify the development of web application user interfaces.

Tiles allows authors to define page fragments which can be assembled into a complete page at runtime. These fragments, or tiles, can be used as simple includes in order to reduce the duplication of common page elements or embedded within other tiles to develop a series of reusable templates. These templates streamline the development of a consistent look and feel across an entire application.

Source: Apache Tiles 2

Our MVC application is about pet information. The main page describes pets in general. The other two pages are speficic for dogs and cats . We will develop our application using standard JSP. Then later, we'll create a Tiles version.

Let's start with the Pets page.

pets.jsp

There are four major div elements here. Each one has been assigned an id so that we can style them using CSS.

Here's the actual screenshot of the Pets page:

Here's the Dogs page.

dogs.jsp

There are five major div elements here. Each one has been assigned an id so that we can style them using CSS.

Here's the actual screenshot of the Dogs page

Here's the Cats page.

cats.jsp

Here's the actual screenshot of the Cats page

We also have the same five major div elements here.

In order for these JSP pages to be served in Spring MVC, we need to declare the corresponding controller.

NoTilesController

This controller has three mappings:
/notiles/pets - for displaying the pets page
/notiles/dogs - for displaying the dogs page
/notiles/cats - for displaying the cats page
To load the pets page, enter the following url:
http://localhost:8080/spring-tiles/krams/notiles/pets
To load the dogs page, enter the following url:
http://localhost:8080/spring-tiles/krams/notiles/dogs
To load the cats page, enter the following url:
http://localhost:8080/spring-tiles/krams/notiles/cats
That's it. We've developed a simple Spring MVC 3 application using standard JSPs.

However, we have a problem

We've declared three JSP pages. Imagine if we have 100 JSP pages to managed with. We need to modify the title and the footer. So we open all 100 JSP pages, edit them one by one. To make it faster, we copy and paste the same code. But we made a typo. So we edit again those 100 pages. And the cycle goes on. What if we have 500 pages? 1000? How do we make our lives less difficult?

Enter Apache Tiles 2

Let's refactor our JSPs. Remember in each of these pages there are major div elements. We'll use those as markers for our templates.

The Pets page uses the following structure:

Our first template is based on this structure.

main.jsp

Each div contains a tiles:insertAttribute element. These are placeholders for the actual content.

Our second template will be based on the cats.jsp and dogs.jsp. They share the same structure so that means they will share the same template.

details.jsp

So far we have created 5 JSPs:
cats.jsp - a standard JSP
dogs.jsp - a standard JSP 
pets.jsp - a standard JSP 

detail.jsp - a Tiles JSP 
main.jsp - a Tiles JSP 
To use these templates we need to activate Apache Tiles by declaring the required XML configurations. To do that we need to declare the required Spring configurations as well.

We'll start with 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. W've also imported a resource tiles-context.xml. This contains the Tiles configuration.

tiles-context.xml

This configuration declares required beans to activate Tiles. The TilesConfigurer relies on an external definitions file tiles-definitions.xml for the actual declaration of the templates.

tiles-definitions.xml

We've declared two templates: template-main and template-detail.

These attributes must match the attributes you declared in template: main.jsp

We've declared three concrete pages: pet-tiles, dog-tiles, cat-tiles

Each concrete page extends a template name. For example, cat-tiles extends from template-detail. In Java this is comparable to inheritance.

Do you understand now how Tiles can help us reduce repetitive code and lessen errors? By reusing the same JSP and template, we improve our development time. Our JSPs became manageable. If you want to switch content, you just do it in the tiles-definitions.xml. For example, if you need to update the footer.jsp, you just open the file. Edit then save. You don't need to edit 1000 JSP pages anymore.

Of course, if you're just dealing with three pages. The initial configuration might be too much. But in real-life applications, it's a time saver because you're dealing with lots of JSPs.

Because we're still dealing with a MVC application, we need to declare another controller to handle these Tiles pages.

TilesController

This controller has three mappings:
/tiles/pets - for displaying the pets page
/tiles/dogs - for displaying the dogs page
/tiles/cats - for displaying the cats page
To load the pets page, enter the following url:
http://localhost:8080/spring-tiles/krams/tiles/pets
To load the dogs page, enter the following url:
http://localhost:8080/spring-tiles/krams/tiles/dogs
To load the cats page, enter the following url:
http://localhost:8080/spring-tiles/krams/tiles/cats

Let's compare side by side our JSP pages with using the standard JSPs and the ones with Tiles support.

Pets Page (before and after)

Dogs Page (before and after)

Cats Page (before and after)

That's it. We've managed to refactor our code and use the Tiles framework. We've also leveraged on Spring programming model to develop our MVC application.

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-tiles/

You can download the project as a Maven build. Look for the spring-tiles.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
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3 - Tiles 2 Integration Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring Security - MVC: Implementing a Single Entry Filter Tutorial

In this tutorial we will implement a custom Spring Security filter that allows a URL to be accessed just once. We will position the filter after the CONCURRENT_SESSION_FILTER. We will take advantage of the SessionRegistry to query the current session. If you're not familiar with setting-up the SessionRegistry and Concurrent Session Management, please read first the Spring Security - MVC: Querying the SessionRegistry tutorial.

The requirements for our custom filter are the following:
  • You can only have one instance of a page
  • If you create a new tab and enter the same page, you will not be able to access the page again and you will be redirected to a custom page
  • If you create a new browser, same result
  • If you create close and open the same browser, same result
  • If you refresh the same tab, same result
  • You can only gain access if you manually log-out
  • You can only gain access if you clear your browser's cache
  • You can only gain access if your session has expired
So how do we do that? First, we evaluate at what position in the FilterProxyChain should we place this filter. We need the SessionRegistry and we need the HttpServletRequest. Somewhere around the CONCURRENT_SESSION_FILTER looks promising.

If you need to learn more about the FilterChainProxy and ordering of the aliases, please check the Spring Security Reference Table 2.1. Standard Filter Aliases and Ordering

The format for adding the filter is similar to the following:


Before we start adding real code, let's declare a pseudocode first:
if user has logged-in for the first time
   flag the session that the user has logged-in
if the user tries to log-in again
   check if there's a protected URL
       if yes, redirect user to a custom page
       if no, then proceed with the remaining filters
And here's the actual implementation for this filter.

SingleEntryFilter

This filter extends OncePerRequestFilter and overrides the doFilterInternal() method

What is OncePerRequestFilter?
Filter base class that guarantees to be just executed once per request, on any servlet container. It provides a doFilterInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain) method with HttpServletRequest and HttpServletResponse arguments.

The getAlreadyFilteredAttributeName() method determines how to identify that a request is already filtered. The default implementation is based on the configured name of the concrete filter instance.

Source: Spring Reference 3 for OncePerRequestFilter
How did we came up with this implementation? I'm sure it didn't just came out from thin air. Actually, I had to study how the CONCURRENT_SESSION_FILTER alias is implemented. It's filter class is based on ConcurrentSessionFilter.

What is ConcurrentSessionFilter?
Filter required by concurrent session handling package.

This filter performs two functions. First, it calls SessionRegistry.refreshLastRequest(String) for each request so that registered sessions always have a correct "last update" date/time. Second, it retrieves a SessionInformation from the SessionRegistry for each request and checks if the session has been marked as expired. If it has been marked as expired, the configured logout handlers will be called (as happens with LogoutFilter), typically to invalidate the session. A redirect to the expiredURL specified will be performed, and the session invalidation will cause an HttpSessionDestroyedEvent to be published via the HttpSessionEventPublisher registered in web.xml.

Source: Spring Security 3 Reference for ConcurrentSessionFilter
Let's examine the doFilter() method of this class.

ConcurrentSessionFilter

This ConcurrentSessionFilter does the following steps:
1. Retrieve the current session
2. Check if session is not null
3. Check if the SessionInformation is not null
4. Check if the session has expired. If expired, logout and redirect
5. If not expired, continue with remaining filters.

Let's compare this with our custom filter SingleEntryFilter.

Inside the doFilterInternal() method, we do the following:
1. Retrieve the current session and verify if it's not null

2. Retrieve the SessionInformation and verify if it's not null

3. Retrieve the session attribute hasLoggedIn and check if it's null or not

If hasLoggedIn is not null, this means the user has logged already.

4. Next, we loop the guardURI list and check if there's a protected URL. If there's one, we redirect to the redirectURI

5. If this is the user's first time to access the site (i.e new session), set the hasLoggedIn attribute

6. Finally, continue with the remaining filters

Examine how this code resembles the ConcurrentSessionFilter

Now, let's update the the Spring Security XML configuration.

spring-security.xml

The changes we did in this file is we added the following custom filter:

We also declared the singleEntryFilter bean.

Notice the guardURI is a list. That means we can protect multiple URIs. Cool :)

We then need to update our login controller so that we can see the invalid login alert.

LoginLogoutController

To access the site, please login first by entering the following URL:
http://localhost:8080/spring-security-single-login-filter/krams/auth/login
Then access the following URL:
http://localhost:8080/spring-security-single-login-filter/krams/main/common
You can only access the URL once! Here's what you'll get if you try again:

That's it. We've just finished implementing our custom filter based on the requirements we laid earlier. They key action here is we studied the existing filters to see how Spring Security does things. I believe this is a good way to enhance one's knowledge of this framework.

Please read the tutorial Spring Security 3 - MVC: Querying the SessionRegistry for a complete step-by-step guide for the other parts of this application.

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-single-login-filter.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
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security - MVC: Implementing a Single Entry Filter Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3 - Accessing web services using JAX-WS

In this tutorial we will create a Spring web service client using JAX-WS. We will integrate this client with a Spring MVC 3 application and provide a form where users can submit data. Our application is a front-end for a subscription web service, which we created in the tutorial Spring WS 2 and Spring 3 MVC Integration Tutorial. It's highly recommend to read that first because that is our web service provider.

We will assume that we only know the WSDL of the web service to simulate a real client development. To generate the proxy classes, we will use the built-in wsimport tool from the JDK. To access the web service, we will use Spring's JaxWsPortProxyFactoryBean. We are not using any Spring Web Service (WS) dependencies here.

What we'll do here is follow the same exact steps as shown in the Spring WS - MVC: Implementing a Client Tutorial. And we will just highlight the difference.

Here's are the changes you need to do to use Spring's JaxWsPortProxyFactoryBean

new applicationContext.xml

old applicationContext.xml

In the applicationContext we just removed the reference to spring-ws.xml and switched to jax-ws.xml

We need to declare this new config and delete the old one.

jax-ws.xml

For a detailed description of this configuration, please check the official Spring Reference: 19. Remoting and web services using Spring

We also need to update the primary controller.

new MainController

This controller declares two mappings:
/main - for showing the subscribe page
/main/subscribe - for processing the subscription
Notice we have injected an instance of a SubscriptionPort

In the Spring WS tutorial we have injected an instance of a WebServiceTemplate instead

Inside the doSubscribe() method, we process the subscription by delegating to the subscriptionJaxProxyService

Once we get a valid response, we add it to the model:

If there are validation errors, the client will throw a SoapFaultClientException so we need to catch that:

That's it. Everything else is exactly the same as with our previous tutorial. We've managed to integrate a Spring MVC application and utilized the JaxWsPortProxyFactoryBean.

To test the client and the web service provider, you need two instances of Tomcat or Jetty : one for the web service and one for the client. Make sure to set the ports accordingly. For the provider, I chose port 8081. For the client, I chose 8080. If you change the ports, you must update the spring-ws.xml configuration of the provider and the client as well. In case you forgot, the web service provider is in my other tutorial Spring WS 2 and Spring 3 MVC Integration Tutorial

To access the Subscribe Page, use the following URL:
http://localhost:8080/spring-ws-client-jaxproxy/krams/main
Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-ws-2-0-0-rc2-tutorial/

You can download the project as a Maven build. Look for the spring-ws-client-jaxproxy.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 integration with other technologies, 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 MVC 3 - Accessing web services using JAX-WS ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring WS - MVC: Implementing a Client Tutorial

In this tutorial we will create a Spring WS web service client using the latest 2.0.0 RC2 build. We will integrate this client with a Spring MVC 3 application and provide a form where users can submit data. Our application is a front-end for a subscription web service, which we created in the tutorial Spring WS 2 and Spring 3 MVC Integration Tutorial. It's highly recommend to read that first because that is our web service.

We will assume that we only know the WSDL of the web service to simulate a real client development. To generate the proxy classes, we will use the built-in wsimport tool from the JDK. To access the web service, we will use Spring's WebServiceTemplate.

What is Spring Web Services (WS)?
Spring Web Services (Spring-WS) is a product of the Spring community focused on creating document-driven Web services. Spring Web Services aims to facilitate contract-first SOAP service development, allowing for the creation of flexible web services using one of the many ways to manipulate XML payloads. The product is based on Spring itself, which means you can use the Spring concepts such as dependency injection as an integral part of your Web service.

Source: Spring WS Reference 2.0
What is WebServiceTemplate?
The WebServiceTemplate is the core class for client-side Web service access in Spring-WS. It contains methods for sending Source objects, and receiving response messages as either Source or Result. Additionally, it can marshal objects to XML before sending them across a transport, and unmarshal any response XML into an object again.

Source: Spring WS Reference Chapter 6
What is wsimport?
The wsimport tool generates JAX-WS portable artifacts, such as:
  • Service Endpoint Interface (SEI)
  • Service
  • Exception class mapped from wsdl:fault (if any)
  • Async Reponse Bean derived from response wsdl:message (if any)
  • JAXB generated value types (mapped java classes from schema types)
These artifacts can be packaged in a WAR file with the WSDL and schema documents along with the endpoint implementation to be deployed

Source: Java™ API for XML Web Services (JAX-WS) 2.0
Let's start by downloading and examining the WSDL document from the web service which is accessible in the following URL:
http://localhost:8081/spring-ws-standalone/krams/ws/subscription.wsdl
subscription.wsdl

This document has one request subscriptionRequest and one response subscriptionResponse.

The subscriptionRequest accepts the following format:

The subscriptionResponse is what we will receive in return:

The service name is SubscriptionPortService. The port type is SubscriptionPort. If you need help in reviewing the basics of a WSDL document, please visit the following tutorial from w3schools.com WSDL Tutorial.

We got our WSDL document. Next we generate the Java proxy classes or precisely the JAX-WS portable artifacts

We will use wsimport to generate the artifacts. Open a terminal and type the following:
wsimport
And this is what you should see:

We need to keep the generated Java sources and specify the target directory. To do that we will include the -keep and -d options. Make sure you update the directory accordingly.

Here's the command to generate the classes

Type that in a terminal and hit enter. You should see the following:
parsing WSDL...


generating code...
Go to the directory where the file is saved. You should see a nest of folders. These folders correspond to the namespace of the WSDL document. Also, for each .class file, there's a coresponding .java file. That's the source code.

Here's an actual screenshot from my machine:

We have our WSDL. We have our artifacts. Notice we haven't done any Java or Spring development yet. These are just preparations.

Let's start the actual development. I'm using Eclipse and the m2eclipse plugin, so my instructions would be IDE-centric and Maven-centric as well.

If you're using Eclipse:
1. Create a new Dynamic Web project.

2. Create the top-level package, ie. org.krams.tutorial

3. Create a sub package, i.e org.krams.tutorial.oxm

4. Remember the files that we generated earlier? Copy all the .java files and paste them in the sub-package.

If you have the m2eclipse plugin:
1. Create a new Maven project.

2. Select the maven-archetype-webapp

3. Create a sub package, i.e org.krams.tutorial.oxm

4. Remember the files that we generated earlier? Copy all the .java files and paste them in the sub-package.

The source code for this tutorial is a Maven project which you can download the end of this tutorial.

Here's how the project looks like in my IDE:

We can now start developing our Spring MVC application.

We begin by declaring the primary controller.

MainController

This controller declares two mappings:
/main - for showing the subscribe page
/main/subscribe - for processing the subscription
Notice we have injected an instance of a WebServiceTemplate

Inside the doSubscribe() method, we process the subscription by delegating to the WebServiceTemplate

The WebServiceTemplate is able to marshall Java objects to XML and unmarshall from XML to Java objects again. In layman's term, marshall and unmarshall are another word for converting back and forth to different formats. If you need a thorough guide of the WebServiceTemplate, please check the official reference guide at SpringSource - Chapter 6. Using Spring Web Services on the Client

Once we get a valid response, we add it to the model:

If there are validation errors, the client will throw a SoapFaultClientException so we need to catch that:

SubscriptionResponse and SubscriptionRequest are JAX artifacts that were generated from the WSDL earlier. So instead of manipulating XML, we deal with Java objects.
A quick look at the contents of these two artifacts shows us the following:

SubscriptionRequest

SubscriptionResponse

Notice how the XML elements had been mapped to equivalent Java fields.

Our controller requires a single JSP page for displaying the form.

subscribepage.jsp

Here's the actual screenshot:

If there's a validation error, we see the following:

If successful, we get the following instead:

What's left are the required XML configurations.

To enable Spring MVC we need to add it 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

By convention, we must declare an applicationContext.xml as well.

applicationContext.xml

This XML config declares three beans to activate the Spring 3 MVC programming model. There's also an extra bean that imports Spring-WS related configuration.

spring-ws.xml

For a detailed description of this configuration, please check the official Spring Reference: Chapter 6. Using Spring Web Services on the Client

That's it. We're done with our Spring WS web service client. We've managed to integrate a Spring MVC application for the submission of subscriptions, and utilized the convenient WebServiceTemplate.

To test the client and the web service provider, you need two instances of Tomcat or Jetty : one for the web service and one for the client. Make sure to set the ports accordingly. For the provider, I chose port 8081. For the client, I chose 8080. If you change the ports, you must update the spring-ws.xml configuration of the provider and the client as well. In case you forgot, the web service provider is in my other tutorial Spring WS 2 and Spring 3 MVC Integration Tutorial

To access the Subscribe Page, use the following URL:
http://localhost:8080/spring-ws-client/krams/main
Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-ws-2-0-0-rc2-tutorial/

You can download the project as a Maven build. Look for the spring-ws-client.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 integration with other technologies, 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 WS - MVC: Implementing a Client Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share