Monthly Archives: July 2012

Spring: @EnableWebMvc and JSR-303

I’ve been happily using XML-free Spring with Web MVC, right until the moment when I wanted to plug in JSR-303 validation.

Failure

I imported validation-api and hibernate-validator to my project. I annotated code for my command:

public class SpendingCommand {
@Size(min=3)
private String category;
// ...
}

… and controller:

@Controller
public class SpendingEditionController {

@RequestMapping(value = "/spending_insert", method = RequestMethod.POST)
public String addSpending(@Valid SpendingCommand spending, 
		BindingResult result, ModelMap model) {
	return "my_view";
}

// ...
}

I plugged it in to form:

#springBind("command.$field")
<label for="$field" class="control-label">${label}:</label>
<div class="controls">
	<input type="text" name="${status.expression}" value="$!{status.value}" />
	$!{status.errorMessage}
</div>

… and nothing happened.

I looked for errors in BindingResult in my controller, and nothing was there. Clearly validation was not working at all.

Almost There: @Valid Working

I read a ton of tutorials, and they did not mention any specific black magic. After a long while of doc reading, random trying and debugging, I found this StackOverflow answer. Skaffman said that <mvc:annotation-driven /> was “rather pointless” so “don’t bother”. Luckily I read comments to that answer as well and discovered that this is actually crucial for all the new goodies in Spring Web MVC, including conversions and validation.

I added annotation equivalent of mvc:annotation-driven to my view configuration:

@Configuration
@ComponentScan(basePackages = "pl.squirrel.money.web")
@EnableWebMvc
public class ViewConfig

When I tested my code again, I did see errors in BindingResult in my controller, so finally validation was working. Unfortunately, the web page still did not show the message. Do you know why?

Bindings and Naming Conventions

It took me even longer to figure this one out. I even began to suspect my custom view for Velocity Tools & Tiles.

Finally in debug I noticed I had my command bound twice in page context: as command and as spendingCommand. I had two bindings for BindingResult as well, but with two different instances! One was org.springframework.validation.BindingResult.command, with zero errors, and another was org.springframework.validation.BindingResult.spendingCommand, containing all errors as expected.

In a word, mess. To clean this up, I had to explicitly name my command like this:

@RequestMapping(value = "/spending_insert", method = RequestMethod.POST)
public String addSpending(@ModelAttribute("command") @Valid SpendingCommand spending,
		BindingResult result, ModelMap model) {
	return "my_view";
}

Now I only have one instance of everything, and everything is working as expected. And they lived happily ever after.

Quirks

In the end, I find it interesting (in a bad sense) that it works like this. I think it’s a bug that the same command is bound under two different names, but it’s quite the opposite for BindingResult.

