Chapter 14. Spring and transactions


In this chapter

  • Introducing the Spring Framework
  • Making the most of Spring
  • Mastering transactions

After plumbing the depths of GORM and Hibernate, it’s time to move back up the abstraction hierarchy and look at the application infrastructure. GORM is wonderful as a database abstraction layer, and you can work some magic with controllers and GSPs, but just as a vertebrate needs a backbone to hold all its appendages together, so too does an application.

Fortunately, Grails is built around a tried and tested framework that will help you grow your application: Spring. We’ve mentioned it in passing a few times, and it tends to remain invisible if your application remains fairly simple. The trouble is, if it stays invisible, you’ll miss out on powerful tools in your armory. We can’t have that, so this chapter will explain some of the basics of the framework and how Grails allows you to interact with it directly.

After that, we’ll look at a feature that will come in handy after all the talk of databases in the previous chapter: transactions. Although not part of the core Spring framework, Spring’s transaction support is instrumental in building reliable, data-oriented applications. It’s an important topic that deserves, and receives, thorough treatment.

Let’s find out what Spring can do for you.


Note

If you’re already a Spring aficionado, we suggest you skim the next section and give the introduction on services a brief once over.


14.1. Spring and Grails

Some time ago, a new paradigm emerged in application design called Inversion of Control (IoC). The principle is simple: instead of an object managing its own dependencies, the code creating that object manages them. The application delegates the responsibility for creating and initializing its objects to a third party—an IoC container. Figure 14.1 illustrates the difference between the two approaches.

Figure 14.1. Inversion of Control compared to the traditional approach of dependency management: all objects are created by the IoC container rather than by the object themselves.

When you look at figure 14.1, it seems obvious that the traditional approach is simpler to understand, so why bother with IoC? There are several significant advantages to using IoC, but the critical point is that the complexity of dependency management is taken out of the class, leaving the important logic. The code for dealing with creating or finding the appropriate dependencies can be the nastiest stuff in a class, so why not make it somebody else’s problem? Your classes become simpler and easier to manage, and, as a side effect, they become much easier to test.

The most common form of IoC nowadays is known as Dependency Injection, which is the pattern implemented by Spring. It’s beyond the scope of this book to provide a detailed description of Dependency Injection, but you can find out more on Wikipedia: http://en.wikipedia.org/wiki/Dependency_injection.

As a Dependency Injection implementation, Spring manages the lifecycle of an application’s objects, which is just a fancy way of saying it creates, initializes, and destroys them. These managed objects are called “Spring beans,” and they’re regular Java objects—they don’t even have to comply with the JavaBeans specification, which makes the name slightly confusing.

Note that Spring is rarely used to manage all the objects in an application. Developers commonly use it to manage the singletons in their applications. For example, this class could be a Spring bean without any changes:

class MyService { 
TransactionManager transactionManager

void doTransaction() {
...
}
}

See how there’s no reference to Spring in this class? Whether it’s a Spring bean depends entirely on whether it’s managed by the Spring framework.

Because a Spring bean is a Plain Old Java Object (POJO), the framework needs some way of knowing how to connect, or wire, different beans together and what values to initialize their properties to. This is achieved through a bean descriptor that contains the required bean definitions—the information necessary to initialize each object. Every bean managed by Spring must have an associated bean definition.

So how does one go about creating one of these bean descriptors? Traditionally, you would create an XML file that followed a particular schema, but Grails simplifies the whole business through convention and a nice DSL. We’ll look at both the XML and DSL forms in section 14.1.2 (both have their uses), but we’ll start by looking at Grails’ entry-level Spring beans: services.

14.1.1. A conventional approach

In a typical Grails application, you start with some of your domain classes and then progress to writing the controllers and views. As you progress, the temptation is to put more and more logic into the controllers, making them heavy and giving them responsibility for more than the UI. You then find that you need to reuse some of that functionality (for example, from a web service gateway) and discover that controllers can’t easily be called from other parts of your application.

