Greg Luck's Blog

I am sick of simple. Things should be great!

Browsing Posts in Java

Today I was upgrading Ehcache’s JGroups replication module to apply a patch. I needed to upgrade JGroups. Fine. I went into IntelliJ and updated my Maven repository indexes as they were a little stale, then clicked on the version number and used auto-complete to find the new versions. I found 2.7. That did not compile with the patch. I went back to the submitter. He then informed me that JBoss had changed their repo.
I had:
<repository>
    <id>jboss</id>
    <url>http://repository.jboss.com/maven2</url>
</repository>

After hunting around I had to change it to:

<repository>
<id>jboss.releases</id>
<name>JBoss Releases</name>
<url>https://repository.jboss.org/nexus/content/repositories/releases/</url>
</repository>

It would have been nice if the old name could have been mapped to the new location.

I thought I was done. But no, in the meantime JGroups decided to become more correct and go to a package name. Now, Ehcache did this about three years ago. So the old and new are as follows:

        <dependency>
            <groupId>jgroups</groupId>
            <artifactId>jgroups</artifactId>
            <version>2.6.8.GA</version>
        </dependency>
        <dependency>
            <groupId>org.jgroups</groupId>
            <artifactId>jgroups</artifactId>
            <version>2.10.0.GA</version>
        </dependency>
