Saturday, February 28, 2009

Spring Webflow: An elegant DSL for your MVC

Spring Web Flow is an interesting MVC framework. Under the hood, it is an implementation of a Finite State Machine (FSM). However, the beauty of Spring Web Flow is in the simplified DSL templating that Web Flow provides.

First, lets look at a simple example:
<flow start-state="start">

<view-state id="start" view="chooseColor.jsp">
<transition on="red" to="showRed" />
</view-state>

<end-state id="showRed" view="red.jsp"/>

</flow>

This web flow above has two states and one transition. States in web flow typically correspond to views. In this case, my views are JSP's. Transitions will be triggered based on events. Within a JSP, events correspond to buttons or links. The event or button to trigger the red event is defined here:

<html>
...

<form:form action="${flowExecutionUrl}">
<input type="submit" name="_eventId_red" value="Red" />
</form:form>

...
</html>


The flowExecutionUrl contains the context-relative URL to the current flow execution's view state. Alright, so what advantages does web flow provide? Here are a few:

  • Do your business users create use cases or flow charts? If they do, those documents should map uniformly to web flows. In fact, the business users that build the flow charts should be able to interpret your web flow definitions also. Self documenting code that you can also share with the business is valuable.

  • Spring Web Flow provides an additional scope called flowScope. Most applications suffer from session bloat because many developers put data into session out of convenience and do not always think about its consequence. Web Flow alleviates this problem with their flow scope. For example, flow scope is created when your flow starts. And when your flow ends, all data held within flow scope is cleaned up automatically. Now you are running lean! In the example below we put a list of colors in flowScope:
    <flow start-state="start">

    <view-state id="start" view="chooseColor.jsp">
    <on-render>
    <evaluate
    expression="colorService.findAllColors()" 
    result="flowScope.colors" />
    </on-render>

    <transition on="red" to="showRed" />
    </view-state>

    <end-state id="showRed" view="red.jsp"/>
    </flow>



  • Spring Web Flow also has a built-in expression language. The expression language is a feature that allows you to call your Spring beans conveniently from within your flows. In the example above, we fetched our colors from the ColorService.

  • There is less code to maintain compared to the other MVC frameworks. You do not need controller objects anymore. However, you still need to create model objects for binding form data to objects. The form binding in web flow is automatic for simple types.

  • Your flows and transitions can be secured with Spring Security. The example below shows how you may secure your web flow or a transition:
    <flow start-state="start">
    <!-- secure the entire flow -->
    <secured attributes="ROLE_USER" />

    <view-state id="start" view="chooseColor.jsp">
    <transition on="red" to="showRed">
    <!-- secure this transition -->
    <secured attributes="ROLE_ADMIN"/>
    </transition>
    </view-state>

    <end-state id="showRed" view="red.jsp"/>

    </flow>



  • You can achieve reuse with subflows and global transitions.
    <flow start-state="start">

    <view-state id="start" view="chooseColor.jsp">
    <transition on="red" to="showRedSubflow" />
    <transition on="green" to="showGreenSubflow" />
    </view-state>

    <!-- subflow states -->
    <subflow-state id="showRedSubflow"
    subflow="redSubflow.jsp" />
    <subflow-state id="showGreenSubflow"
    subflow="greenSubflow.jsp" />

    <end-state id="thankYou" view="thanks.jsp" />

    <!-- If every page had a cancel button we may declare that transition once. -->
    <global-transitions>
    <transition on="cancel" to="cancel.jsp" />
    </global-transitions>

    </flow>



  • Web flows are browser button friendly. To achieve this, every view state rendered gets stored as a snapshot. When you press the back button, the previous snapshot is retrieved from the snapshot repository. For performance, you may limit the number of snapshots that exist within the snapshot repository.

  • Web flows eliminate the double-submit problem. To accomplish this, Spring will apply the POST-REDIRECT-GET pattern to all POST requests. You may also disable this feature if it's not needed or if you want better performance.

  • As always, Spring has strong JUnit test support to help test your flows.



In conclusion, Spring Web Flow is a very unique MVC framework. It is an ideal solution for simplifying complex work flows. I particularly like the simplicity of the domain specific templating language (DSL), the flowScope, and the expression language capabilities.

Thursday, February 19, 2009

Designing for Accessibility

How accessible is your website? If you are interested in finding out, you may enter your URL at the WAVE website for a quick evaluation. You may also download the WAVE Firefox plug-in for even greater control.

Well, did your site have any errors? Technically, you do not have anything to worry about unless your site is for a government agency. In any case, Web standards are a good thing to design for and this WAVE plug-in can be a great tool to help find any gaps you may have. In addition, this tool can also serve as another check list item for your next client-side code review.

If you are interested in designing for accessibility, the effort is minimal. For example, you can achieve nearly zero accessibility errors by simply focusing on these three categories:
  1. Create accessible forms
  2. Create accessible images with appropriate alt text
  3. Use appropriate heading and table header tags

You may be wondering about dynamic content. If you have dynamically updated content, you will also want to learn about ARIA (Accessibility of Rich Internet Applications). For example, if you have data that gets dynamically updated within a <div> tag you can include aria attributes to notify assistive technologies of dynamic content updates. Here are several examples that demonstrate how to make your dynamic content accessible. There is nothing to install to take advantage of ARIA. ARIA is supported in Firefox 3+ and IE 8+.

In conclusion, the effort involved to implement these accessibility standards is relatively minor. In return, you are designing towards standards, your site is consumable by a larger user base, and you have just given your sales team another competitive advantage. The WAVE plug-in also gives you and your QA team an automated tool to evaluate pages for accessibility compliance.

Thursday, February 12, 2009

A Spring Pattern for Error Logging

Looking for an effective error logging solution? I recently found this pattern from the Pro Spring 2.5 team and it has several very elegant features which include:
  • It is an AOP based solution so it will prohibit you from infecting your business logic with error logging details. This concept isn’t new. The next two features I thought were more interesting.
  • The log details are written to a database. In fact, the exception will only get written once. If an identical exception occurs the count of that occurrence will be incremented. This reduces the redundancy that we see in file based solutions.
  • For reporting purposes, the following exception details will be captured:
    • number of occurrences (nice feature)
    • exception name
    • class and method name
    • method arguments (nice feature)
    • stack trace
    • timestamp of last occurrence



An example report may look like:


There are two components necessary to complete this task. An aspect for identifying the level at which you want to capture exception logging. And secondly, a data access object to manage the persistence. Here's an example of the Spring Aspect that will intercept all Service method calls:

@Aspect
@Component
public class ErrorLoggingAroundAspect {

@Autowired
private ErrorLogDao errorLogDao;

@Around("execution(* com.mycompany.myproject.service.*Service*.*(..))")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
pjp.getSignature().getName();
try {
return pjp.proceed();
} catch (Throwable t) {
insertThrowable(t, pjp);
throw t;
}
}


private void insertThrowable(Throwable t, ProceedingJoinPoint pjp) throws IOException {
StringWriter stackTrace = new StringWriter();
t.printStackTrace(new PrintWriter(stackTrace));
stackTrace.close();
StringBuilder methodArgs = new StringBuilder();
for (Object argument : pjp.getArgs()) {
if (methodArgs.length() > 0) methodArgs.append(",");
methodArgs.append(argument);
}
methodArgs.insert(0, "(");
methodArgs.insert(0, pjp.getSignature().getName());
ErrorLog errorLog = new ErrorLog(
t.getClass().toString(), stackTrace.toString(), methodArgs.toString());
this.errorLogDao.insert(errorLog);
}
}


public class ErrorLog {
private String exceptionName;
private String stackTrace;
private String method;
private int count = 1;

public ErrorLog(String exceptionName, String stackTrace, String method) {
this.exceptionName = exceptionName;
this.stackTrace = stackTrace;
this.method = method;
}
}



Here's the example DAO that will persist the exception to memory. A real solution would persist to a database.

/** Persists to memory.*/
@Repository
public class ErrorLogDaoImpl implements ErrorLogDao {

private List<ErrorLog> errors = Collections.synchronizedList(new LinkedList<ErrorLog>());

public void insert(ErrorLog errorLog) {
for (ErrorLog log : this.errors) {
if (log.getMethod().equals(errorLog.getMethod()) &&
log.getStackTrace().equals(errorLog.getStackTrace())) {
log.setCount(log.getCount() + 1);
return;
}
}
this.errors.add(errorLog);
}

public List<ErrorLog> getAll() {
return this.errors;
}
}


In addition to the code above, you will also need to include <aop:aspectj-autoproxy/> within your Spring configuration file. This tag scans for @Aspect's and turns them into proxies.

Again, I like this solution because it keeps the business-tier clean of logging details, there are no redundant error log messages like we see with file-based solutions, and the persisted data allows for much simpler error reporting. In addition to error logging, I also see this pattern being a good solution for business auditing too.

Saturday, February 7, 2009

Pro Spring 2.5: the Good, the Bad, and the Ugly

Pro Spring 2.5 covers the new 2.5 additions to the Spring framework. The table of contents is viewable from the Apress web site.


The Good:

  • In addition to the new core framework features (JDBC, AOP, remoting, transaction management) they also included chapters about Spring MVC, Spring Web Flow, JMX, testing, and performance tuning.

  • The authors do a good job of including introductory content for new Spring users. In fact, the first eight chapters (Part I) were targeted towards users getting started with Spring.

  • The author's explain many of the new features in great detail and had code examples for nearly everything. However, there are some gaps in their code examples.

  • If you are a fan of Josh Bloch's puzzler's then you will definitely enjoy some of the code examples. The disappointing point is that these were not intentional mistakes! If you do not like puzzlers, then move this one to the bad and ugly category.

The Bad and Ugly:

  • The source code examples in this book contained many typos and copy-paste errors. More than I had ever seen an any book previously. Unfortunately, this may cause confusion for new Spring users.

My recommendation (3.9 stars out of 5):
I originally preordered this book based on the reputation of the first
Pro Spring book. That book was very good and it had great reviews to back it up. Despite the typo's, I have found value in this book. I have given brown bags on the new features of Spring, Spring MVC, and Spring Web Flow and I gathered most of my content from this book. This book has been a good compliment to the Spring reference documentation. However, If you can't tolerate an occasional typo then you may want to avoid this book completely.

Wednesday, February 4, 2009

97 Things Every Software Architect Should Know – The Book

Richard Monson-Haefel's list of 97 Things Every Software Architect Should Know is expected to be released soon by O'Reilly. I personally want to thank Richard for assembling this great list! We have always seen the architectural and programming design pattern books on the shelves but this one will be an awesome compliment.

I think these types of books where content is submitted by many contributors will become much more popular going forward. Career 2.0, by Jared Richardson, is another new book where the content was gathered in a similar fashion. In fact, you may submit your experiences for this book now on their Career 2.0 blog.

Is this a trend? Not sure, but it is interesting.