Skip navigation

Release: 2.4 Previous Releases
Publish Date: October, 2007

Article Rating?


Spring Quick Start

Introduction

This document describes the process of getting started clustering the Spring framework with Terracotta.

Further Reading

• For a deeper discussion of Terracotta for Spring, see the Spring section of the Concept and Architecture Guide.

Installation

Unix/Linux
Download the Unix/Linux install kit for Terracotta and unzip and untar it. A typical location to use for a production deployment is the /usr/local directory. For testing purposes, your home directory is appropriate.

For information on the sample applications included with Terracotta DSO, view the samples.html file in the samples/spring directory.

Microsoft Windows
Download the Windows executable (.exe) install file for Terracotta and run it. The installer guides you through the process of installing the product.

If the same version of the product has been previously installed in the same directory, the installer will backup the existing installation and perform a new install. The installer will notify the user about the backup and display the location of the new backup directory.

The installation creates an uninstaller for removing the product. The uninstaller does not delete files modified or created after the installation. These files will need to be removed manually.

Configuring Terracotta for Spring

The heart of Terracotta for Spring is the XML configuration file. Terracotta for Spring does not have a Java API and does not require code changes or additions. Declaration of clustering behavior is externalized into the XML configuration file.

Configuration Options

Naming Web Application to Share

Typically, you use the name of the WAR file you want to share:

<!-- tc:config/application/spring --> 
<!-- list of applications --> 
<jee-application name="SampleWebApp"> 
  ... 
</jee-application>

If you are running a stand-alone application you can use the wildcard '*' as shown in the code sample below:

<jee-application name="*"> 
  ... 
</jee-application>

Sharing Application Contexts

Each new instance of an application context (invocation to new ClassPathXmlApplicationContext(..) or similar), is a unique "logical" application context throughout the cluster.

<!-- tc:config/application/spring/jee-application --> 
<application-contexts> 
  <application-context> 
     <paths> 
        <path>config/inventory-bean-config.xml</path> 
     </paths> 
  <application-context> 
<application-contexts>

An application context is identified by the set of bean definition files that are used to construct it. Each <path> element can be the full path from the root of the package (classpath root or web application root as defined for loading Spring context), or a pattern. The order of the <path> elements is unimportant but they must match the paths used to construct the application context exactly.

This same code shows an application context that is constructed from config/foo.xml and config/bar.xml:

ApplicationContext ac = new ClassPathXmlApplicationContext({ 
    "config/foo.xml", 
    "config/bar.xml" 
});

or in web.xml using Spring's ContextLoaderListener:

<web-app>
  ...
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      classpath:config/foo.xml
      classpath:config/bar.xml
    </param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  ...

Then in Terracotta config it should be as shown in the following code sample:

<!-- tc:config/application/spring/jee-application --> 
<application-contexts> 
  <application-context> 
     <paths> 
        <path>config/foo.xml</path> 
        <path>config/bar.xml</path> 
     </paths> 
  </application-context> 
</application-contexts>

Here are some code examples of valid patterns. In this example, if the bean definition file resides in the package com/biz/webapp, then these are all valid patterns:

<path>com/biz/webapp/my-bean-config.xml</path> 
<path>*/webapp/my-bean-config.xml</path> 
<path>*/my-bean-config.xml</path>

However, if you are using patterns then you have to ensure that there are no other bean definition files that can match the pattern.

Naming Spring Beans to Share

The names of the Spring beans you want to share (for a specific application context).

<!-- tc:config/application/spring/jee-application/application-contexts/application-context -->
<beans>
   <bean name="myBean"/>
   <bean name="txManager"/>
   <bean name="securityManager"/>
   ... 
</beans>

Naming Fields Not to Share

You can name the fields in a Spring bean that you do not want to share such as
which fields might hold on to resources on disk, for example.

<!-- tc:config/application/spring/jee-application/application-contexts/application-context -->
<beans> 
  <bean name="myBean">
    <non-distributed-field>dataSource</non-distributed-field>
  </bean> 
</beans>

