Second-level caching: Still an effective performance tuning technique

Date April 6, 2009

I keep reading discussions regarding the performance of Seam applications. These discussions are generally centered around the performance overhead of the interception techniques used by Seam. While this is definitely a valid issue in certain scenarios, see this excellent forum discussion started by Tobias Hill, many tend to blame Seam too quickly for their performance issues. If it is taking many seconds or even minutes to load a page, in most cases your application is more likely to blame than Seam.

In my experience, most performance issues stem from data access. Improperly tuned queries (a common culprit) and not using the second-level cache of your ORM provider when appropriate can lead to some serious performance implications in your application. While second-level caching is nothing new, here I will describe why it is important to a Seam application and how you can improve performance using Hibernate’s second-level cache provider.

Before I go any further, note that second-level caching is not the only caching solution you have available if you are using Seam. Seam provides a multi-layer caching solution that allows you to cache page fragments and objects easily while abstracting away the details. You can read all about Seam’s multi-layer caching solution in Chapter 34 of Seam Framework: Experience the Evolution of Java EE.

Loading Reference Data

Seam provides an elegant solution to the common problem of associating entities based on a dropdown selection. Take the common booking example with Seam. We are attempting to book a Hotel and we need to input credit card information. The type of credit card is likely to be a dropdown, but that dropdown is going to need to associate to a CreditCardType entity.

@Entity
public class CreditCardType implements Serializable
{
  @Id
  private Long providerId;
  private String description;
  // ... ...
}

Our Booking class then needs a reference to the CreditCardType class.

@Entity
public class Booking implements Serializable
{
  @Id
  private Long id;
  // ... ...
  @ManyToOne
  private CreditCard creditCard;
  // ... ...
}

To make this task simple, Seam provides the <s:entityConverter /> component which ensures that the user selection is converted to an entity for association with your object.

<h:selectOneMenu id="creditCard" value="#{booking.creditCard}"
    required="true">
  <s:selectItems noSelectionLabel="" var="type"
    value="#{creditCardTypes}"
    itemLabel=”#{type.description}” />
    <s:convertEntity />
  </s:selectItems>
</h:selectOneMenu>

As you can see this is quite simple, but we need to load the creditCardTypes into the conversation context in order to associate an instance to our entity. This is because the creditCardTypes need to be managed instances in the conversation-scoped persistence context. It is quite simple to accomplish this through a @Factory method scoped to the conversation.

@Name(“bookingAction”)
@Scope(CONVERSATION)
public class BookingAction implements Serializable {
  // ... ...
  @In private EntityManager entityManager;

  @Factory(“creditCardTypes”)
  public List<creditcard> loadCreditCardTypes()
  {
    return entityManager.createQuery("select c from " +
      "CreditCardType as c order by c.description").getResultList();
  }
  // ... ...
}

Great, so now we can load our entities into the context and associate them using a dropdown, so what’s the catch? The factory method only executes once, right?  The problem is that the query that loads the CreditCardType instances into the conversation context executes every time a new conversation requests the dropdown list.  This can cause the initial page load to lag.

This may not be a problem in this simple case as we only have this one dropdown, but what if we have many dropdowns on the screen? Even further, what if this dropdown list is used by several conversations? Doesn’t it seem wasteful to hit the database every time we need it? We can avoid the database hit and still achieve the same benefits by using second-level caching.

Second-level caching with Hibernate

Second-level caching is intended for data that is read-mostly. It allows you to store the entity and query data in-memory so that this data can be retrieved without the overhead of returning to the database. You can configure the cache expiration policy, which determines when the data will be refreshed in the cache (e.g. 1 hour, 2 hours, 1 day, etc.) according to the requirements for that entity. An entity like CreditCardType is certainly read-mostly so it is definitely a good candidate for the second-level cache.

Using Hibernate, it is quite simple to cache an entity by using the @Cache annotation.

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class CreditCardType implements Serializable {
  // ... ...
}

We then need to include the jars necessary for a second-level cache provider. I tend to use Ehcache as I find it simple to use and it is fully supported by Seam’s multi-layered caching solution.

Once you include the appropriate jars, you must configure Hibernate to use second-level caching. In your persistence.xml file, add the following properties for your persistence-unit definition.