For a variety of reasons, best practice dictates that business logic—the stuff unrelated to the UI—should go into Grails services. What this best practice is doing is following the principle of Separation of Concerns (SoC), where a “concern” is a selfcontained area of functionality or, perhaps more accurately, responsibility. For example, the UI is one concern, database access is another, and access control might be a third. By limiting a single class to only one concern, the application code is easier both to understand and modify. Typically controllers stick to UI-related matters, and services host the business logic of the application.

In practice, this means that the real work of the application should be implemented in services. As a general rule of thumb, controllers should not access the database directly except in the case of trivial queries that have little reuse value. Unfortunately, hard-and-fast rules are difficult to come by, but the overall effect we’re after is illustrated in figure 14.2.


More on SoC

You shouldn’t stop thinking about Separation of Concerns once you split your code between controllers and services. Applications themselves are often collections of concerns, so you should apply the principle throughout your code. In Hubbub, for example, managing individual posts could be treated as one concern, searching as another, and managing friends and followers as a third. Also, packages are an ideal way of grouping classes by concern.


Figure 14.2. Typical application architecture using services to encapsulate business logic

You’ve already seen services in action in chapter 5, and you’ve seen how they can be injected into controllers and other Grails artifacts. How does all that magic happen? Under the hood, Grails creates Spring beans for services such that the name of the bean is the class name with a lowercase first letter. So PostService becomes a bean named postService.


Tip

Because closures behave a lot like methods, you may be tempted to use them in services instead of methods. This isn’t a good idea because transactions and other features that depend on method interception won’t work properly. The problem is that neither Spring nor Java know anything about closures, so they’re treated as fields. Only methods get special treatment.


Bean names are an important part of Spring, because they’re used for wiring objects together. In typical Spring applications, the interdependencies between beans defined in bean descriptors, but Grails uses a special feature of Spring to magically inject a bean with its dependencies.

Dependency Management by Magic

Let’s take another look at the post controller and service from chapter 5. The two classes look something like this:

class PostService {
boolean transactional = true

Post createPost(String userId, String content) {
...
}
}
class PostController {
def postService

def scaffold = true
...
}

You should now see that the controller has a property with the same name as the Spring bean resulting from PostService. That’s the key to automatic Dependency Injection.

Spring has a feature called “autowiring” that takes the rigmarole out of manually declaring dependencies, and it works like this: if one Spring bean has a property with the same name as another bean, Spring automatically wires the second bean into that property. Hence the postService property in the post controller is initialized with the actual post service. All of this magically happens before any bean is used, so your service methods and controller actions can happily assume that the relevant properties have already been initialized.


Autowiring by type

Experienced Spring developers will know that you can also autowire beans by type. All the beans managed by Grails are autowired by name, and you can’t change that, but when we discuss user-defined bean descriptors, you’ll see that you can autowire your own beans by type.

While we’re on types, did you notice that postService is declared as a dynamically typed property? That’s partly because class-reloading currently fails if you declare the property with the static type of the service. It’s a class-loading problem that may take some time to fix, so at the moment it’s best to use def for injected services.


Hold on a second. If the autowiring only works for Spring beans, how come the controller is injected with the post service? Simple: controllers are also Spring beans. That said, we strongly recommend that you don’t attempt to wire controllers into other beans. There are no guarantees that the bean names and types will stay the same in the future, and controllers can’t easily be reused by other code.

Any named bean can be injected in this way. Grails defines many beans itself, and you can see a select list of them in table 14.1. Some of these can be useful when the usual Grails mechanisms can’t help.

Table 14.1. Some useful Spring beans in Grails

Bean name

Type

Provided by

grailsApplication

DefaultGrailsApplication

Grails core

sessionFactory

org.hibernate.SessionFactory

Hibernate plugin

groovyPagesTemplateEngine

GroovyPagesTemplateEngine

Controllers plugin

messageSource

ReloadableResourceBundleMessageSource

I18n plugin

The grailsApplication bean is useful for getting information about the application, such as its configuration, the Spring application context (covered next), and the loaded artifacts. If you need direct access to Hibernate, inject the sessionFactory bean into your classes. Want to parse GSP pages yourself? Consider using the groovyPagesTemplateEngine bean. And last but not least, the messageSource bean allows you to manually look up the appropriate text for a given message code.