Changes to non-distributed fields are not propagated to other JVMs. As an example, imagine that the bean myBean is defined as follows:

<bean name="myBean" class="com.biz.webapp.MyBeanImpl"> 
  <property name="dataSource" ref="dataSource"/> 
</bean>

If the dataSource field is defined to be non-distributed then each myBean bean will be initialized with a reference to that JVM's DataSource.

Defining Spring Events to be Distributed

You can define if you want the Spring events to be distributed for a specific application context. You define the event classes that you are interested in distributing.

For example:

<!-- tc:config/application/spring/jee-application/application-contexts/application-context -->
<distributed-events> 
  <distributed-event>org.comp.SomeEvent</distributed-event> 
  <distributed-event>*.SomeEvent</distributed-event> 
  <distributed-event>org.comp.Some*</distributed-event> 
  <distributed-event>org.comp.*</distributed-event> 
  <distributed-event>*</distributed-event> 
</distributed-events>

You can use wildcards ('*'). The wildcards can be used either at the beginning, at the end, both at the end or the beginning, or solely as a wildcard.

Including Classes for Instrumentation

Terracotta is instrumenting the bytecode of the classes for the target application transparently at class load time. During instrumentation Terracotta inserts the clustering hooks needed to cluster the application.

When using Terracotta for Spring, explicit instrumentation is something that, in most cases, will not be a concern since Terracotta for Spring figures most of this out on the fly. Terracotta for Spring inspects the Spring bean configuration file, grabs the types for the beans that are marked as shared. It then includes this bean type as well as all types that are reachable from this bean type, e.g. it better navigates the type hierarchy up to java.lang.Object for the target bean type as well as for all references that are reachable from this bean type.

The only references that Terracotta Spring cannot resolve are the Java Collection types such as java.util.ArrayList, java.util.HashMap, etc. In these cases you will have to explicitly define which classes Terracotta for Spring needs to instrument. This means all non-resolvable types that will potentially join the clustered object e.g., those reachable from the shared bean instance, have to be included for instrumentation in the XML configuration file.

<!-- Under c:config/application/spring/jee-application --> 
<instrumented-classes> 
  <include>
    <class-expression>com.biz.webapp..*</class-expression> 
  </include> 
</instrumented-classes>

You can define classes you want to include for instrumentation by using AOP-style pattern matching:

Pattern Matches
* Exactly one class or package
.. Eagerly zero or more packages

Turning on Session Clustering

Use the <session-support> element if you want to turn on HTTP session clustering or Spring Web Flow support.

<!-- Under c:config/application/spring/jee-application --> 
<!-- optional (default false) --> 
<session-support>true</session-support>

Defining Locks

Generally, locking is not something you have to configure. By default, Terracotta manages all locking for instrumented classes (bean types and types reachable from the bean, for example). However, what you have to ensure is that you have written a correct multi-threaded application. E.g. if you modify the state of an instance that is part of a shared object graph, then this object needs to be protected by a synchronized block, e.g. the code has to be thread-safe. Terracotta will then turn this synchronized block into a cluster-wide lock. The same holds for wait(), notifyAll() etc.

There is one exception from the rule above: if you specify a certain set of classes for instrumentation explicitly (using a fully qualified name or pattern), then you also have to define the locking necessary for these classes. Locks are defined using AOP-style pointcuts.

<!-- tc:config/application/spring/jee-application --> 
<locks> 
  <autolock> 
    <method-expression> 
      * com.biz.webapp.MyBeanImpl.updateBar(..) 
    </method-expression> 
    <lock-level>write</lock-level> 
  </autolock> 
  <named-lock> 
    <lock-name>lockTwo</lock-name> 
    <method-expression> 
      * com.biz.webapp.MyBeanImpl.getBar(..) 
    </method-expression> 
    <lock-level>read</lock-level> 
  </named-lock> 
</locks>

Configuration File Example

Imagine that the web application has the following Spring configuration.

<web> 
  <web-app> 
    <context-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value> 
        /WEB-INF/services-applicationContext.xml 
        /WEB-INF/dao-applicationContext.xml 
      </param-value> 
    </context-param> 
    ... 
 
  </web-app> 
