Friday, August 21, 2009

Spring Web Flow 2 Web Development: Book Review

I have been keeping the good people of PACKT Publishing waiting some time for this short review; they were kind and prompt in sending me their book - in my defence I have been very busy lately. I had hoped to include some example code but as I am still short on time right now I thought I would release a general review first and maybe something with some example code at a later date when I've had some more time to digest the book further. To business, Spring Web Flow 2 Web Development is a book for Spring developers who want to give Spring Web Flow a try. So what is Spring Web Flow? As described in following excerpts from the book (page 9):

"...- you can use Spring Web Flow to create conversational web applications. ...For example, take an application with a wizard-like interface. ...You are working in a predefined flow with a specific goal, such as ordering a book or creating a new user account. ...Spring Web Flow makes it very easy to create flows. Flows created by Spring Web Flow are not only decoupled from the applications logic, but are also re-usable in different applications. A flow in Spring Web Flow is a sequence of steps, that is, with states and transitions between them. There are also actions that can be executed on various points, for example, when the flow starts or the web page is rendered..."

This book is intended to describe Spring Web Flow 2 and any book which ties itself to a particular version is going to date quickly but that said you are bound to learn something new reading this book.

The book contains the obligatory chapters describing the Spring Web Flow 2 concepts and exploring what has changed since the last version, the distribution and example code. It also has a chapter on setting up your development environment be that Ant, Maven, Eclipse (and Spring IDE) or NetBeans. A chapter on JavaServerFaces integration using the Spring Web Flow 2 "Spring Faces" module, as I've never properly explored JavaServerFaces I'm not qualified to comment on this. The sample project that is used throughout the book is a simple bug tracking system ("flow.trac"). With this project there is plenty of scope to explore what Spring Web Flow 2 has to offer in terms of user interface (JavaScript including AJAX, Apache Tiles etc.), testing (JUnit and EasyMock) and security (Spring Security) whilst utilising a JPA (Hibernate) database layer. In the appendix it shows you how you can run your code on the SpringSource dm Server and gives a gentle introduction to making you application work in an OSGi environment. The source code for the book is available @ www.packtpub.com/files/code/5425_Code.zip

One of my early impressions was one of surprise, I admit to raising an eyebrow that they chose to use Microsoft SQL Server 2008 Express Edition as their example database server. I would expect something more lightweight such as H2 or Apache Derby -e.g. something you could easily bundle as part of a Maven build.

The intended audience for this book seems to be people who plan to use the triumvirate of Spring, Spring MVC and Spring Web Flow. From my perspective Spring is a gimme and you are obviously interested in Spring Web Flow (that is why you bought the book!) but I'm not so sure you are always free to choose Spring MVC. To be fair the book goes to great pains to say that Spring Web Flow can be used with other technologies but as my main web development MVC framework is still good ole' Struts 1.3, it would be nice to see some examples of using Spring Web Flow 2 with something other than Spring MVC or maybe even in a more exotic environment like inside a Spring MVC portlet. Spring Web Flow 2 includes components for integrating with JavaScript. I have to admit to being a jQuery devotee so any alternate JavaScript technology seems a bit unnecessary to me but I can see it could be useful to some folks.

All in all and so far, I have found reading this book to be very enjoyable. It is nice to see how other developers go about things, I found myself reading and thinking "I wouldn't do it that way" AND "That's clever, I'd never have thought of that!". The experience of reading this book is very much like shadowing some very experienced senior Java developers.

Tuesday, August 11, 2009

Coming soon: Spring Web Flow 2 Web Development: Book Review

PACKT Publishing very kindly sent me a copy of Spring Web Flow 2 Web Development to review. I have been very busy with work so I have not yet gotten around to reviewing it but I plan to publish something in the not too distant future. So watch this space!

Thursday, July 02, 2009

jQuery UI ThemeRollerReady IFRAME in a dialog box

Whilst making preparations for upgrading to uPortal 3.1.x from uPortal 2.5.x I came into contact with jQuery UI themes.

In our previous portal the help screens were displayed using Cody Lindley's ThickBox. At the time I first introduced Thickbox to our portal I thought this was pretty revolutionary, clicking on a link made the background dim and the help text (via an IFRAME) was shown in sharp contrast in the foreground of the page (very Web 2.0!).

The interface for uPortal 3.1 has evolved considerably from 2.5.x. The fluid project have worked on uPortal 3.1 to improve the user experience. jQuery and jQuery UI have become an integral part of the uPortal interface. uPortal 3.1 makes good use of jQuery UI dialog and tab widgets. (Incidentally, when did dialogue become dialog?) As the range of jQuery UI widgetry expands so too will the options for portal improvement, all with a common look and feel and easily themed.

In our new portal I would still like to access the help pages in a Thickbox/IFRAME style. However, the jQuery plugins that provide this kind of functionality (Thickbox and jqModal) do not look like the other jQuery UI widgets and are not themeable via jQuery UI themes. I could probably map the plugin CSS to the jQuery UI theme CSS but this seems like it could be a lot of work. So I have produced my own version of a dialog using an IFRAME.