That’s only a taste of what’s available; almost every plugin adds its own beans to the mix. The main obstacle to using them is knowing that they exist in the first place! Some documentation (both for Grails and plugins) may mention them, but often the only way to find out is to ask on the Grails mailing lists or look at the plugin descriptors. You’ll find out more about the latter in chapter 16. Fortunately, you rarely need to access the Spring beans directly, and the relevant documentation will surely improve.

Dependency Injection works well and makes life easy, but sometimes you want to get hold of beans from within objects that aren’t managed by Spring. What then?

The Spring Application Context

We’ll move out of the realm of convention here to look at another way of fetching Spring beans. Let’s say you have a servlet that you want to add to your application, and it needs access to the services. The only way to get a reference to a service is via Spring, but how do you access Spring from an unmanaged object?

The answer to this conundrum is Spring’s application context, the singleton object that manages the beans and the loading of resources. It’s, in essence, the core of the Spring IoC container. It provides several helpful features, but the one we’re interested in right now is the getBean() method:

PostService postService = applicationContext.getBean("postService")

That’s pretty straightforward, but we’ve skirted the issue of how you get a reference to the application context in the first place. You have a couple of choices here. You can get the application context from the servlet context by issuing this magic incantation:

import org.springframework.context.ApplicationContext
import org.springframework.web.context.support.WebApplicationContextUtils

ApplicationContext appCtx =
WebApplicationContextUtils.getWebApplicationContext(servletContext)

Talk about a mouthful! Verbosity aside, this is a useful approach if you have ready access to the servlet context, as you would in a servlet. The alternative is to use the Grails application instance, like so:

import org.codehaus.groovy.grails.commons.ApplicationHolder

def grailsApp = ApplicationHolder.application
def appCtx = grailsApp.getMainContext()

This is the preferred method if you need to get hold of the application context but the servlet context isn’t available. For more information on this marvelous object, check out both the Spring reference guide and the API documentation.

The conventional approach that we looked at in this section is easy to use and quite powerful. But at some stage, convention invariably becomes a limiting factor when creating and configuring Spring beans. In the next subsection, we’ll look at a more powerful and flexible technique for that job.

14.1.2. Creating and defining your own beans

We mentioned earlier how Grails defines quite a few Spring beans itself, and you now know that your services are Spring beans too. But what if you have classes that don’t fit the mold of services? They may be provided by a Java library in a JAR file, for example. You need some way of informing Spring about them.

As you would expect, Grails has the answer. In fact, it has two of them. You can add Spring bean definitions to the grails-app/conf/spring/resources.xml file, the grailsapp/conf/spring/resources.groovy file, or both. They work in similar ways, but the format for defining the beans in the two files is quite different: one is XML-based and the other uses a Groovy domain-specific language (DSL).


Load order

Both resources files are loaded after all the core Grails and plugin beans have been defined. This means that you can refer to Grails and plugin beans from your resources files, but plugins can’t see the beans you define.

More importantly, you can override beans that have already been defined by a plugin. For example, if you define a bean named messageSource, it will be used instead of the bean defined by the i18n plugin.


That leaves us in a bit of a quandary. Which method is better depends on whether you’re more comfortable working with XML or the DSL. Consider this: the Spring DSL allows you to use variables, conditions, loops, and all manner of Groovy goodness. XML is just XML.

We’ll only be looking at the Spring DSL in detail here, but if you would like to find out more about Spring XML bean descriptors, take a look at the Spring reference guide: http://static.springframework.org/spring/docs/2.5.x/reference/. It will give you a good grounding in the features available in Spring and how to use them.

Introducing the Spring DSL

We’ll admit that we don’t like working with XML much. Fortunately, we don’t have to in order to define Spring beans. Like most Groovy-based DSLs, the Spring DSL uses method and closure notation to describe the bean configuration. In essence, any call to a nonexistent (or missing) method is treated as the start of a new bean definition.

Listing 14.1 contains an example resources.groovy file that we will deconstruct so that you can see how it works. This particular example sets up Hibernate statistics collection via JMX (Java Management Extensions).

Listing 14.1. Example bean definitions in resources.groovy

Because resources.groovy is a plain Groovy script, you can pretty much put anything you like in there. But to define Spring beans, you must declare a beans script variable and assign a closure to it. If any of your bean definitions fall outside of that closure, they won’t be picked up by Grails and will likely cause an exception.