</web>

Below is a complete example of how the corresponding Terracotta for Spring XML configuration file can look. The file is a bit verbose, but illustrates everything you can do.

In the beginning of the file are some mandatory general server and client settings, such as hostname and log directories. Following the server and client settings come the different applications and how they are defined as described in detail above.

<?xml version="1.0" encoding="UTF-8"?> 
<tc:tc-config xmlns:tc="http://www.terracotta.org/config"> 
  <!-- optional --> 
  <system> 
    <configuration-model>development</configuration-model> 
  </system> 
  <!-- optional --> 
  <clients> 
    <logs>%d/client-logs-%h</logs> 
  </clients> 
  
  <!-- optional --> 
  <servers> 
    <server name="localhost" /> 
  </servers> 
   <!-- list of Terracotta enabled applications --> 
  <application> 
    <spring> 
      <!-- list of web applications --> 
      <jee-application name="SampleWebApp">  
        <!-- optional (default false) --> 
        <instrumented-classes> 
          <include> 
            <class-expression>com.biz.webapp..*</class-expression> 
          </include> 
        </instrumented-classes> 
        <!-- optional (default false) --> 
        <session-support>true</session-support>  
        <!-- optional (default false) --> 
        <fast-proxy>true</fast-proxy> 
        <application-contexts> 
          <application-context> 
            <paths> 
              <path>/WEB-INF/services-applicationContext.xml</path> 
              <path>/WEB-INF/dao-applicationContext.xml</path> 
            </paths> 
            <distributed-events> 
              <distributed-event>com.biz.MyEvent1</distributed-event> 
              <distributed-event>com.biz.MyEvent2</distributed-event> 
            </distributed-events> 
            <beans> 
              <bean name="service1"/> 
              <bean name="service2"/> 
              <bean name="dao1"> 
                <non-distributed-field> 
                  connectionPool 
                </non-distributed-field> 
              </bean> 
              <bean name="dao2"/> 
            </beans> 
          </application-context> 
        </application-contexts>  
        <locks> 
          <autolock> 
            <method-expression> 
              * com.biz.webapp.MyFoo.updateBar(..) 
            </method-expression> 
            <lock-level>write</lock-level> 
          </autolock> 
        </locks> 
      </jee-application> 
    </spring> 
  </application> 
</tc:tc-config>

Enabling Terracotta for Spring in Applications

To enable Terracotta for Spring in your application you need to modify how you start up the application (or application server if you are using one). You can use either the Java wrapper script that ships with Terracotta for Spring, which is the simplest, or you can feed the regular invocation with some additional options.

Using the Java Wrapper Script

Terracotta for Spring ships with a startup script that should be used as a drop-in replacement to the regular java command. The name of the script is dso-java and can be found in the bin directory in the distribution.

To use the recommended Terracotta startup script:

  1. Find the (dso-java) script in the bin directory
  2. Replace the regular invocation to java with the invocation to dso-java.

Using Additional JVM Options

To use additional JVM options for applications inside the web container, perform the following:

  • Prepend the Terracotta boot Jar to the Java bootclasspath
  • Define the path to the Terracotta configuration file

Here is an example (assuming you are running Windows):

java -Xbootclasspath/p:<path to terracotta boot jar> \
   -Dtc.config=path/to/your/tc-config.xml \
   -Dtc.install-root=<path to terracotta install dir> \
   ... <your regular options> ...

Sample Applications

Terracotta for Spring sample applications are included in the samples/spring directory. These samples illustrate how to cluster with Terracotta and show by example ways you can cluster your own applications.

Web Flow

The Web Flow sample application shows how Spring Web Flow with continuation support can be clustered with Terracotta for Spring to enable failover of the conversation state.

A four-step conversation flow requires that you answer simple questions at each conversation stage. As you use the Back, Forward and Refresh browser buttons to navigate through the conversation, you can stop and start the individual web server nodes that make up the cluster. The application continues to work as expected, since Terracotta for Spring keeps your conversation available and intact, regardless of which server node actually handles your request (a load balancer round-robins each web request to a different server node).