This whole thing was a hassle. Played out over the entire development community it turns into a lot of wasted productivity. To me each of these changes is no different to people changing interfaces in code. You have to change to rebuild. As it happens, later on I found out JGroups also did that with getLocalAddress, which is no longer castable to IPAddress. :(
This is a pet hate of mine. Why create work for your users? I always strenuously try to avoid these changes.
As to Maven I have been observing a trend where much of what you need is no longer in the central repository. It is now mainly a federated system. The central repo is therefore kind of dead.
This is now getting to be not much better than the old days of having to go hunting for software on a multitude of websites. But now it is even worse than that. You also have to then search on those web sites for their Maven repository, which is often buried somewhere, and then their maven coordinates for the artifact you want. I think this is turning into a software anti-distribution system. And then back to the beginning of this post – having done all that you can expect to do the same each time you want to upgrade, because of a lack of regard for backward compatibility.

A few weeks ago I blogged about the fantastic tc-maven plugin which works just as well as the Jetty plugin and makes life easy for Maven-based developers. My surveys from talks I do suggest that the mix of Maven and Ant based builds is 40-60% Maven. Three years ago it was about 10% Maven. Interestingly in Philadelphia the maven usage was 40% versus 60% in San Francisco. But many Ant people have tried Maven and had a less than stellar experience. My own experience was that Maven was as painful as EJB ever was. But it has been getting better over time.

The forthcoming release of Ehcache bundles the Terracotta server and I am very interested in making this as easy as possible for developers. The 2.1-beta kit has instructions for using the tc-maven plugin. The upcoming 2.1 final will also support Ant. Fortunately Ant and Maven interoperate and we will support Ant via the Maven Ant Tasks library.

Installation

Install Maven

Download and install Maven which is just expanding the download somewhere on your file system. Version 2.2.1 or higher is required.

Installing Maven Ant Tasks

There are a couple of choices documented at the Maven site. For simplicity, download the Maven Tasks for Ant 2.1.0 and copy the jar into your $ANT_HOME/lib directory.

Create a pom.xml

Maven requires a pom.xml which is placed in the same directory as build.xml. Use this sample which has all you need:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-terracotta</artifactId>
<version>2.1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.terracotta.maven.plugins</groupId>
<artifactId>tc-maven-plugin</artifactId>
<version>1.5.1</version>
<executions>
<execution>
<id>run-integration</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-integration</goal>
</goals>
</execution>
<execution>
<id>terminate-integration</id>
<phase>post-integration-test</phase>
<goals>
<goal>terminate-integration</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>terracotta-snapshots</id>
<url>http://www.terracotta.org/download/reflector/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

Additions to build.xml

Add these to build.xml:

    <macrodef name="maven">
        <attribute name="options" default=""/>
        <attribute name="goal"/>
        <attribute name="basedir"/>
        <attribute name="resultproperty" default="maven.result"/>
        <element name="args" implicit="true" optional="true"/>
        <sequential>
            <java classname="org.codehaus.classworlds.Launcher" fork="true"
                  dir="@{basedir}" resultproperty="@{resultproperty}">
                <jvmarg value="-Xmx512m"/>
                <classpath>
                    <fileset dir="${maven.home}/boot">
                        <include name="*.jar"/>
                    </fileset>
                    <fileset dir="${maven.home}/lib">
                        <include name="*.jar"/>
                    </fileset>
                </classpath>
                <sysproperty key="classworlds.conf" value="${maven.home}/bin/m2.conf"/>
                <sysproperty key="maven.home" value="${maven.home}"/>
                <arg line="--batch-mode @{options} @{goal}"/>
            </java>
        </sequential>
    </macrodef>

    <property name="maven.home" value="/Users/gluck/work/apache-maven-2.2.1"/>

    <target name="start_terracotta" description="Starts the Terracotta Server">
        <maven basedir="${basedir}"
               goal="tc:start"
               resultproperty="maven.build.result"
                />
    </target>

    <target name="stop_terracotta" description="Stops the Terracotta Server">
        <property name="maven.home" value="/Users/gluck/work/apache-maven-2.2.1"/>
        <maven basedir="${basedir}"
               goal="tc:stop"
               resultproperty="maven.build.result"
                />
    </target>

Ensure you change your maven.home property value to where you installed Maven.

Usage

Starting Terracotta Server

ant start_terracotta
Buildfile: /Users/gluck/work/ehcache/core/build.xml

start_terracotta:
     [java] [INFO] Scanning for projects...
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Building Unnamed - test:test:jar:1.0
     [java] [INFO]    task-segment: [tc:start]
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] [tc:start {execution: default-cli}]
     [java] 2010-05-01 12:34:26,737 INFO - Terracotta 3.2.1, as of 20100304-100300 (Revision 14673 by cruise@su10mo5 from 3.2)
     [java] 2010-05-01 12:34:27,018 INFO - Configuration loaded from the Java resource at '/com/tc/config/schema/setup/default-config.xml', relative to class com.tc.config.schema.setup.StandardXMLFileConfigurationCreator.
     [java] 2010-05-01 12:34:27,152 INFO - Log file: '/Users/gluck/terracotta/server-logs/terracotta-server.log'.
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Starting DSO Server
     [java] [INFO] [dso start] 2010-05-01 12:34:27,576 INFO - Terracotta 3.2.1, as of 20100304-100300 (Revision 14673 by cruise@su10mo5 from 3.2)
     [java] [INFO] OK
     [java] [INFO] [dso start] 2010-05-01 12:34:28,065 INFO - Configuration loaded from the Java resource at '/com/tc/config/schema/setup/default-config.xml', relative to class com.tc.config.schema.setup.StandardXMLFileConfigurationCreator.
     [java] [INFO] [dso start] 2010-05-01 12:34:28,255 INFO - Log file: '/Users/gluck/terracotta/server-logs/terracotta-server.log'.
     [java] [INFO] [dso start] 2010-05-01 12:34:30,759 INFO - Available Max Runtime Memory: 506MB
     [java] [INFO] [dso start] 2010-05-01 12:34:30.575::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
     [java] [INFO] [dso start] 2010-05-01 12:34:30.620::INFO:  jetty-6.1.8
     [java] [INFO] [dso start] 2010-05-01 12:34:30.663::INFO:  Started TerracottaConnector@0.0.0.0:0
     [java] [INFO] [dso start] 2010-05-01 12:34:33,097 INFO - JMX Server started. Available at URL[service:jmx:jmxmp://0.0.0.0:9520]
     [java] [INFO] DSO Server status: OK
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] BUILD SUCCESSFUL
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Total time: 14 seconds
     [java] [INFO] Finished at: Sat May 01 12:34:33 EST 2010
     [java] [INFO] Final Memory: 22M/133M
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] [dso start] 2010-05-01 12:34:33,840 INFO - Terracotta Server instance has started up as ACTIVE node on 0.0.0.0:9510 successfully, and is now ready for work.

BUILD SUCCESSFUL
Total time: 17 seconds

The Terracotta server will be running on its default port of 9510.

Stopping Terracotta Server

ant stop_terracotta
Buildfile: /Users/gluck/work/ehcache/core/build.xml