What does a bean definition look like in this DSL? It consists of the bean name followed by the bean class in parentheses ; the method name becomes the bean name, and the argument maps to the bean class. In an XML file, the bean class would be a string, but because this is Groovy, you can use class literals. That means you can use imports to keep the definitions tidy.

If you want to configure properties of the bean, you must follow the declaration with a closure block as we’ve done for all three bean definitions in the example. Inside this block, you can set properties using the simple <property name> = <value> notation. In contrast to the XML form, in which everything is a string, the value in the DSL should be of the appropriate type for the corresponding property. In listing 14.1, we set both Boolean and map properties. This syntax means that initializing collections and maps is far more succinct than with the XML format.

Using bean references is the manual approach to wiring beans together. They’re specified in the same way as normal properties, but you have two options for what goes on the right side of the assignment. First, you can set the property to the name of the bean definition without quotes , but this only works if the target bean was defined earlier in the same file. The second option is to use the ref() method , which takes the name of a bean as a string. Of these two options, we prefer the second because it will always work regardless of where the target bean is defined or of the order of the bean definitions in the resources.groovy file.

That was easy. We may not have shown many techniques in this example, but you’ll find that they suffice for a large percentage of cases. To get some insight into the more specialized features, we’ll compare the DSL to the XML format. This will allow you to learn the intricacies of Spring from another source and then apply that knowledge to the DSL.

Comparing Spring’s XML and DSL Formats

The Spring DSL supports almost all of the features you’ll find in the Spring XML descriptor format. In table 14.2, you’ll see the equivalent DSL syntax for various XML forms. If you don’t understand what a particular form is or what it does, check out the online Spring reference manual, which covers all of these variations and more.

Table 14.2. Comparing the Spring XML descriptor format to Spring DSL

Feature

XML

Spring DSL

Bean attributes

<bean id="ex" class="o.e.Ex"
scope="prototype"
autowire="byType"
init-method="init"
destroy-method="finish"/>

ex(o.e.Ex) { b -> 
b.scope = "prototype"
b.autowire = "byType"
b.initMethod = "init"
b.destroyMethod = "finish"
}

Lists

<bean id="ex" class="o.e.Ex">
<property name="items">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>

ex(o.e.Ex) {
items = [1, 2, 3]
}

Static factory methods

<bean id="ex" class="o.e.Ex"
factory-method="create"/>

ex(o.e.Ex) { b ->
b.factoryMethod = "create"
}

Instance factory methods

<bean id="ex"
factory-bean="myFactory"
factory-method="create"/>

ex(myFactory: "create")

As you can see from the table, some features are much more concise in the Spring DSL. That, along with being able to use real types for property and constructor argument values, would be enough to sway even the most ardent of XML fans. But as we mentioned earlier, you can use Groovy’s flow control in the DSL as well.

Consider this example, where serviceName and isTransactional are variables set elsewhere:

def beanNames = [ "transactionInterceptor" ]

"${serviceName}Manager"(org.example.ServiceManager) {
service = serviceName
if (isTransactional) {
interceptors = beanNames.collect { ref(it) }
}
}

This demonstrates how you can create a bean whose name isn’t resolved until runtime and how you can use conditions to affect the configuration. We also throw in a gratuitous collect() for good measure. The ability to mesh regular Groovy code with bean definitions opens up a whole world of opportunities.

A recent addition to the Spring DSL is support for namespaces. These were originally introduced as XML namespaces to simplify configuration, but you can now experience their benefits from Groovy.

Namespaces in the Spring Dsl

In order to show you how to use namespaces, we’ll use a simple example based on Spring’s aspect-oriented programming (AOP) support. We won’t go into detail about what AOP is, but suffice it to say that the following example will time every method call on the sessionFactory bean:

beans = {
xmlns aop: "http://www.springframework.org/schema/aop"

aop.config {
aspect id: "profiling", ref: "profileInterceptor" {
around method: "profile", pointcut: "bean(sessionFactory)"
}
}

profileInterceptor(com.manning.gria.ProfilingInterceptor)
}

