Tag Archives: Spring

“Spring Data. Modern Data Access for Enterprise Java” (Book Review)

Spring Data is a relatively young set of tools that seems to be quickly gaining popularity. I got introduced to it by Oliver Gierke at 33rd Degree Conference and immediately got really interested (not to say fell in love).

Spring Data is an elegant combination of tools for almost uniform access to various data stores (JDBC, JPA, MongoDB, Neo4j, Redis and others). It has a very slick way to generate queries automatically (even from method names on repository interfaces), with support for paging and sorting as well as auto-generated CRUD.

It makes it very easy to expose repositories on the web via a REST API (and I mean REST, with HATEOAS in the box). In fact, sometimes all you need is to provide entity mapping (e.g. JPA, but there are ways to do similar things with NoSQL stores) and write the repository interface with the right set of annotations. That can be all you need to get a basic REST data service up and running!

Of course you can mix and match or bring more power in. Write your own queries when you need it. Use the repository as data access layer for a “thicker” business layer. Use whatever other Spring tools you like.

The book itself is really well written. It quickly explains the basic ideas behind the data access API. It starts on familiar ground and shows a new way to solve old annoying problems, demonstrating new, streamlined ways to deal with JPA and JDBC repositories. It also offers a new way to write typesafe queries with all the benefits of IDE support: Querydsl.

Then it shows how you can use most of the same API for NoSQL stores, including MongoDB, Neo4j and Redis. Each of those chapters starts with an introduction to the store itself (what it is, what it’s good for). Then it shows how you can use the Spring Data API for, pardon me, Object-NoSQL mapping and writing repositories and queries. As it progresses it gradually dives deeper in the technical details.

Next section is devoted to rapid application development. It features Spring Roo (which I’m not much interested in, not being a fan of codegen) and the REST repository explorer. The latter is a true gem and worth attention on its own. This chapter is also a very good demonstration of (introduction to?) a complete REST API with hyperlinks, CRUD, search, relationships between resources etc.

Towards the end of the book there are also 3 chapters on Hadoop. The final chapter is devoted to GemFire, a distributed data grid.

Spring Data is definitely worth a close look, and this book is a perfect resource to get started. Authors had a very good plan on what they wanted to say and executed it perfectly. The language is fairly light, clear and easy to follow. The examples are interesting, simple and concise at the same time. Very easy to understand, but not simplistic – they demonstrate the underlying power and do a good job of exposing all the gory details. You get to see a fairly wide and reasonably deep view of the framework.

What else could you possibly want from a technical book? Oh yes, and it has a squirrel on the cover!

Many thanks to Oliver for a copy of the book.

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.

Testing Spring & Hibernate Without XML

I’m very keen on the improvements in Spring 3 that eventually let you move away from XML into plain Java configuration with proper support from IDE and compiler. It doesn’t change the fact that Spring is a huge suite and it sometimes finding the thing you need can take a while.

XML-free unit tests around Hibernate are one such thing. I knew it was possible, but it took me more than 5 minutes to find all the pieces, so here I am writing it down.

I am going to initialize all my beans in a @Configuration class like this:

@Configuration
@EnableTransactionManagement
public class TestRepositoryConfig {
	@Bean
	public DataSource dataSource() {
		return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
				.setName("Nuts").build();
	}

	@Bean
	public LocalSessionFactoryBean sessionFactoryBean() {
		LocalSessionFactoryBean result = new LocalSessionFactoryBean();
		result.setDataSource(dataSource());
		result.setPackagesToScan(new String[] { "pl.squirrel.testnoxml.entity" });

		Properties properties = new Properties();
		properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
		result.setHibernateProperties(properties);
		return result;
	}

	@Bean
	public SessionFactory sessionFactory() {
		return sessionFactoryBean().getObject();
	}

	@Bean
	public HibernateTransactionManager transactionManager() {
		HibernateTransactionManager man = new HibernateTransactionManager();
		man.setSessionFactory(sessionFactory());
		return man;
	}

	@Bean
	public OrderRepository orderRepo() {
		return new OrderRepository();
	}
}

… and my test can look like this:

@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback = true)
@ContextConfiguration(classes = { TestRepositoryConfig.class })
@Transactional
public class OrderRepositoryTest {
	@Autowired
	private OrderRepository repo;

	@Autowired
	private SessionFactory sessionFactory;

	@Test
	public void testPersistOrderWithItems() {
		Session s = sessionFactory.getCurrentSession();

		Product chestnut = new Product("Chestnut", "2.50");
		s.save(chestnut);
		Product hazelnut = new Product("Hazelnut", "5.59");
		s.save(hazelnut);

		Order order = new Order();
		order.addLine(chestnut, 20);
		order.addLine(hazelnut, 150);

		repo.saveOrder(order);
		s.flush();

		Order persistent = (Order) s.createCriteria(Order.class).uniqueResult();
		Assert.assertNotSame(0, persistent.getId());
		Assert.assertEquals(new OrderLine(chestnut, 20), persistent
				.getOrderLines().get(0));
		Assert.assertEquals(new OrderLine(hazelnut, 150), persistent
				.getOrderLines().get(1));
	}
}

There are a few details worth noting here, though:

  1. I marked the test @Transactional, so that I can access Session directly. In this scenario, @EnableTransactionManagement on @Configuration seems to have no effect as the test is wrapped in transaction anyway.
  2. If the test is not marked as @Transactional (sensible when it only uses @Transactional components), the transaction seems to always be committed regardless of @TransactionConfiguration settings.
  3. If the test is marked as @Transactional, @TransactionConfiguration seems to be applied by default. Even if it’s omitted the transaction will be rolled back at the end of the test, and if you want it committed you need @TransactionConfiguration(defaultRollback=false).
  4. This probably goes without saying, but the @Configuration for tests is probably different from production. Here it uses embedded H2 database, for real application I would use a test database on the same engine as production.

That’s it, just those two Java classes. No XML or twisted depedencies. Take a look at my github repository for complete code.

Integrating Spring, Velocity and Tiles

I like Tiles and I heard a lot about Velocity. They seem to serve different purpose and reportedly are easily married together, so I decided to give it a shot and use them both in Spring web app. The integration actually took many hours and was a real rollercoaster during which I learned a lot about all three technologies. Hopefully this post can spare someone this fun and let them focus on business.

Goals

When I use tiles, I don’t like the default (?) approach of tiles.xml. I don’t want to put imports of JS & CSS, page title, navigation, body etc. each in its own file like in the snippet below, because that makes me switch between editor windows.

<definition name="hello" template="/WEB-INF/templates/main.jsp">
	<put-attribute name="title" value="Hello" type="string" />
	<put-attribute name="head" value="/WEB-INF/templates/hello-js-and-css.jsp" />
	<put-attribute name="nav" value="/WEB-INF/templates/hello-nav.jsp" />
	<put-attribute name="body" value="/WEB-INF/templates/hello.jsp" />
</definition>

Obviously I don’t want to put too much detail in tiles.xml, either.

What I really like is having one file per page, assembling the template in one place, such as this piece of JSP:

<tiles:insertTemplate template="template.jsp">
	<tiles:putAttribute name="title" value="Hello" />
	<tiles:putAttribute name="head">
		<script type="text/javascript" src="/js/jQuery.js" />
		<script type="text/javascript" src="/js/hello.js" />
	</tiles:putAttribute>
	<tiles:putAttribute name="body">
		<div>Hello, world!</div>
	</tiles:putAttribute>
</tiles:insertTemplate>

In Velocity, it’s supposed to look like this:

#tiles_insertTemplate({"template": "template.vm"})
	#tiles_putAttribute({"name":"title", "value": "Hello"})#end
	#tiles_putAttribute({"name":"head"})
		<script type="text/javascript" src="/js/jQuery.js" />
		<script type="text/javascript" src="/js/hello.js" />	
	#end
	#tiles_putAttribute({"name":"body"})
		<div>Hello, world!</div>
	#end
#end

However, the docs on integration are really intended for adding some Velocity support to your Tiles-based app, while I wanted quite the opposite: Use Tiles in my rich Velocity app, with full support for spring context, macros etc.

Solution

In short, what we’re going to do is:

  1. Use VelocityViewResolver to resolve and render pages
  2. Add support for Tiles macros to this Velocity rendering engine
  3. Extend the Tiles renderer with full support for Velocity, including Spring context, macros etc. Ultimately we’re going to make it use the original Velocity engine created by Spring.

Full source code in form of a minimal, complete web app are at github. For details see below.

Spring & Velocity -> Tiles

For the first step, we define viewResolver and velocityConfig like this:

@Bean
public VelocityConfig velocityConfig() {
	VelocityConfigurer cfg = new VelocityConfigurer();
	cfg.setResourceLoaderPath("/WEB-INF/velocity/");
	cfg.setConfigLocation(context
			.getResource("/WEB-INF/velocity.properties"));
	return cfg;
}

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

It’s important that we use VelocityToolboxView there, otherwise the tiles directives won’t work.

We also need to put the following in velocity.properties:

userdirective=org.apache.tiles.velocity.template.AddAttributeDirective,\
  org.apache.tiles.velocity.template.AddListAttributeDirective,\
  org.apache.tiles.velocity.template.DefinitionDirective,\
  org.apache.tiles.velocity.template.GetAsStringDirective,\
  org.apache.tiles.velocity.template.ImportAttributeDirective,\
  org.apache.tiles.velocity.template.InsertAttributeDirective,\
  org.apache.tiles.velocity.template.InsertDefinitionDirective,\
  org.apache.tiles.velocity.template.InsertTemplateDirective,\
  org.apache.tiles.velocity.template.PutAttributeDirective,\
  org.apache.tiles.velocity.template.PutListAttributeDirective