stop_terracotta:
     [java] [INFO] Scanning for projects...
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Building Unnamed - test:test:jar:1.0
     [java] [INFO]    task-segment: [tc:stop]
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] [tc:stop {execution: default-cli}]
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Stopping DSO Server
     [java] [INFO] [dso stop] No host or port provided. Stopping the Terracotta server instance at 'localhost', port 9520 by default.
     [java] [INFO] OK
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] BUILD SUCCESSFUL
     [java] [INFO] ------------------------------------------------------------------------
     [java] [INFO] Total time: 7 seconds
     [java] [INFO] Finished at: Sat May 01 12:48:37 EST 2010
     [java] [INFO] Final Memory: 21M/123M
     [java] [INFO] ------------------------------------------------------------------------

BUILD SUCCESSFUL
Total time: 10 seconds

More Information

The Terracotta plugin is documented on the Forge.

I am interested in people’s experiences using this. Ping me at gluck AT gregluck.com or post questions to the Ehcache Forum.

Having servers at development time is pain. You need tooling to make it smooth. Fortunately, Terracotta has the tc-maven plugin for this purpose.

Integration Testing with Maven

To start and stop the server pre and post integration tests, add the following to your pom.xml:

<pluginRepositories> <pluginRepository> <id>terracotta-snapshots</id> <url>http://www.terracotta.org/download/reflector/maven2</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories>   <plugin> <groupId>org.terracotta.maven.plugins</groupId> <artifactId>tc-maven-plugin</artifactId> <version>1.5.1</version> <executions> <execution> <id>run-integration</id> <phase>pre-integration-test</phase> <goals> <goal>run-integration</goal> </goals> </execution> <execution> <id>terminate-integration</id> <phase>post-integration-test</phase> <goals> <goal>terminate-integration</goal> </goals> </execution> </executions> </plugin>
 

Interactive Use

Interactively, with the pom configured, it is just mvn tc:start to start and mvn tc:stop to stop

Ehcache Server and Standalone Server have been released to Sourceforge Downloads. The server provides RESTful and SOAP APIs to Ehcache. It is available as a WAR which works with all app servers, or standalone using Glassfish V3 embedded.

New in this release is integration with Terracotta Server Array for coherent, scalable and HA caching. Also the Ehcache core has been upgraded to version 2.0, Jersey to 1.1.5, Metro to 2.1.5 and for standalone, Glassfish to V3 embedded.

This release has been performance tested against memcache and gives comparable over-the-network performance. Coupled with the simplicity of coding in your HTTP client of choice in your programming language of choice and easily getting the benefits of Terracotta Server Array backing it, this is a killer combination.

See the Ehcache Server documentation to get started or download it now.

Due to an issue with external repository handling, these have not yet been released to Maven. Sonatype are completing a project for Sun whereby they will be adding their artifacts to the Central repository. This is expected to be completed this week or next, so the Maven artifacts will be released then.

Interestingly, it can take a little bit of work to tune your Java HTTP client for speed. The following code snippet shows two recommended optimisations for the Apache HTTP client: turning off the staleness check (you would catch the exception on connection clone in production code and open a new one) and ignoring cookies.

HttpClient httpClient = new HttpClient();
httpClient.getParams().setParameter("http.connection.stalecheck", false);
for (int i = 0; i < cacheOperations; i++) {
    String url = new StringBuffer(cacheUrl).append('/').append(keyBase).append(i).toString();
    HttpMethod httpMethod = new GetMethod(url);
    httpMethod.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
    httpClient.executeMethod(httpMethod);
}
LOG.info(cacheOperations + " gets: " + stopWatch.getElapsedTime() + "ms");

I am working on Ehcache Monitor right now, which uses Ext JS. IntelliJ gives you the ability to debug both Java and JavaScript, which is really nice.

Local Debugging

To debug in IntelliJ you right click on a .html file and select Debug.

Remote Debugging

Set up a JavaScript Debug Remote configuration. See below for an example.

Make sure Firefox is closed and any previous debug session is closed.

Then Debug the Javascript Debug Remote config.

Getting it to Work

We had a bit of pain getting this working.

Mac OS X Version

10.6.2

IntelliJ Versions

I tested 9.0, 9.0.1 but couldn’t get it to work. It is known to work with Maia IU.92.273 which will become 9.0.2. It will install a FireFox plugin called JetBrains Firefox Extension. The version should be 0.2.5. 9 and 9.1 shipped with a 0.1 version of this plugin.

I am using Java 1.6_17.

Firefox Bug

Firefox gives an error mentiowith sqlite3 when using the HTML and JavaScript debugger.