First, you have to declare the namespace and assign it a prefix (aop, in this case), which you do with the built-in xmlns() method. You can declare additional namespaces by adding extra named arguments to the method, like so:

xmlns aop: "...", context: "...", ...

Once you’ve declared a namespace, you can use a property with the same name as the namespace prefix to access the custom features, as we do for aop.config in the preceding example. Note that the aspect() and around() methods aren’t prefixed because they’re nested within a method that is. You could also use this syntax:

aop {
config {
aspect ...
}
}

There isn’t any more to using Spring namespaces than that. Any documentation for specific namespaces will refer to the XML format, but now you know how to translate from XML to Spring DSL. You’re good to go! For even more information on the Spring DSL, we recommend the Grails user guide, which gives significant coverage of this topic and is well worth a look.

We’re almost done with our discussion of Spring, but one item from table 14.2 deserves some discussion. One of the bean attributes listed is scope, and this is directly supported by Grails services.

Bean Scopes

All Spring beans are by default singletons, which means that there’s only one instance of each bean of that type in an application. That makes any state stored in the bean, such as a simple field, effectively equivalent to a global variable—not a good idea in a multithreaded environment!

Stateless singletons are ideal, but if you want to store state in a bean, you can make your life easier by controlling the visibility of the shared data. Say your bean is inherently tied to the HTTP request processing. You would be pretty safe if the bean’s state were only shared within a single request, particularly as a request is typically a single thread. Each request would have its own copy of the data, so it could safely update the information without affecting any other requests.

This concept of visibility is known as the “scope,” and you can change it for a service by declaring a static field:

class MyRequestService {
static scope = "request"
...
}

The singleton and request scopes aren’t the only ones available to you either. Here is a quick rundown of all of them:

  • singletonOnly one instance of the bean exists for the entire application (the default).
  • prototypeA new instance is created each time a bean is retrieved from the application context.
  • requestThere is one instance per HTTP request.
  • sessionThere is one instance per HTTP session.
  • flowThere is one instance per flow or subflow—see chapter 9 for more info.
  • conversationThere is one instance per conversation—see chapter 9 for more info.

As you saw in table 14.2, you can also set the scope within your bean definitions.

Now that you know how to define extra beans for your application, the full power of Spring is open to you. If you discover a cool library that comes with dedicated Spring integration, you’ll know how to make use of it from Grails. We can only touch on the features of Spring here, so for serious development it’s well worth looking into documentation and books that are dedicated to the subject.

With the fundamentals under our belt, we can now boldly face one of those extra Spring features that Grails relies quite heavily upon but that can cause a little confusion: transactions.

14.2. Using transactions with GORM

In some fields, transactions are a big deal. Microsoft created Microsoft Transaction Server (MTS) and then COM+ to make developing transaction-based applications easier than they used to be. EJBs and their servers were also designed with transactions in mind. So what are they? Let’s start with a definition:


Definition

A transaction is a unit of work in which everything is done or none of it is. It isn’t possible for only part of a transaction to complete.


It’s all or nothing. As a practical example, consider a transaction that updates several database tables. If any of those updates fail, none of the changes are committed to the database. Only if all updates are successful does the transaction complete. Transactions are therefore a way of ensuring data integrity.

So why the fuss? The classic example is banking software. Imagine a bank customer wants to transfer funds from one account to another. At a superficial level, this consists of two steps: removing the funds from one account and depositing them in the other. What if the first step succeeds but the second one fails for some reason? Without transactional behavior, the customer would lose their money! That’s a big problem.

Without further ado, let’s look at how we can use transactions within a Grails application.

14.2.1. Easy transactions with services

In order to investigate the properties of transactions, we’ll have to add some transactional behavior to Hubbub. It’s not naturally a transaction-oriented application, but we have just the ticket.

Let’s say that users can reply to others’ posts by including the string @<user ID> in their own message. We’d like to keep track of these replies and whom they’re directed to, so let’s introduce a new domain class:

class Reply {
Post post
User inReplyTo
}

Next up, we want to make sure that every time a user posts a reply, a Reply instance is created. In addition, if Hubbub doesn’t recognize the user ID specified in the message, it shouldn’t commit that message to the database. Being a sensible person, you would check the user ID before saving the post, but we’re not going to do that. Instead, we’ll first save the message and then check the user ID, just so that we can effectively demonstrate how transactions work.