I am fairly new to jQuery and what I have produced isn't quite up to jQuery plugin standard but if somebody out there wanted to apply some finishes touches to it I would be happy to contribute it back to the jQuery effort. The main difference between my effort and Thickbox and jqModal is that I am only interested in IFRAMEs and my version should be ThemeRollerReady. All being well you should see the themeswitcher below and a click on the link below that should give you a dalog box IFRAME:

jQuery UI IFRAME dialog box example

alternatively you can see it at standalone jQuery UI IFRAME dialog box example.

Monday, June 08, 2009

Fetching Servlet Filter init parameters from a properties file with Spring

A while ago I wrote some code and thought it a neat trick but totally forgot about it until recently. I am writing this blog entry, firstly to share the idea and secondly to see if somebody can give an alternative using only Spring classes (which would deepen my understanding). Using Spring's DelegatingFilterProxy it is possible to hand off creation of servlet filters to a bean defined in Spring's application context. This is very useful if you want to inject Spring managed beans into a your servlet filters.

I am using the DelegatingFilterProxy mechanism to configure my servlet filter init parameters and in conjunction using PreferencesPlaceholderConfigurer so these come from a properties file. This means I can easily switch between prod and dev environments without having to modify web.xml (I could even change the authenticationFilter implementation to something else but that is a different story!). My aim here is to minimize the number of files I need to edit when moving between prod and dev environments. I hope somebody else finds this approach useful.

As an example I am using the Yale CAS Filter, which is considered a little long in the tooth now (but I'm still using it). It makes for a good example because there are numerous filter properties that you might want to change. Even the most up to date version of the JA-SIG CAS Filter could potentially benefit from using my approach.

web.xml


...
<filter>
<filter-name>authenticationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>authenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...

applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="location" value="/WEB-INF/dev.properties" />
</bean>

<bean id="authenticationFilter" class="edu.bristol.web.ParameterPassingFilterProxy">
<property name="parameters">
<map>
<entry key="edu.yale.its.tp.cas.client.filter.loginUrl" value="${cas.loginUrl}" />
<entry key="edu.yale.its.tp.cas.client.filter.validateUrl" value="${cas.validateUrl}" />
<entry key="edu.yale.its.tp.cas.client.filter.wrapRequest" value="${cas.wrapRequest}" />
<entry key="edu.yale.its.tp.cas.client.filter.serverName" value="${cas.serverName}" />
<entry key="edu.yale.its.tp.cas.client.filter.renew" value="${cas.renew}" />
</map>
</property>
<property name="targetBeanName" value="casFilter" />
</bean>

<bean id="casFilter" class="edu.yale.its.tp.cas.client.filter.CASFilter"/>

</beans>

The extra class that I added to make this work is available from ParameterPassingFilterProxy.java you are free to use it as you wish.

Thursday, May 14, 2009

What would Hibernate do? Avoidance of hbm2ddl.auto=update in production

For the past 9 months I have been using Hibernate Annotations (along with the Spring Framework) to build my development database. Although I have a reasonably strong grasp of SQL I would still not consider myself fluent. Hibernate does all the hard work for me. Truth be told, there is a substantial learning curve to mastering mapping entity bean associations/relationships with Hibernate annotations. However once you finally develop an understanding (or find enough examples of what you want) it is very easy to continually evolve a data model throughout system development. Using annotations in conjunction with a suitably crafted import.sql file I can go from zero to system in no time. So after several months' development I am on the brink of having a production ready database containing precious real data that I do not want to loose. Should I take the risk of using "hbm2ddl.auto=update" to incorporate last minute database changes? I think not. I would not do this and this is not because I don't trust Hibernate but more because I do not trust myself. If I accidentally used hbm2ddl.auto=create (as I do regularly in my development instance) then bang goes my production database and all the data it contains.

So I wrote a small program to let me see what Hibernate would do if I ran an update without the associated risk of actually performing an update. I have a Spring applicationContext.xml which contains something like the following (note the complete absence of hbm2ddl.auto property setting):


<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="location" value="jdbc.prod.properties" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>${jdbc.driverClassName}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}
</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>edu.bristol.entity.Tom</value>
<value>edu.bristol.entity.Dick</value>
<value>edu.bristol.entity.Harry</value>
</list>
</property>
<property name="dataSource" ref="dataSource" />
</bean>

Now for my program, one thing that I have noticed is that update scripts that Hibernate would create will add new fields to a database but will not delete existing columns (even if these have been removed from the annotated entity). It makes a good deal of sense not to delete columns from a production database without knowing exactly what you are doing so this is a good thing!


import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;