<persistence-unit name="myBookingDS">
  ... ...
  <properties>
    <property name="hibernate.cache.provider_class"
      value="org.hibernate.cache.EhCacheProvider" />
    <property name="hibernate.cache.use_second_level_cache"
      value="true" />
    <property name="hibernate.cache.use_query_cache"
      value="true" />
    ... ...
  </properties>
<persistence-unit>

The hibernate.cache.provider_class should be specific to the cache provider you are using. Hibernate supports a number of implementations as described in the reference documentation.

Notice that we also set hibernate.cache.use_query_cache to true. This allows us to take the caching a step further by caching the query itself and not just the entities. In order to cache the query, we can take two approaches: use the Hibernate Session API or the Hibernate @NamedQuery annotation. Let’s look at the Hibernate Session API approach first. Our factory method above changes to the following:

@Name(“bookingAction”)
@Scope(CONVERSATION)
public class BookingAction implements Serializable {
  // ... ...
  @In private EntityManager entityManager;

  @Factory(“creditCardTypes”)
  public List<CreditCard> loadCreditCardTypes()
  {
    Session session = (Session) entityManager.getDelegate();

    Query query = session.createQuery("select c from " +
      "CreditCard as c order by c.description");
    query.setCacheable(true);

    return query.list();
  }
  // ... ...
}

Now you will notice in the logs that once the creditCardTypes have been loaded, even a new conversation does not cause a database call the next time these entities are requested. The query and the entities are loaded directly from the second-level cache in-memory.

The other approach is to use the Hibernate @NamedQuery annotation which gives the option to cache your query.

@Entity
@NamedQuery(name="getCreditCardTypes",
  query="select c from CreditCard as c " +
      "order by c.description",
  cacheable=true)
public class CreditCardType implements Serializable
{
  @Id
  private Long id;
  private String description;
  // ... ...
}

The @NamedQuery can then be retrieved through the createNamedQuery() method in the EntityManager API.

While we are only showing one scenario here, there are many cases where second-level caching can be applied in your application.

No silver bullet

By no means am I claiming here that second-level caching is the solution for every scenario. Performance tuning is somewhat of an art. It is definitely handy to know the various potential hot spots when tuning an application, but a solution that works in one case may not work in others. Simply read up on the various approaches and techniques to tune your application so that you can apply each technique when the time is right.

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Seam Framework promotion at JavaRanch

Date March 31, 2009

Michael Yuan and I will be answering questions about the book and Seam in general at JavaRanch this week in the JBoss forum.  If you would like to ask us a question feel free to stop by!  They will be selecting four random posters in the forum to win a free copy of the book provided by Prentice Hall. We look forward to a good week of questions and hope to see you there!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Seam UI Refcard Released

Date February 23, 2009

As a follow-up to the Core Seam Refcard, DZone has now released my companion reference for using Seam with JSF. The Seam UI Refcard has now been released through the DZone Refcardz site and includes:

  • Simplifying JSF
  • Page Navigation
  • JSF Component Annotations
  • JSF Component Tags
  • Hot Tips and more…

So download the Seam UI Refcard here and please send your comments and feedback to refcardz@dzone.com. For in-depth coverage of Seam 2.1, you can also purchase the just released Seam Framework: Experience the Evolution of Java EE.

In a related story, JavaLobby posted an interview with me to coincide the release of the reference card. Check it out!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Seam Framework: Available in Paperback

Date February 19, 2009

I just got my hands on a hard copy of my book, Seam Framework: Experience the Evolution of Java EE. For those who have been awaiting the paperback release, you can order your copy today from Amazon or Barnes and Noble. The book is the second edition of the best-selling JBoss Seam covering the latest and greatest features of Seam 2.1 and Web Beans (JSR-299). Check it out!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

5 Steps to Improve your Development Process

Date February 4, 2009

Improving your development process takes time and effort, but always pays off in code quality and professionalism. When consulting for an organization I always recommend the following 5 steps that I feel are essential to any development process. You may already be using these recommendations in practice as they are all well-known techniques and tools so I certainly applaud anyone who can check off each step. Note that each step requires learning, practice, and discipline, so if you are introducing something new, take it a step at a time. Process improvement doesn’t happen over night.

1. Write tests for your code, then write more tests

I won’t get into the religious battles generally surrounding Test Driven Development (TDD), but regardless of what you believe you should be writing tests for your code. Professional software developers write tests and run the test suite after making logic changes. As Robert C. Martin put it in Clean Code, “Code is never clean unless it has tests.” Enough said.