Note

In order to see the correct behavior, you should use a database that supports transactions, such as PostgreSQL, H2, or MySQL with the InnoDB engine. Nontransactional databases, such as MySQL with MyISAM tables, won’t work as expected.


Where shall we add the code for all this? It’s time to dust off our old friend PostService. The beefed up implementation, in which we create replies, is shown in listing 14.2.

Listing 14.2. The reply-aware post service

As you can see, the post service now saves the new post, looks for a reply-to user ID, and then checks that the user exists. If it does, a new Reply is saved; otherwise an exception is thrown. With the service now ready for prime time, what do we need to do to make it transactional? Nothing!

By default, all public methods in a service are transactional. If you were to post a message containing @dilbert (assuming dilbert isn’t a user in Hubbub), not only would you see an exception trace in the browser, but you should also discover that the post hasn’t been saved. Why not try it out and see for yourself? Try these two posts:


  • @glen hi there mate!

  • @dilbert do you really exist?

The first appears in your list of posts, but the second doesn’t—just as we’d hoped for. This raises an interesting question: how does Grails know that the transaction should be rolled back (not committed)? The method throws an exception, so Grails (or more accurately, Spring) infers that the transaction failed.


Under the hood

Transactional services are implemented using Spring’s AOP mechanism: each one is wrapped by a proxy created using Spring’s TransactionProxyFactoryBean. When you have a reference to a service, it’s in fact a reference to that proxy.

Transactions themselves are controlled by a transactionManager bean that is an instance of Spring’s HibernateTransactionManager by default. You can override this in one of the resources.* files if you need a special transaction manager or custom settings.


Before going any further, we should get rid of that stack trace. And while we’re at it, some way of seeing the saved replies would be useful. Modify the add action in the post controller so that it looks like this:

def add = {
def content = params.postContent
if (content) {
def post = null
try {
post = postService.createPost(session.user.id, content)
}
catch (e) {
}
if (post) {
flash.message = "Added new post"
}
else {
flash.message = "Failed to add new post"
}
}
redirect(action: "list")
}

The key change is that we catch the exception. We don’t need to do anything with it because we treat a thrown exception and a null return value in the same way. In a real system, the error reporting should be more informative, but this will suffice for the purposes of demonstration. You should also add a dynamically scaffolded controller for the Reply domain class:

class ReplyController {
def scaffold = true
}

That will allow us to check whether the replies are being saved or not. With that done, let’s move on.

A common problem that people have with transactions in Grails is related to the exception handling. To see what we mean, change this line

throw new PostException(message: "Reply-to user not found", ...)

in the post service to read as follows:

throw new Exception("Reply-to user not found")

All we’ve done is change the exception type, but when you try to post the @dilbert message now, the new post appears in the list! Why did that happen?


Testing transactions

Integration tests run inside a transaction by default, which is then rolled back after each test finishes. This ensures that data changes don’t affect other tests, but it means you can’t check whether transactions are rolled back or not. If you want to test transactional behavior, you need to add a static transactional property to your test:

static transactional = false

The alternative is to use functional tests for this job.


The default behavior for Spring mimics that of EJB containers: transactions are only rolled back automatically for runtime exceptions and errors. It expects you to handle checked exceptions yourself. Because Java forces you to deal with checked exceptions (or declare them on the method), that isn’t much of a problem. Groovy, on the other hand, lets you treat checked exceptions as if they were runtime exceptions, so it’s not immediately obvious why transactions aren’t rolling back. That can lead to lots of wasted time if you’re not aware of this issue.

What if you don’t want your service to have transactional behavior? Then set the static transactional property to false:

class PostService { 
static transactional = false
...
}

Make sure that you revert the previous change (the service method should throw a PostException), and then start the application and try to post the @dilbert message again. Notice any difference? The message appears in the list now! So even though dilbert isn’t a recognized user ID (and a runtime exception is thrown), the post is saved to the database. We no longer have transactional behavior.