For instructions on running the Web Flow sample application, consult the readme.html file in the samples/spring/webflow directory.

Thread Coordination

The Thread Coordination sample application shows how to use Terracotta for Spring to coordinate processes across a cluster of nodes using standard Java synchronization.

When each web server node in the sample starts, it creates a Spring bean that increments a counter every second. The counter is protected from multi-threaded access using Java synchronization, such that only one thread at a time may increment the counter. Terracotta for Spring clusters this Spring bean across all web server nodes, keeping the synchronization semantics the same across all threads in the cluster.

In this demonstration, the web server node that first enters the synchronized portion of the code is said to be "active," while the other web server nodes that are waiting to enter the synchronized block are said to be "passive." By viewing each web server you can see which is active and which is passive; as you bring down the active web server node you can see the passive node switch to active as the synchronization lock is made available.

For instructions on running the Thread Coordination sample application, consult the readme.html file in the samples/spring/coordination directory.

Events

The Events sample application shows how to use Terracotta for Spring to propagate ApplicationContext events across the cluster.

It is a simple Spring web application that takes as input a text message and publishes it as an event to its application context. Terracotta for Spring clusters the application context and the events published to it. As you refresh the list of published messages on each of the web server nodes, you can see that they all receive the events published by other nodes.

For instructions on running the Events sample application, consult the readme.html file in the samples/spring/events directory.

JMX

The JMX sample application shows how to use Terracotta for Spring to cluster Spring beans and AOP Advices and how to expose clustered data through JMX.

The application has a Spring bean that increments one of two counters, depending on which Increment button is pressed in the UI. One counter is configured to be transparently clustered with Terracotta for Spring, while the other is left alone and is "local" to each web server node.

Additionally, the Spring bean is advised using an AOP interceptor which keeps track of the increment history of each counter – this history is also configured to be clustered with Terracotta for Spring.

All of these components are published to JMX via the Spring framework. By using a JMX compliant tool (such as JConsole which ships with the 1.5 version JDKs) you can view and verify the local verses clustered data.

For instructions on running the JMX sample application, consult the readme.html file in the samples/spring/jmx directory.

Appendix

Contacting Terracotta


Contact Terracotta at the following:
Web site:  http://www.terracotta.org
Online forums:  http://forums.terracottatech.com/forums/
Information:  info@terracottatech.com

Platform Support

See Platform Support for information on which platforms are supported by Terracotta.
See Integrations to see the status of integrations with third-party technologies.


Copyright Information

Copyright © 2005-2007
Terracotta, Inc.
All Rights Reserved

This publication (the "Documentation") and the Terracotta software which it describes (the "Software") are protected to the maximum extent permitted under applicable law, including but not limited to, the regulations set forth in Title 17 of the United States Code, and California law. This Documentation, or any parts thereof, may not be reproduced in any form, by any method, for any purpose, without the express written consent of Terracotta. Terracotta makes no warranty, either express or implied, including but not limited to any implied warranties of merchantability or fitness for a particular purpose, with respect to the Software discussed in this Documentation, and the Documentation itself (collectively, "the Materials"). The Materials are made available solely on an "as-is" basis. In no event shall Terracotta be liable to anyone for special, collateral, incidental, indirect, punitive, exemplary, or consequential damages in connection with, or arising from the purchase or use of, the Materials. Under no circumstances and regardless of the cause of action alleged, shall Terracotta's liability exceed the purchase price of the Software described herein. Terracotta reserves the right to revise and improve its Software and Documentation as it deems fit. The Documentation describes the state of the Software at the time of publication.

Trademarks
"Terracotta," the stylized "T" logo, and "Open Terracotta" are trademarks of Terracotta. All other brand names, product names, or trademarks belong to their respective holders. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. All other brand names, product names, or trademarks belong to their respective holders.

Government Use
Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in FAR 12.212 (Commercial Computer Software-Restricted Rights) and DFAR 267.7202 (Rights in Technical Data and Computer Software), as applicable.

Adaptavist Theme Builder Powered by Atlassian Confluence