To test it, I attempted to edit this SpendingCommand in controller by overwriting value of a field. At this point I knew what would happen: My web page showed overwritten value in form (because Spring was still able to match the command with different name), but no validation errors (because there are two different instances of BindingResult.

Spring & Velocity Tools (No XML)

A few months ago I wrote about integrating Spring, Velocity and Tiles. I discovered that one bit was missing from there: Velocity Tools. Two hours of yak shaving, frantic googling and source reading later, I figured out how to add support for Velocity Tools to such project with no XML configuration. Here’s how.

For starters, let’s say I want to use some tools in my Velocity and Tiles pages. Let’s add the LinkTool.

template.vm:

<html>
	<head><title>#tiles_insertAttribute({"name":"title"})#end</title></head>
	<body>
		#tiles_insertAttribute({"name":"body"})#end
		<p>Spring macros work in tiles template, too: #springUrl("/myUrl")</p>
		<p>Do Velocity tools work in template? $link.contextPath</p>
	</body>
</html>

body.vm:

<p>Here's a demonstration that Spring macros work with Tiles: #springUrl("/myUrl")</p>
<p>Do Velocity tools work in Tile? $link.contextPath</p>

When I render the code from previous post, I get this:

Here's a demonstration that Spring macros work with Tiles: /SpringVelocityTiles/myUrl

Do Velocity tools work in Tile? $link.contextPath

Spring macros work in tiles template, too: /SpringVelocityTiles/myUrl

Do Velocity tools work in template? $link.contextPath

Not good.

After some googling, I found a similar question on StackOverflow. It had two helpful answers – one from serg, delegating to this blog post, and another from Scott.

None of them worked out of the box, though. I’m tired of XML configs, and apparently it’s too easy to get weird exceptions related to some Struts tools. No wonder I get them, I don’t use Struts and don’t want any of its tools!

Apparently the issue is that Spring support for Velocity Tools is rubbish. One way out is to write your own ViewResolver or View, and that’s what I did in the end.

For starters, I’ll configure my ViewResolver to use a new view class:

@Bean
public ViewResolver viewResolver() {
	VelocityViewResolver resolver = new VelocityViewResolver();
	resolver.setViewClass(MyVelocityToolboxView.class);
	resolver.setSuffix(".vm");
	return resolver;
}

MyVelocityToolboxView is below. This time I’m pasting it with imports to avoid ambiguity on names like Context or VelocityView.

package pl.squirrel.svt;

import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.context.Context;
import org.apache.velocity.tools.Scope;
import org.apache.velocity.tools.ToolboxFactory;
import org.apache.velocity.tools.config.ConfigurationUtils;
import org.apache.velocity.tools.view.ViewToolContext;
import org.springframework.web.servlet.view.velocity.VelocityView;

public class MyVelocityToolboxView extends VelocityView {
	@Override
	protected Context createVelocityContext(Map<String, Object> model,
			HttpServletRequest request, HttpServletResponse response) {
		ViewToolContext context = new ViewToolContext(getVelocityEngine(),
				request, response, getServletContext());
		
		ToolboxFactory factory = new ToolboxFactory();
		factory.configure(ConfigurationUtils.getVelocityView());
		
		for (String scope : Scope.values()) {
			context.addToolbox(factory.createToolbox(scope));
		}

		if (model != null) {
			for (Map.Entry<String, Object> entry : (Set<Map.Entry<String, Object>>) model
					.entrySet()) {
				context.put(entry.getKey(), entry.getValue());
			}
		}
		return context;
	}
}

It’s important that we only use ConfigurationUtils.getVelocityView() – it includes generic tools and view tools, but not Struts tools.

That’s it, now we have a project which uses Tiles for high-level templating, Velocity for individual pages and details, with (hopefully) full support for Spring macros and Velocity tools in all areas. Even if you don’t like Tiles, it may still serve as a good example of how to integrate Spring and Velocity Tools.

I pushed updated code for the demo application to my GitHub repository.

In the irregular habit of posting a sermon on Friday… Less than a week ago I saw an excellent presentation on using Clojure for Spring views. Compared to all this mess and yak shaving here, that Clojure solution is infinitely simpler, more elegant and more powerful at the same time. Too bad it does not have the market share of Spring & Velocity yet.

Confitura 2012 & “Boring” Application of Clojure

This year I attended the Confitura conference for the first time. Many posts have been written on it, so I’ll focus on one (but not the only) presentation that I found particularly worthwhile.

Clojure…

I started my day with talk on Clojure as HTML Templating Language by Łukasz Baran. Despite all the advocacy for Clojure that I do, I was surprised to find this presentation in the agenda – specialized, concrete talk instead of a generic “Clojure is awesome! Go use it!”. Another surprise came from the fact that someone in Poland was serious about using it commercially. I suspect I wasn’t the only surprised person there, as there were a few dozen people in the room and only few of them used Clojure or even functional programming.

Łukasz showed how you can use Clojure for HTML templating in Java projects. He described a team which moved from Velocity to Clojure ca. 2009. They created a DSL for HTML similar to Hiccup (before Hiccup became popular), and went a step further implementing a component library and other automations. From the very beginning they assumed it would be called from Java, so they wrote a loosely coupled component that you can plug in to Spring. Finally, they’ve been using it in production for years and are very happy with it.

Why do this, and why this way? Compared to Velocity, Clojure is very fast, concise, powerful and productive. It has gentle learning curve (when narrowed down to DSL). It was much easier to introduce Clojure in a big enterprise Java shop this way than to write purely Clojure projects from scratch (this may be a good approach in general, by the way).

Personally, I really liked it that this presentation was limited to such a boring, but concrete area. Everyone knows something about writing view layers in Java webapps. Everyone knows pains of JSP (Velocity & other frameworks or not). This presentation showed that it can be done differently and the pain points can be mitigated. It also was a great proof that Clojure has its place and is no academic black magic. In other words, advocacy done right: Instead of showing off the new tool from an ivory tower, demonstrate how it can solve a concrete everyday problem.

… and the Rest

That was not the only good thing at this Confitura. In fact, I really enjoyed most of the talks I saw there.

Paweł Wrzeszcz gave a very good presentation on How to work remotely and don’t go crazy. He showed many good habits for teams and individuals that let you live a healthy life in a healthy project. Though my personal conclusion is that even if you do everything right as an individual, team culture can kill and sometimes the only way out is… out.

I saw two talks on testing, by Jacek Kiljański and Tomek Kaczanowski. Jacek seemed to be a young passionate who believes in everything he says, but also had a well prepared presentation on Clean Tests with clear message and good examples. The following talk by Tomek was quite different – felt more like a rational, sometimes skeptical veteran sharing war stories. It may be due to my tiredness or combination of high temperature and low oxygen, but I did not find this presentation as sharp and clear as the previuous one. Part of the story might be that Jacek stole Tomek’s thunder and there was much overlap.

After a break I went to Maciek Próchniak’s talk on Scala, CQRS and Event Sourcing, but I was rather disappointed. It was pretty chaotic and shallow. I suspect that if you had a slight idea of CQRS and ES, you could not learn much new – even though the problem at hand had some depth that could be discussed in more detail. On the the hand, it assumed too much of the listener to be suitable for a beginner.

Then I saw Sławek Sobótka’s presentation about Soft aspects for IT experts. It was centered around Dreyfuss skill acquisition model (again, and even Sławek admitted it’s something that appears a few times at each conference). Still, it managed to offer something new by only treating the model as a framework and an excuse to dive into many interesting aspects of psychology. Very professional, enjoyable and worthwhile.

Our day ended with Wojciech Seliga’s keynote titled How to be awesome at a Java developer job interview. Less of a talk, more of an emotional rant, but most of the time I really agreed with the presenter. I know way too many careless, ignorant people who consider themselves experts and neglect common tools and practices, stopped learning years ago or simply don’t know what they’re doing.

All in all, it was a very good conference. More technical and low-level than 33rd Degree. By no means “worse” or “better”, just different. Felt like a family get-together, rather than a big conference with big names talking about big stuff that put things in perspective or show some trends, but are somewhat detached from our daily work.