Interestingly, if you remove the try... catch block from the post controller, you’ll find that the post is no longer saved. What’s going on there? To understand that, you have to learn how transactions and the underlying Hibernate session relate to each other.

14.2.2. Transactions, the session, and me

The way Hibernate works can be quite confusing for newcomers. When you add transactions on top of that, it’s time to reach for the aspirin. Part of the trouble is that the Hibernate session appears to exhibit some transactional behavior, as you just saw. If you step through your application code in a debugger, you’ll notice that calls to save() don’t appear to commit anything to the database. So is it transactional or not?

The Hibernate session is effectively a cache that sits in front of the database, which is why it’s also known as the first-level cache. When you save a domain instance, all you’re doing is updating this in-memory cache. The data isn’t committed to the database until the cache and database are synchronized, a process known as “flushing” in Hibernate. You can see all this in figure 14.3.

Figure 14.3. The Hibernate session is an in-memory cache that stores data changes locally and then persists them to the database when it’s flushed.

Remember that example from the end of the last subsection: when we stopped catching the runtime exception thrown by the service, the exception propagated out and stopped the active session from flushing. If you put the try... catch block back in place, the action returns normally, allowing Grails to flush the session and commit the new post to the database. As you can probably gather from this, Grails opens a session for you before your controller action is called and flushes it if and when the action returns normally.

You can even manually trigger a flush if you wish. The easy way to do that is to pass the flush: true named argument to either the save() or delete() domain methods.


Under the hood

Grails uses a custom version of a Spring web interceptor to ensure that a session is open before an action executes. The Spring class is OpenSessionInViewInterceptor, but Grails modifies it slightly to change the flush mode of the session to manual after an action returns but before the view is rendered. This allows views to access lazy-loaded collections and relationships, but it prevents them from making any changes that will automatically be committed to the database.


All changes made in the session up to that point will then be committed to the database. For a quick example, make sure that the post controller’s add action is not catching the exception, and then use the flush argument when saving the user in the post service:

...
post = new Post(content: content)
user.addToPosts(post)
user.save(flush: true)

Now if you try to post a message in reply to dilbert, that message will be saved to the database—just load the post list page to see the evidence.

The main thing to be aware of is that making changes to the database is a two-stage process: you first update your domain objects (or save new ones) and then flush the session. The next question is, how do transactions fit into this model?


When is a Hibernate session created?

It’s all very well knowing how the Hibernate session works, but that’s not much good if you don’t know when they’re created and how long they remain open. So here is a quick rundown of the most common scenarios:

  • A session is opened before a controller action is called and it’s flushed when the action returns. It isn’t closed until either the view is rendered or the response is committed (say via a redirect or error).
  • If a session isn’t already open, a transaction will open a new one and keep it open for the life of the transaction.
  • Queries and methods like get() will automatically create a session if one doesn’t exist. The session is closed as soon as the method returns.

Let’s make PostService transactional again, but leave the flush: true in there. What happens when you try to post a reply to dilbert now? You get the stack trace as before, but when you reload the post list, you won’t see that message. Even when you catch the exception in the controller, the post is still not persisted to the database. This is starting to look a little too much like black magic. Shouldn’t Grails have saved the post to the database because we have an explicit flush? No, and if you go back to the definition of a transaction, you’ll understand why.

Any changes made within a transaction must happen in their entirety or not at all. Even an explicit flush must not commit the changes made up to that point. Grails manages this feat by starting a database transaction at the beginning of an application transaction (for example, on entry to a transactional service method). When Grails flushes the session, the changes are added to the database transaction, but they’re not committed. Once the application transaction has finished, Grails flushes the session automatically and commits the database transaction, persisting the changes made up to that point. Without a transaction, the Hibernate session operates in autocommit mode, which is why changes are always persisted to the database immediately on a flush.


Warning

When a transaction flushes the session, it will commit all the changes associated with that session, including ones made before the start of the transaction. If you choose to use transactions, we recommend that you only ever change or save domain objects within them.


One question that might be bugging you is what happens when you have transactions within a transaction. Let’s say that our post service (in transaction mode) calls another transactional service method. Does the second method start its own transaction? Does it have any impact on the original transaction? The answer is that nested transactions join their parent, so there’s only ever one transaction in progress (the parent). The Hibernate session is only flushed when the parent transaction finishes, and if the parent transaction fails, all child transactions are rolled back too.