What it requires:

  • A unit testing tool such as JUnit or TestNG. I also recommend a code coverage analysis tool for measuring how well you’re doing with your testing such as Cobertura or Emma.
  • Learning to write testable code (e.g. small methods that generally have a single responsibility).

2. Don’t let your code changes become stale, commit regularly

Don’t hang onto your changes locally for an extended period of time. For continous integration to flush out issues early, you must integrate your code with other developers often. If you follow the technique of continuous commits, it will re-enforce itself on other members of your development team over time.

Merging is a pain to say the least. In a continuous commit environment, the longer you hold onto changes, the more likely you will have to merge. Other developers will soon realize that if they do not follow this approach, you are going to make their life miserable.

What it requires:

  • Breaking your work into smaller chunks that can be completed in reasonable time periods.
  • Developing the habit of committing as you finish a logical chunk of code.

3. Setup a Continuous Integration (CI) server

Continuous integration (CI) is nothing new, but I’m always surprised at how many environments I encounter that are still not using this vital development technique. Setting up a CI server is easier than ever thanks to some outstanding open-source projects.

What it requires:

  • A build that is autonomous, i.e. doesn’t rely on external input such as compiling the source files in Eclipse, to achieve the goal of building the project artifact(s).
  • A CI server implementation and a build machine to install the server on. Popular implementation choices include Hudson and CruiseControl (the original).

4. Automate scheduled releases to a production environment clone

Aka: Release Early, Release Often. The CI server can deploy releases to a production environment clone based on the current stable code in the VCS. If possible, this deployment should be fully automated and should generally occur at a specific time.

To avoid downtime for user testing it is not recommended that this occur on each commit. As the size of the team grows this can become quite a hindrance with continuous commits. Deploying a release somewhere between nightly and weekly at a time when usage is low is generally reasonable.

What it requires:

  • A way to deploy the application from the CI server to the production environment clone. With the hot deployment features of JBoss, I generally use SFTP and Hudson provides a great plugin for this.

5. Add a project artifact repository

This is probably the most controversial of the steps outlined here. The concept of an artifact repository is probably familiar to most people given the broadened use of Maven, but may still be unfamiliar to some. Maven repositories allow you to store project artifacts including POMs, jars, wars, ears, etc. in a structured format that incorporates naming conventions and versioning. This allows you to archive versions of your software products over time while automating dependency management as dependencies and versions change.

What it requires:

  • A server to install the artifact repository with the disk space necessary to store archives over time. Popular server choices include Artifactory and Nexus.
  • Integration of dependency management into your build. If you are using Ant, the Ant Tasks for Maven are useful or you can use Maven itself. Ivy is also a popular choice.

So what would you recommend? What processes and tools do you feel are essential to all development teams?

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Seam Framework: All Chapters Now Available

Date November 30, 2008

All early access chapters for Seam Framework: Experience the Evolution of Java EE have now been released through Safari Rough Cuts. The only book specifically covering Seam 2.1 now includes new chapters on Seam 2.1 security, an introduction to Web Beans (JSR-299), multi-layer caching, using Maven with Seam, and much more! You can download the source code or learn more here.

These chapters are still undergoing copy-editing so if you would like to pre-order the final print edition, you can order from amazon today. The final edition is scheduled for print release in February. Check it out!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Core Seam 2.1 Refcard Released

Date November 24, 2008

Have you been searching for a quick reference for setting up and configuring your Seam applications? Well search no more! The Core Seam Refcard has now been released through the DZone Refcardz site and includes:

  • Component annotations
  • Seam-gen commands and configuration
  • Conversation management
  • Common components.xml configuration
  • Seam security
  • The Seam application framework
  • Hot tips and more…

So download the Core Seam Refcard here and please send your comments and feedback to refcardz@dzone.com. For in-depth coverage of Seam 2.1, you can also purchase the upcoming Seam Framework: Experience the Evolution of Java EE. Enjoy!

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Seam and Web Beans: Not just evolutionary, revolutionary

Date September 29, 2008

Just a quick note to let you know that I will be speaking next week on October 8 at the Java MUG in Dallas. I will be talking about how Seam has simplified JEE web development and influenced the revolutionary Web Beans specification (JSR-299). Hope to see you there!

[Presentation Slides]

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