This is caused by a bug in Firefox 3.5.7 and a few versions back. This problem has been reported on SnowLeopard.

Dyld Error Message:
Library not loaded: /usr/lib/libsqlite3.dylib
Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
Reason: Incompatible library version: Security requires version 9.0.0 or later, but libsqlite3.dylib provides version 1.0.0

Dyld Error Message:  Library not loaded: /usr/lib/libsqlite3.dylib  Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security  Reason: Incompatible library version: Security requires version 9.0.0 or later, but libsqlite3.dylib provides version 1.0.0

This is a known issue in Firefox. See https://bugzilla.mozilla.org/show_bug.cgi?id=513747

The workaround is to change the Browser config to use firefox-bin rather than firefox. See below.


The Ehcache project is happy to welcome Grails to the fold. The new Grails 1.2RC1 uses Ehcache as the default Hibernate second level cache. We worked with the Grails community to test Ehcache with Grails to ensure a good developer experience. As part of that we have added a new Grails Chapter to the Ehcache documentation on how to configure Ehcache for Grails, including production tuning.

We plan further enhancements to Ehcache to roll in the Terracotta Hibernate provider so that Grails users can experience the Terracotta Scale Continuum by simply making config changes in ehcache.xml.

Note that earlier versions of Grails also ship with the Ehcache library and it very quick and easy to configure it. See the documentation.

This is a final GA release of ehcache-1.7.1 comprising ehcache, ehcache-core and ehcache-terracotta modules.

This release contains 15 fixes and improvements over 1.7.0. See the changelog for complete details. Downloads and Maven modules are available here.

Very significantly, this release will enable new GA releases of the other ehcache modules, such as ehcache-web, which we expect to release over the next few weeks.

Note: If you experience different caching ergonomics you can enable the LinkedHashMap based engine with java -Dnet.sf.ehcache.use.classic.lru=true. This is the engine enabled up to 1.5.

I am over in the US through to Christmas and enjoying my second only Thanksgiving here. It has put me in a reflective mood. We have been hard at work on Ehcache over the last few months and I want to give everyone an update on some cool stuff coming out soon.

Ehcache-1.7.1

1.7.1 contains 15 bug fixes and improvements. That is quite a lot for an ehcache release, but reflects some serious time put in by the Terracotta Transparency Engineering Team, together with the impact of the large changes made in 1.7.0 when we integrated with Terracotta.

The biggest thing is that 1.7.1 is ready for some serious business. Start with local caching, and choose from Terracotta open source, RMI, JGroups or JMS for clustering and replication. RMI and JGroups work well up to around 20 nodes, and up to as much data as you can comfortably deal with in your local node, around 5GB in memory and more if you overflow to disk. If you need more than that, or your need coherence, or you need 99.99+ then plugin in Terracotta. This last one costs money, but it is worth it and cheaper and better than the competition. With that solution you can scale as far as you want. Literally. In the new year I plan on showing how to take this to a 1 Terabyte coherent cache with 99.999% availability and class-leading performance.  In the marchitecture, we call this the Scale Continuum, because that is what it is.

The other really big thing is that 1.7.1 completes the modularisation that was started over a year ago. The other ehcache modules will all have new releases, many of these the first non-beta releases as modules, in the next few weeks.

Google App Engine

Back in June I made some tweaks to support Ehcache in Google App Engine. At the time I suggested how this could be used with JCache and Google’s cache infrastructure. Because of GAEs restrictions, it did not include CacheLoaders. In 1.7.1 CacheLoaders have been changed to support GAE. And now, with a contribution from Cedric Lime, the ehcache-googleappengine module has been created. That one is fully integrated. It uses Ehcache as a high performance in-process L1 cache and GAE’s cache infrastructure as an L2. Why is this cool? Ehcache is 3 orders of magnitude faster. This means your apps will be faster, will do far less network calls to the cache infrastructure and will cost you a lot less in data and CPU charges. And you can build your apps as you are used to

Grails becomes a first-class citizen

I am a big fan of Grails, as are my Terracotta colleagues. Ari Zilka, Terracotta CTO,  ran into Graeme Rocher, the maintainer, a few weeks ago at SpringOne, and we thought it was high time  we offer Grails first class support. With that in mind I have been working with Graeme, testing Ehcache 1.5, which is already included in Grails-1.1.1, but is not active by default. It all works great. There will be a new Grails chapter (yes, this is the link, but I have not quite put it up) in the Ehcache documentation on Grails, showing step by step how to get up and running with Ehcache and Grails in about two minutes, with a couple of config line changes. Of course, with ehcache-1.7.1, this means that the Grails is a first-class citizen and can use our technology to scale up to massive apps.