This adds basic support for Tiles directives to Velocity, but it’s still useless because once Velocity hands rendering over to Tiles, Tiles is unable to render Velocity and would simply ignore it (rendering syntax of #directives to browser.

Tiles -> Velocity

We need to teach Tiles to use Velocity. For this we’re going to need a custom TilesInitializer:

@Bean
public TilesConfigurer tilesConfigurer() {
	TilesConfigurer cfg = new TilesConfigurer();
	cfg.setTilesInitializer(new VelocityTilesInitializer(velocityConfig()));
	return cfg;
}	
public class VelocityTilesInitializer extends DefaultTilesInitializer {
	private VelocityConfig velocityConfig;

	public VelocityTilesInitializer(VelocityConfig velocityConfig) {
		this.velocityConfig = velocityConfig;
	}

	@Override
	protected AbstractTilesContainerFactory createContainerFactory(
			TilesApplicationContext context) {
		return new BasicTilesContainerFactory() {

			@Override
			protected List<TilesRequestContextFactory> getTilesRequestContextFactoriesToBeChained(
					ChainedTilesRequestContextFactory parent) {
				List<TilesRequestContextFactory> factories = super
						.getTilesRequestContextFactoriesToBeChained(parent);
				registerRequestContextFactory(
						VelocityTilesRequestContextFactory.class.getName(),
						factories, parent);
				return factories;
			}

			@Override
			protected AttributeRenderer createTemplateAttributeRenderer(
					BasicRendererFactory rendererFactory,
					TilesApplicationContext applicationContext,
					TilesRequestContextFactory contextFactory,
					TilesContainer container,
					AttributeEvaluatorFactory attributeEvaluatorFactory) {
				ContextPassingVelocityAttributeRenderer var = new ContextPassingVelocityAttributeRenderer(
						velocityConfig.getVelocityEngine());
				var.setApplicationContext(applicationContext);
				var.setRequestContextFactory(contextFactory);
				var.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
				var.commit();
				return var;
			}
		};
	}
}

We’re almost there, but here’s a tricky bit. Normally in lines 31-32 you would put velocityAttributeRenderer. However, this renderer completely ignores the Spring-augmented Velocity context & engine that Tiles received from Velocity. It creates its own VelocityEngine and lets it do the rendering, throwing away all the Spring and tiles directives and context objects.

There is no way to change this behavior in Tiles (which otherwise seems to be an interesting study in design patterns and extensibility). I even created two JIRA issues for it: 541 for forwarding context and 542 for injecting VelocityEngine.

Meanwhile, we have to make do with this workaround (see github for full source):

public class ContextPassingVelocityAttributeRenderer extends
		AbstractTypeDetectingAttributeRenderer {
	// ...

	private VelocityEngine engine;

	public ContextPassingVelocityAttributeRenderer(VelocityEngine engine) {
		this.engine = engine;
	}
	
	// ...

	public void commit() {
		velocityView = new VelocityView(new TilesApplicationContextJeeConfig());
		velocityView.setVelocityEngine(engine);
	}

	@Override
	public void write(Object value, Attribute attribute,
			TilesRequestContext request) throws IOException {
		if (value != null) {
			if (value instanceof String) {
				InternalContextAdapter adapter = (InternalContextAdapter) ((VelocityTilesRequestContext) request)
						.getRequestObjects()[0];
				Context context = adapter.getInternalUserContext();
				Template template = velocityView.getTemplate((String) value);
				velocityView.merge(template, context, request.getWriter());
			} else {
				throw new InvalidTemplateException(
						"Cannot render a template that is not a string: "
								+ value.toString());
			}
		} else {
			throw new InvalidTemplateException("Cannot render a null template");
		}
	}
	
	// ...

It works arounds both of the JIRA issues and lets us accomplish the ultimate goal:

  1. The VelocityEngine injected to VelocityView here is the original VelocityEngine from Spring. Among other things, it supports Spring directives and context-dependent tools.
  2. The TilesRequestContext in write method still contains the original Velocity context created from Spring scaffolding. Standard implementation of VelocityAttributeRenderer simply throws it away. This workaround above extracts the original context and uses it for rendering.

Conclusion

This journey took much more time than I thought. Documentation on such cases is nonexistent, so I spent hours debugging, reading source code, experimenting, praying and cursing. It was even more fun as I had close to zero knowledge of internals of Spring view resolution and rendering engine, as well as Tiles and Velocity.

It’s quite satisfying since I learned a ton about all those technologies and eventually was able to resolve it in a fairly elegant way. But it was also a frustrating and time-consuming riddle and I hope this post spares someone some trouble.

Update – Velocity Tools

A while later I discovered this solution does not support Velocity Tools property. Here’s how to add it: Spring & Velocity Tools.