OSGi: What modularity can do for you (part 1)

Date August 27, 2008

It’s been a bit since I blogged last, but I wanted to discuss something I’ve been busy with lately. Inspired by a recent presentation by a friend of mine, Craig Walls, and the announcement by Ales Justin to support OSGi in JBoss 5, I decided to see what all the fuss is about. Perhaps you’ve heard all the hype lately surrounding OSGi, but I wanted to let readers know what they are in for should they decide to trek the OSGi path.

Part 1 will really just be an introduction to OSGi, so for those who have been watching OSGi for awhile now (the OSGi Alliance was founded in 1999!) feel free to jump in on the next entry. But, for those who are OSGi newbies, this will help to get the ball rolling.

So what is modularity all about?

Modularity is the basis of the OSGi world and each bundle is considered a distinct module. Essentially bundles are just standard jars which happen to register with the OSGi container on deployment.

  • They inform the OSGi container of what services they expose and what services they consume.
  • They run in the same VM and all invocations of the module are in-process calls (no remote invocations).
  • Modules are restricted in their interaction with one another as the OSGi container defines restricted class-loading policies (only allowing classes from a module to be exposed if they are explicitly exposed).

Bundles are not a fit for all cases and not all jars are required to be OSGi bundles. In fact using tools like the Apache Felix Maven OSGi Plugin we can choose to selectively embed dependencies directly into our bundles. But, in this case always consider the scope of the classes contained in those embedded dependencies as there are specific rules related to class-loading in the OSGi container.

When modularity counts

Modularity is important in cases where we want to limit what our clients can and cannot use. For example, looking at the Seam Booking Example, let’s say we add a payment service. We can define the payment service through an API, aptly named: PaymentService. There is likely a fairly extensive implementation behind the PaymentService necessary to validate forms of payment, authorize charges, etc, but the Booking application is really only concerned with authorizing payment (not the messy details).

public interface PaymentService {
  public boolean authorizePayment(Payment payment);
}

The details of the implementation should be hidden from the Booking application. Unfortunately, if the payment-service.jar is loaded into our classpath, we suddenly have access to not only the interface, but all the implementation classes as well. So there is nothing to stop developer A from directly instantiating and invoking PaymentServiceImpl. And when developer B changes the name of this class and its implementation months down the line suddenly we have a break.

OSGi solves this by only providing visibility to the services which are exposed by a bundle. This makes things simple in the following package structure:

payment-service
- src/main/java
    - com.solutionsfit.payment
         PaymentService
    - com.solutionsfit.payment.internal
         PaymentServiceImpl
         ... ...

Notice the package structure above. The PaymentService interface is separated from the implementation which is in general good practice, but externalizing one package or the other has never been enforced. So how can it be done with OSGi?

Remember that crazy MANIFEST.MF file that perhaps you looked at one time to see what was in there. Or maybe you just noticed it sitting there and never bothered to look at it (Maven generates it for us anyway right!?). OSGi introduces some specific entries into the MANIFEST file that defines exactly what packages are imported and exported. So for our example above our manifest may look something like:

Manifest-Version: 1.0
Bundle-SymbolicName: com.solutionsfit.payment-service
Bundle-Name: Payment Service
Bundle-Version: 1.0.0
Bundle-Description: Payment Service
Import-Package: org.apache.commons.lang
Export-Package: com.solutionsfit.payment
Build-Jdk: 1.5.0_15
Bundle-ManifestVersion: 2

These entries simply let the container know what they require from other modules to execute:

Import-Package: org.apache.commons.lang

And what they make available to other modules:

Export-Package: com.solutionsfit.payment

Notice that we haven’t specified anything earth-shattering here. All we’ve done is said that we require commons-lang to be provided to us and we are making the com.solutionsfit.payment package available to others. Note that I don’t state where the dependencies come from! This means that in the above case any registered bundle could export the package that I use. You can also specify a version to be more specific:

Import-Package: org.apache.commons.lang;version=”2.4.0″

This allows multiple bundles to export the same package but we only use the version we are interested in. This becomes very useful in addressing dependency version issues between jars. Here bundle A can depend on 2.3.1 while bundle B depends on 2.4.0 and the OSGi container enforces this restriction for us. In the example above by not specifying a version, the latest version registered by a bundle will be chosen.

Note in our diagram above that the PaymentService is the only class available to the org.jboss.seam.example.booking bundle. This is because we explicitly specified that its package should be exported meaning that the OSGi container makes it visible to other bundles.

This all looks very Maven-ish to me…

Your right! The naming conventions and versioning are very similar to Maven and they fit well together. In general, the BundleSymbolic-Name is determined by appending the group-id and artifact-id of your Maven POM. The version is just stripped directly from the POM, so it all fits. In fact, if you want to make your jar a bundle, simply create a /src/resources/META-INF/MANIFEST.MF file by swapping in your project details in the entry above and add the following lines to your POM:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifestFile>
              src/main/resources/META-INF/MANIFEST.MF
            </manifestFile>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

The next packaging of your project will be a OSGi bundle. Of course, the Apache Felix plugin mentioned previously provides a much more automated approach, but if you are into manual entry (sometimes the best way to learn), this approach will certainly work.

So besides visibility, what does this buy me?

Imagine the Booking application is running in production and your customers are happily booking trips to their favorite vacation destinations. You have realized that there is a critical bug in the production payment service that could result in substantial losses for your company. Do you bring down the application for temporary maintenance and perhaps lose those customers? No way!

With OSGi there is very loose coupling between the bundles. While OSGi will simply provide back a direct reference to the object registered by the bundle, this allows helpers like Spring-DM to proxy the PaymentService that will force the org.jboss.seam.example.booking to wait should the service go down.

If we simply replace the bundle with a bundle that includes the fix, the container will unregister the old bundle and register the new bundle. The proxy can then handle the reference shuffling and resume the service invocation.  This interaction will be almost instantaneous. Your customers will be completely oblivious to what has happened and you just saved your company a substantial amount of money (do I hear bonus?).

The diagram above obviously omits quite a bit of the magic of OSGi and hides some implementation details, but demonstrates the general idea.

Alright, alright, so all this stuff is very basic, where are the integration points! Don’t worry, in upcoming posts I’ll further discuss how the Booking application can use OSGi to simplify development.

Stay tuned…

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit

Managing Environment Specific Configuration with Seam

Date June 17, 2008

Swapping configuration between development and production (and often other environments) is usually a custom solution but often follows a general pattern. Personally, I usually leave this up to properties files. For instance, let’s say we have a specific URL for an adding service and let’s say the URL changes between the development and production environments. Obviously we would want to automate this.It is quite simple to define a component to invoke the service using Seam:

package com.solutionsfit.example.service;

@Scope(ScopeType.STATELESS)
public class AddingServiceFacade {
  private location;
  private port;

  public int add(int num1, int num2) {
    // invoke service at location and port
    // ... ...
  }

  // getters and setters
  // ... ...
}

Once defined, we can simply create a namespace for this component (as shown in this previous posting) and our configuration in components.xml becomes simple:

<components xmlns="http://jboss.com/products/seam/components"
    xmlns:service="http://solutionsfit.com/example/service"
  ... ...
  <service:adding-service-facade name="addingService"
    location="@addingServiceIpAddress@" port="@addingServicePort@" />
  ... ...

The wildcard attributes above are replaced by our components.properties definition:

addingServiceIpAddress=192.168.0.1
addingServicePort=9999

The properties are set into our component at create time and invocation is now as simple as injecting the component:

@Name("addingAction")
public class AddingAction {
  @In
  private AddingServiceFacade addingService;

  // ... ...

  public void addNumbers() {
    result = addingService.addNumbers(num1, num2);
  }
}

Since this definition changes between development and production we simply maintain properties files specific to each environment aptly named: components-dev.properties and components-prod.properties. A simple ant target (or Maven profile) resolves the appropriate properties file based on environment when creating the archive that is being deployed.

This becomes even more useful when creating integration tests. An additional properties file can be defined that specifically defines the integration testing properties for your automated tests (e.g. components-test.properties). The integration test target can then use this properties file for running automated tests, avoiding any additional setup in the tests, and allowing a full integration test to be run.

So my question, how are you managing your environment-specific configuration with Seam?

UPDATE: This approach will be supported in Seam 2.1 as a feature of seam-gen’d projects as part the profiling functionality. See JBSEAM-3157 to patch your existing seam-gen’d project.

Enjoyed this post? Share it!

  • description
  • del.icio.us
  • Digg
  • Google
  • Technorati
  • StumbleUpon
  • Furl
  • Reddit