Coming in early 2010: a new unified Hibernate Caching Provider

Ehcache of course started life as the “Easy Hibernate Cache”, thus ehcache and we remain committed to being the very best Hibernate caching provider. Now just prior to Ehcache joining Terracotta, Terracotta released a killer provider. As well as integrating with Terracotta clustering, it uses bytecode manipulation to remove syncrhonization required by caching providers (not Ehcache) and screams. Now that we have two providers, and Ehcache is already integrated with Terracotta via the ehcache-terracotta module, we plan to simplify everyone’s lives and unify the two by making a new ehcache provider which will work with ehcache but also with Terracotta.

OpenJPA becomes a first-class citizen

With JPA 2 about to make it out the door, a lot of folks have been playing with JPA by using Hibernate through it, or by using DataNucleus in GAE (at least I have). Earlier this year Craig Andrews contributed a patch for OpenJPA. That was released a few months back as the ehcache-openjpa module 0.1. In the best open source tradition the idea was to release it and get feedback. Now, we have that feedback, including from OpenJPA lead Kevin Sutter, and we have been readying 0.2. Once again, as with the OpenJPA ehcache provider can take you all the way along the scale continuum. We should have this released in the next week.

Ehcache DX Monitoring and Management

A few months ago I used the MySQL Enterprise Monitor. It turned out to be very useful to debug a gnarly problem we were having. It got me thinking that Ehcache could do with its own monitor for the same reason. Given that it would need to collect data from each CacheManager in your enterprise, and that most operations monitoring tools charge per monitor, an Ehcache Monitor would also provide a cheap and convenient consolidation point for integration with those tools. Now, at Terracotta, we think that caching should be a first-class component of your architecture, and therefore it needs first-class tools.

A few weeks ago we put out our first beta of this product and have been getting feedback. With the first cut working I have been thinking the past few weeks that I need to instil my knowledge of every caching issue I have ever had to investigate, and all the ones I have helped others with, into this tool. In other words, give it the secret sauce. In my opinion this will make the tool invaluable for production Ehcache environments.

Here is a peek at what is getting added into the next cut:

  1. Simplified SLA monitoring, using our HTTP interface
  2. Statistics switchable between instantaneous and cumulative
  3. A week or two’s history, for comparative analysis, and for finding the dreaded issues in your new application release
  4. Graphing of numerous Cache Efficiency statistics
  5. Graphing of Full GC and other GC events. Why? Because this is critical for apps with large heaps, which caching apps have
  6. Graphing of actual and projected memory use for each Cache. Wow! This one will be great.
  7. Clear a cache in all nodes across the whole enterprise with one click.  (This one would have been useful )

Ok, so those are features, but how will that work on the ground. Well, I have been thinking about that and here is just one use case.

A new system is put into production with Ehcache. After 3 months, the users notice that the system is getting slow. Operations sets up SLA-alerts on page response time which immediately fail. They then set up alerts on average get time of 100 ms on any cache in the app’s main cachemanager – which immediately fails. 2nd level support is contacted. The av get time graph for a series of caches are reviewed. com.company.process.domain.Country cache shows a get time of 300ms. The graph history which goes back 2 weeks shows that it jumped a week ago and a week and a half ago. The config on the config tab is checked and it is noted that the max elements in memory is set to 50. The statistics tab shows that there are 50 elements in memory and 2 on disk. The memory consumption tab shows that used cache memory equals max predicted memory for the cache. The 2nd level support checks with apps administrators and discover that the system has been rolled out to more countries and is now at 52, with more coming. Solution: up the maxElementsInMemory to > 52.

To get involved in helping us shape the Monitor, you can download the first cut here. If you do, ping us with your feedback and we will incorporate it in the next cut which we will be starting work on in the next week.

Anyway, as everyone can see, I have been up to a few things since I started working on Ehcache full-time a month ago. Look out for next year!

No comments

See a 3 minute video of Greg Luck previewing Ehcache DX, the new monitoring and management product, for Ehcache versions 1.2.3 and higher. Help to shape this exciting new product by registering and downloading theEhcache DX early release.