So far, you’ve only seen transactions in the context of services. But what if a service is overkill, or you need finer-grained control over when a transaction starts and finishes?

14.2.3. Fine-grained transactions

When might you want a bit more control over what goes into a transaction? One possibility is that you may want to update the database from a controller directly, because that particular change only happens in the one place. Or perhaps you want to execute multiple transactions within a single service method.

Let’s say we want to move the post creation code back into the controller, but we still want it to run in a transaction. This isn’t recommended practice, but we’ll do it for demonstration. All we have to do is use the withTransaction() static method that’s available on all domain classes. You can see the resulting code in listing 14.3. For the sake of brevity, we’ve removed some of the variable checks.

Listing 14.3. Using withTransaction() for fine-grained transactions

Although we still recommend that you use a transactional service instead, this neatly demonstrates how you can quickly add a transaction to a block of code. The key is the withTransaction() method , which accepts a closure as an argument. Everything inside that closure is run within a transaction. An additional benefit of this approach is that you’re given access to the Spring TransactionStatus instance, which allows you to manually roll back the transaction without throwing an exception .

One thing that might puzzle you is why we call withTransaction() on the Post domain class rather than User. In fact, it doesn’t matter which domain class is used—it has no effect on the transaction block at all. You could even use Tag, which isn’t even used within the transaction block. Not surprisingly, users are often a little confused by this. Think of the domain class as something that the method can attach to—a surrogate host, if you like.

So when should you use transaction blocks rather than transactional services? That’s difficult to say and depends on the situation. Transactional services are the recommended approach, plus they’re less verbose than transaction blocks and form nice reusable components. The transaction block is good for one-off transactions and in cases where you don’t already have an open session and can’t readily get hold of a service. The BootStrap class and integration tests are typical places where you might want to use transaction blocks over services.

Transactions are hugely important to many applications, and you’ve seen that Grails makes them easy to use. They can appear to exhibit odd behavior sometimes, particularly when combined with the Hibernate session, but now that you know what is going on under the hood, you’ll be able to tackle any problems that arise.

14.3. Summary and best practices

As you’ve seen, Spring is a fundamental part of Grails, and although you can happily develop simple applications without ever being aware of its existence, you need to take advantage of it as your application grows. Fortunately, this is easily done with services and the automatic Dependency Injection that Grails provides.

When you start using Java libraries and integrating your application with other Java systems, you’ll often find that services don’t help. For the integration to work well, you have to define your own beans using the resources.xml and resources.groovy files, so that they can be easily slotted into the various Grails artifacts. If you do a lot of this integration, we recommend you become more familiar with Spring itself, either through the online documentation or a book. The framework contains far more than the classes related to the core IoC container.

Grails transaction support is one example of other features Spring brings to the table, and you’ve seen how easy they are to use. If you write an application that performs updates to a database, you ought to make yourself familiar with transactions and the effects they have on reliably saving and modifying domain objects.

So what recommendations do we make for your projects?

  • Put your business logic into services. Not only does this conform to the principle of the Separation of Concerns, resulting in code that’s easier to understand, maintain, and test, but you can also easily reuse the functionality from web service gateways, remoting interfaces, and the like.
  • Make important singleton objects Spring beans. Lifecycle management and Dependency Injection mean that any singleton objects benefit hugely from becoming Spring beans. Use the resources.* files to define beans for classes under the src directory or in JAR files.
  • Prefer Spring DSL. Whether you’re a fan of XML or not, the advantages of defining Spring beans in code are massive, with support for conditions, loops, and environment-specific definitions.
  • Update the database within a transaction. Making changes to the database outside of a transaction means that you have to be aware of how the Hibernate session operates, and you can easily end up with inconsistent data. Transactions are so easy to set up, why not use them? Note that there’s an overhead associated with transactions, so if you need to perform a high volume of updates, you may need to come up with a different solution. This is pretty specialized, though, so it’s unlikely to affect you.

With your application structured along these guidelines, you’ll find that further development, testing, and maintenance become easier than you have a right to expect.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset