Introduction

Author’s note: this is an article that I co-authored
with a colleague, Robert van der Steen. It has also been
published in our company newsletter.

Many of the applications we write for our clients nowadays use the service paradigm: a dedicated and often reusable component within the application that is responsible for a particular task or process. Such components are often written and used in such a way that a component is instantiated once and reused often within the runtime of the application (such as a web service or a Spring managed bean).

Using components in this way is a very resource-friendly way of constructing an application; resource-intensive objects are created only once and reused instead of having to be recreated and reinitialized for each request. However, they do make it necessary to pay special attention to issues that arise in reuse and concurrent use — specifically state management. A common technique to avoid such state problems is to build stateless components.

Unfortunately, mistakes happen in software engineering. Sometimes team members introduce state to shared components without thinking about it. This article discusses using the Memento pattern as an easy way of transforming a stateful into a stateless service.

The problem

In order to illustrate the problem sketched above, let’s introduce an example. This example is an adaptation of a piece of code I stumbled upon in the codebase of a project:

                public class SpringManagedServiceClass {
                        private String oneField;
                        private String anotherField;

                        public boolean anOperation(final String input) {
                                oneField = someOperationOnInput(input);
                                anotherField = somethingElseInvolvingInput(input);
                                totalOperationSucceeded = operationOnTwoStrings(oneField, anotherField);
                                return totalOperationSucceeded;
                        }

                        public String getOneField() {
                                return oneField;
                        }

                        public String getAnotherField() {
                                return anotherField;
                        }
                }

The code above evolved from a class that was not managed by Spring and was instead instantiated each time the service was needed. In that form having state at the class level was no problem: each object was used once and then discarded. This meant it was also thread safe for a client of the service object to extract state using the getters. However, when moved over to Spring the class became a de facto singleton and therefore not thread safe. The person who converted the class to a Spring bean did not recognize this and so introduced a problem by allowing concurrent access to unguarded state.

A quick fix to this problem might be to move back from Spring to instantiation at use. Unfortunately, in this case the class had evolved to depend on a database connection managed by Spring, so moving away from Spring support would be a lot of work.

Introducing the Memento

The Memento pattern is a rather simple pattern that externalizes a classes (visible) state. The way it works is by following these steps:

  1. Take a class C which has fields (i.e. objects with state).
  2. Introduce a new class CMemento.
  3. Move all the fields from C to CMemento. Make them private.
  4. Introduce constructors, getters and setters into CMemento as needed.
  5. In C, in your service methods, initialize a new instance of CMemento.
  6. Refactor C to use the variables in CMemento instead of the variables C used to have itself.
  7. Refactor the relevant methods of C to return a CMemento instead of their existing return types.
  8. Refactor CMemento and C so that the previous return values of the methods of C are placed in the CMemento objects.
  9. Finally, refactor the relevant methods of C again to place their previous return values in their CMemento objects before returning these objects.

The CMemento classes take over the state of the class C in this pattern. C can instantiate a single CMemento instance or as many instances of CMemento as it likes and so create a set of states for itself. Each of these CMemento instances can be the “current” state of any object of type C at any time, so instances of C can roll back to a previous state easily or even swap states.

The Memento pattern is actually not meant to address the problem discussed in this article; it is meant to enable rolling back to a previous state. Fortunately for us the idea can be reused easily to solve our problem as well. Instead of being swappable however, we will refactor our service object to create a Memento object (an object to hold the externally visible state). The public service method will then return this Memento object and the service class will “abandon” its “state” after that, making the service completely stateless.

The solution applied to the example

First, let’s introduce our Memento class:

                public class ServiceMemento {
                        private String oneField;
                        private String anotherField;
                        private boolean serviceResult;

                        public ServiceMemento(final String oneField, final String anotherField, final boolean serviceResult) {
                                 this.oneField = oneField;
                                 this.anotherField = anotherField;
                                 this.serviceResult = serviceResult;
                        }

                        public String getOneField() {
                                 return oneField;
                        }

                        public String getAnotherField() {
                                 return anotherField;
                        }

                        public boolean getServiceResult() {
                                 return serviceResult;
                        }
                 }

Now we can refactor our original service class and replace its state with a Memento object:

                public class SpringManagedServiceClass {
                        public ServiceMemento anOperation(final String input) {
                                String oneField = someOperationOnInput(input);
                                String anotherField = somethingElseInvolvingInput(input);
                                boolean totalOperationSucceeded = operationOnTwoStrings(oneField, anotherField);
                                ServiceMemento result = new ServiceMemento(oneField, anotherField, totalOperationSucceeded);
                                return result;
                        }
                }

After this refactoring all the client code will of course have to be refactored as well. However, all the state access has been replaced by getter calls to the new Memento object, so that refactoring is not very difficult.

The most important thing is that using the Memento has allowed us transform our service class into a thread safe, stateless service class rather easily. The price for this was introducing a new class. This is not as clean a solution as we would have had if the service class had been designed to be thread safe from the very start. But it is an easy fix to implement so it allows us to avoid a lot of (potentially difficult) rework. Also, this Memento class will do nothing but hold the result of the work done by the service class. So at least instantiating and having multiple instances of this class will not be as expensive as having to create multiple instances of the service class.

Summary

This article discussed using the Memento pattern as a quick fix for a thread safety problem in service classes. It covered the problem of accidentally introducing concurrent access problems in singleton classes by introducing state into those classes and then showed how that state can be externalized into a Memento class to make the service class stateless once more.

Using the Memento pattern to solve thread safety issues
Tagged on:     

3 thoughts on “Using the Memento pattern to solve thread safety issues

  • Pingback:Links for the day - 25-01-2009 | Blogmines

  • January 4, 2009 at 3:26 am
    Permalink

    Hi Gerbrand,

    Long time no see! How are you doing? Is the new job going well?

    You are correct — the example given in the post is amenable to all of its fields being final (although it makes little difference since they are private and there are no setters). The main reason I didn’t make them final here is that the example is adapted from the code we really developed and that was slightly different, making final fields unusable.

    The “prototype” scope might be a solution depending on how your application was built. The main thing to remember is that prototype scope means that a bean is instantiated every time it is referenced FROM THE SPRING CONTEXT, not every time it is used from client code. That is, every time a bean is injected, a new object will be created for injection; but injected is injected so if some code USES an injected (prototype) bean twice, that client code will not magically be given a new bean object between Java method calls (unless the client code retrieves the bean from the context itself before each method call on that bean). Particularly relevant here is that a prototype bean injected into a singleton bean will not be replaced in the lifetime of the singleton bean. In a typical web or webservice app you would not have the entire bean tree rebuilt for each request (you would make the middle tier service beans singletons), so prototype scope will not help. Unless you make EVERY bean in the middle tier (or at least every bean involved with a certain request-response) prototype scoped, but then you have to consider carefully what the impact will be on the performance of the application. Or you can use method injection to inject a lookup of the prototype bean into the unmodified (singleton) service code you already had, but that probably isn’t the quick fix I was looking for in this article.

    Note that you can possibly fix the entire situation in the Spring context definition in a web application by using the request scope rather than the prototype scope (this has a bean recreated each time an HTTP request is received). Your Spring config will become a bit more fiddly though, since you’ll need an AOP scope proxy to make sure that the request-scoped bean is correctly re-injected (or looked up) in the existing service code. I have to note though that I’m not completely sure of how thread-safe this solution is. Plus, I have a hunch that if your code is amenable to this solution, you were probably already clever enough as a developer to avoid the problem I was trying to fix. 😉

  • January 3, 2009 at 5:28 pm
    Permalink

    Hi Ben,

    Avoiding objects with (changing) state is usually a lot more efficient then having objects with modifiable state, so I think your listed solution sounds good.

    I suggest adding final to all fields in ServiceMemento, do indicate the state of the object should not be changed.

    Would a quick alternative solution not be changing the scope of the bean in the spring configuration?
    By changing the scope to prototype (http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes-prototype) the object should be instantiated each time it’s referenced.

Comments are closed.