public class AcquireScripts {

public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// ampersand is very significant - it means get me an
// instance of the beanfactory and not give me a bean
LocalSessionFactoryBean sfb = (LocalSessionFactoryBean) context.getBean("&sessionFactory");
Configuration cfg = sfb.getConfiguration();
Dialect dialect = Dialect.getDialect(cfg.getProperties());
//printDropSchemaScript(cfg, dialect);
//printSchemaCreationScript(cfg, dialect);
printSchemaUpdateScript((SessionFactory) sfb.getObject(), cfg, dialect);
}

private static void printSchemaCreationScript(final Configuration cfg, final Dialect dialect) {
String[] schemaCreationScript = cfg.generateSchemaCreationScript(dialect);
for (String stmt : schemaCreationScript) {
System.out.println(stmt + ";");
}
}

private static void printDropSchemaScript(final Configuration cfg, final Dialect dialect) {
String[] dropSchemaScript = cfg.generateDropSchemaScript(dialect);
for (String stmt : dropSchemaScript) {
System.out.println(stmt + ";");
}
}

private static void printSchemaUpdateScript(final SessionFactory sf, final Configuration cfg, final Dialect dialect) {
HibernateTemplate hibernateTemplate = new HibernateTemplate(sf);
hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER);
hibernateTemplate.execute(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Connection con = session.connection();
Dialect dialect = Dialect.getDialect(cfg.getProperties());
DatabaseMetadata metadata = new DatabaseMetadata(con, dialect);
String[] schemaUpdateScript = cfg.generateSchemaUpdateScript(dialect, metadata);
for (String stmt : schemaUpdateScript) {
System.out.println(stmt + ";");
}
return null;
}
});
}
}

Notice the cunning use of the ampersand to acquire an instance of the LocalSessionFactoryBean rather than the actual SessionFactory itself. So there we have it, all of the cleverness of Hibernate annotations working out what SQL we might need to update our database but none of the risk.

Wednesday, May 06, 2009

I am experimenting with a hosted blog

My "other blog" is located at http://markmclaren.blogs.ilrt.org/. I'm looking to see how I get on with a more restricted environment!

Thursday, January 15, 2009

An alternative to req:isUserInRole

For me, HttpServletRequest's getRemoteUser() and isUserInRole(role) have always felt like the right place to obtain user information in a web application. My experience with JASIG CAS filter and SecurityFilter has taught me that it is easy to create a servlet filter and drop in a request wrapper (HttpServletRequestWrapper) and create a method to set the remoteUser value. Couple this filter with something like Spring's DelegatingFilterProxy and it is easy obtain user details from some dependency injected external database.

Once the remoteUser value exists in the wrapped request you can acquire the details in a JSP page using JSTL e.g:


<c:out value="${pageContext.request.remoteUser}"/>

or with simple expression language alone (JSP 2.4+), e.g:


${pageContext.request.remoteUser}

The question is how to obtain the role information for a user. Jakarta's Request tag library enables you to make use of role information.


<req:isUserInRole role="admin">
<h1>Hello Admin User</h1>
</req:isUserInRole>

For some reason the request tag library is now deprecated. Of course you can still use it (and it is in the Maven repository) but there is something of a stigma associated with using deprecated code! So I have come up with an alternative. The issue is that it is not easy to invoke methods with parameter arguments from expression language. You cannot simply call:


${pageContext.request.isUserInRole('admin')}

Using expression language you can access scoped variables, arrays, lists and maps. Most of the time this data will be acquired and stored in some scope prior to loading the JSP page (such as in a typical MVC application). However, I have discovered that you can acquire runtime generated responses from a Map using Commons Collection's LazyMap and this technique can be used to effectively perform a user role lookup. I added the following method to my request wrapper (and made sure the request wrapper was publically accessible):


public Map getIsUserInRole() {
Transformer factory = new Transformer() {
public Object transform(Object mapKey) {
return isUserInRole((String) mapKey);
}
};
Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
return lazyMap;
}

and this means I can now access role information in a way that looks very much like a direct call to request.isUserInRole(role).


${pageContext.request.isUserInRole['admin']}

Using an idea that Matthew Sgarlata had for the request tag library it is even possible to include support for multiple role queries.


public Map getIsUserInRole() {
final String ROLE_DELIMITERS = ", \t\n\r\f";
Transformer factory = new Transformer() {

public Object transform(Object mapKey) {
StringTokenizer tokenizer = new StringTokenizer((String) mapKey, ROLE_DELIMITERS);
boolean result = false;
while (tokenizer.hasMoreTokens() && !result) {
if (isUserInRole(tokenizer.nextToken())) {
result = true;
}
}
return result;
}
};
Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
return lazyMap;
}
and the expression language becomes:

${pageContext.request.isUserInRole['admin,staff']}

and this can be easily negated:


${!pageContext.request.isUserInRole['admin,staff']}

Sample WAR with source code available (Assuming Java 1.5+ and Maven build "mvn compile war:war").

Update

As an update to this, I am now using the above technqie with what I call a ClearingLazyMap. This class implements the LazyMap interface but does not cache any values when they are fetched. This is necessary in order to pick up the most recent database updates, see also LazyMap that always calls transform, good idea?