Technical Blog

4 Posts tagged with the spring tag

Hello all,

 

In a recent project we began using the @Autowired spring annotation in our objects and services to help simplify and minimize the amount of configuration we were writing in our various xml files.

 

Introduced in Spring 2.5 annotation-based configurations are now a viable alternative to pure XML configuration.  While it is debatable if one approach is “better” than the other, in practice it seems that mixing both methods allows you to spend less time wiring everything up and just getting on with it.

 

There are a number of annotations available including support for JSR-250 and JSR-330 but for this article I will be focusing purely on the @Autowired annotation.  For more information please refer to the Spring documentation or any number of articles on the web.

 

What’s the point?

 

How many times have you had to explicitly wire your spring beans and services hunting for the proper bean names?  What about creating setter methods for your private objects?  What if there were an easier way to do it?

 

Spring 2.5 (and beyond) has introduced a new xml context schema that deals with ApplicationContext configuration related to plumbing – that is, not usually beans that are important to an end-user but rather beans that do a lot of the grunt work in Spring, such as BeanFactoryPostProcessors.  To enable the tags in the context namespace, simply add the context namespace to your schema definition:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- <bean/> definitions here -->

</beans>

 

 

Now let’s look at a class as an example to see how @Autowired can help you in your daily development.

 

package emptest;
public interface EmployeeService {
         String hire(String name);
         String fire(String name);
}
 
 
package emptest.impl;
@Service
public class EmployeeServiceImpl implements EmployeeService {
 
         private EmployeeDao employeeDao;
 
         public String hire(String name) {
                 String message = employeeDao.getMessage("Hire");
                 return name + ", " + message;
         }
 
         public String fire(String name) {
                 String message = employeeDao.getMessage("Fire");
                 return name + ", " + message;
         }
 
         public void setEmployeeDao(EmployeeDao employeeDao) {
                 this.employeeDao = employeeDao;
         }
}
 

 

In this simple example we have a service implementing an interface with a private DAO object.  In a typical spring configuration for this service typically you would define your bean as:

 

 

<bean id="employeeService" class="emptest.impl.EmployeeServiceImpl">
         <property name="employeeDao">
                 <ref bean=”employeeDao”/>
         </property>
</bean>

 

 

But Spring can automatically detect classes and register bean definitions with the ApplicationContext!  Let’s see how this works in practice.

 

Step 1.  Add <context:component-scan base-package=”emptest.impl”/> to your configuration file.  This tells spring to scan everything in the emptest.impl package for Spring stereotypes and annotations.

 

 

<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
     xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

     <context:component-scan base-package="emptest.impl"/>


</beans>

 

 

Step 2.  Add @Autowired annotation to any private objects that you would like Spring to wire up for you.

 

package emptest.impl;
@Service
public class EmployeeServiceImpl implements EmployeeService {
         @Autowired
         private EmployeeDao employeeDao;
 
         public String hire(String name) {
                 String message = employeeDao.getMessage("Hire");
                 return name + ", " + message;
         }
 
         public String fire(String name) {
                 String message = employeeDao.getMessage("Fire");
                 return name + ", " + message;
         }        
}
 
 

 

That’s it!  Notice that there is no need to explicitly define a setter method, nor do you need to explicitly define your bean within the Spring configuration.

 

Of course this is a very basic scenario, but for the most part will get you started using annotation based configuration.  There are lots of tutorials, guides and documentation available online for more advanced usages.

 

Cheers!

1 Comments Permalink

Short screencast illustrating how to enable and use the Step Filtering feature of Eclipse:

 

 

Here are the step filters that should be enabled to skip over Spring's dynamic proxy code:

  • $Proxy*
  • java.*
  • javax.*
  • org.apache.*
  • org.springframework.*
  • sun.*
  • java.lang.ClassLoader
1 Comments Permalink

If some of the recent performance-related posts by our much cherished Get Elastic blogger extraordinaire Linda are starting to worry you, fear not! With the newly released Elastic Path 6.2, the Product Development and Performance teams at Elastic Path have done a fantastic job ramping up the standard performance of the product. I'll let them brag about the numbers at a later date, but today's post is to dig into the guts of the caching introduced into the system, and how you can start tweaking some of the configuration settings to squeek out every millisecond for page responses.

 

Within Elastic Path, there are now two caches that are available to be tweaked:

  • Application-level: Sitting between the view layer and the data access layer
  • Persistence-level: A Level-2 cache, within the OpenJPA ORM framework

 

Application Level Cache

All products loaded within the Storefront application via the StoreProductService will be from an Ehcache-backed cache by default. Each application is responsible for loading products via a ProductRetrieveStrategy. You'll notice storefront has two new configurations to facilitate using Ehcache:

 

Cache.xml:
     <bean id="productCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
          <property name="timeToLive" value="600"/>
          <property name="timeToIdle" value="600"/>
     </bean>

     <bean id="cachingProductRetrieveStrategy" class="com.elasticpath.sfweb.service.impl.EhCacheProductRetrieveStrategyImpl">
          <property name="productService" ref="productService" />
          <property name="cache" ref="productCache" />
     </bean>

 

ServiceSF.xml:
    <alias name="cachedSettingsReader" alias="settingsReader"/>
    <alias name="cachingProductRetrieveStrategy" alias="productRetrieveStrategy"/>

 

You'll note that the storefront is now using aliases in the Spring configuration to override the same bean definitions in the default core service.xml. This allows the storefront to setup caching-specific classes. For tweaking purposes, the productCache bean definition should be updated to optimize the Ehcache settings. By default, Spring's EhCacheFactoryBean will initialize the cache to allow overflow to disk, use LRU eviction and limit the in-memory size to 10k objects. For catalogs with a larger product mix, these settings should be optimized and potentially moved to an distributed cache via Terracotta to keep the JVM heap size to a reasonable level.

 

You can choose to add new properties here to tweak these values, or add an ehcache.xml configuration file to the classpath and define a specific cache name as part of the productCache definition to use. A quick tip on monitoring the cache statistics for tweaking the settings during load test is to setup JMX monitoring for the storefront cache. This can be done via two steps:

 

Running the appserver with remote JMX enabled (no authentication for a non-production environment):

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=6969 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

 

Configuring the JMX beans for Ehcache in cache.xml. Note in this case we are explicitly setting up a cache manager, which we can also use to specify a custom Ehcache configuration file instead of the default ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">

    <bean id="productCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
        <property name="timeToLive" value="600"/>
        <property name="timeToIdle" value="600"/>
        <property name="cacheManager" ref="cacheManager" />
    </bean>

    <bean id="cachingProductRetrieveStrategy" class="com.elasticpath.sfweb.service.impl.EhCacheProductRetrieveStrategyImpl">
        <property name="productService" ref="productService" />
        <property name="cache" ref="productCache" />
    </bean>

    <bean id="cacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    </bean>

    <!-- Spring initialization of ehCache's mbeans -->
    <bean id="ehCacheMBeanRegistration"
        class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod"
            value="net.sf.ehcache.management.ManagementService.registerMBeans" />
        <property name="arguments">
            <list>
                <ref bean="cacheManager" />
                <ref bean="mbeanServer" />
                <value>true</value>
                <value>true</value>
                <value>true</value>
                <value>true</value>
            </list>
        </property>
    </bean>

    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
        <property name="locateExistingServerIfPossible" value="true" />
    </bean>

</beans>

 

Connecting up with jConsole lets us check the cache settings are properly configured, and to check the statistics, as per the below image. We should see updates to statistics as you browse the storefront and load more products:

screen-capture-1.png

 

 

Persistence Level Cache

As part of the Elastic Path 6.2 release, the included OpenJPA library has been upgraded to a 1.2.1 version, which overcomes some data cache issues in the previous 1.0.1 version. Please see the OpenJPA 1.2.1 documentation for all details on the native OpenJPA datacache. We'll go over some of the changes that enable the data cache using the native implementation.

 

Annotations:

All transactional persistent entities (anything submitted or updated regularly as an online transaction such as orders, payments and customers) have a new data cache annotation so that they are non-cacheable. By default, entities are enabled in the data cache unless this annotation is present and explicitly disabled the caching. All relatively static data, such as catalog entities should be part of the cache and thus will be missing this new annotation.

 

@DataCache(enabled = false)

 

Persistence.xml Configuration:

As part of the persistence unit configuration, three new properties are configured by default:

            <property name="openjpa.DataCache" value="true"/>
            <property name="openjpa.RemoteCommitProvider" value="sjvm"/>
            <property name="openjpa.DataCacheTimeout" value="1000"/>

 

These values are used for:

  • openjpa.DataCache - enabling the cache, and specifying the cache properties. We recommend tweaking this value to accomodate the cache size according to the size of the underlying data: (true(CacheSize=25000, SoftReferenceSize=0))
  • openjpa.RemoteCommitProvider - specifying the commit provider. For a clustered setup, evictions should be handled via configuring this setting to use JMS or TCP-based evictions.
  • openjpa.DataCacheTimeout - maximum time to live for entities in the cache

 

Also suggested is to tune the query cache, which is enabled with default values when the DataCache property is set to true:

<property name="openjpa.DataCache" value="true(CacheSize=25000, SoftReferenceSize=0)"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm"/>
<property name="openjpa.QueryCache" value="CacheSize=25000, SoftReferenceSize=0"/>

 

Tip: Catching Cache Hits and Misses

If caching is enabled and you're still seeing a large amount of database queries from the storefront server, you can enable data cache Log4j tracing and grep out the hits and misses logged to track down which entities and queries are mistakingly hitting the database. Most of the times, these can be tracked down to accidental evictions or entities within the inheritance hierachy being disabled from cache.

 

log4j.category.openjpa.DataCache=TRACE

 

This spits out some logs similar to below that's easily greppable to count and track which entities are creating problems:

DEBUG 2009-09-10 12:56:33,918 org.apache.renamed.openjpa.lib.log.CommonsLogFactory$LogAdapter.trace(CommonsLogFactory.java:76) - Cache hit while looking up key "com.elasticpath.domain.attribute.impl.ProductTypeProductAttributeImpl-1".
DEBUG 2009-09-10 12:56:33,926 org.apache.renamed.openjpa.lib.log.CommonsLogFactory$LogAdapter.trace(CommonsLogFactory.java:76) - Cache miss while looking up key "org.apache.renamed.openjpa.datacache.QueryKey@b7ee9cab[query:[SELECT ps.skuCodeInternal FROM ProductSkuImpl ps

 

OpenJPA Cache Plugins

The native data cache within OpenJPA is architected to be swappable via plugin configuration. This allows the ability to swap in alternative caching technologies like Ehcache or Oracle Coherence to support extensive scalability requirements, as both Ehcache/Terracotta and Oracle Coherence support distributed caching setups. We've tested Ehcache and Coherence plugins internally with favourable results.

 

An Ehcache plugin is provided by the Ehcache group, however this version must be repackaged to match the custom package names of the Elastic Path specific org.apache.renamed.openjpa jar. Once a repackaged instance of the Ehcache-OpenJPA jar is in the classpath, the configuration changes to:

<property name="openjpa.DataCacheManager" value="ehcache"/>

 

Similarily enough, OpenJPA commiter Pinaki has posted the initial workings of an Oracle Coherence plugin on his blog, along with some additional JPA caching insights. Elastic Path with OpenJPA and Oracle Coherence is probably worth an entire blog entry in itself (coming soon!), but the same configuration settings apply, along with the need to repackage the code to point at the Elastic Path OpenJPA jar:

 

<property name="openjpa.DataCacheManager" value="coherence"/>

 

So there it is, two new caching mechanisms to tweak and fine-tune as part of load tests that should favourably reflect storefront page load times, and hopefully conversion rates and green dollar signs. Feel free to ask away about some of our load testing and tuning war stories. We'd be happy to talk about our hands on experience with the recent caching work.

6 Comments Permalink

In Elastic Path 6.1, we updated some of our library dependencies to more recent versions. This article outlines the changes, how they impact the application in terms of performance and behaviour, and how they might impact any custom Elastic Path development work you might be doing.

 

  • JUnit has been upgraded from version 3.8.1 to 4.4. Version 4.4 of the JUnit testing framework provides more powerful unit testing features, leveraging Java annotations. The upgrade is fully backwards compatible with tests written against older versions of JUnit. For more information on JUnit 4, go to http://junit.org/.
  • jMock has been upgraded from version 1.1 to 2.5. jMock 2.5 provides better management and creation of mock objects, but is not fully compatible with version 1.1, so both versions still exist as dependencies in Elastic Path 6.1. For more information on jMock 2.5, go to http://www.jmock.org/.
  • For an example of a test class in that uses the features of JUnit 4 together with jMock 2, see com.elasticpath.service.impl.GiftCertificateThemeServiceImplTest in the com.elasticpath.core product.#
  • The Spring framework was upgraded from 2.0.4 to 2.5.5. This upgrade brings improved performance, ease of configuration, and new features. For more information on the changes, see the Spring framework site (http://static.springframework.org/spring/docs/2.5.x/reference/new-in-2.html).  This upgrade is backwards compatible with previous versions of the Spring framework and customizations should not be affected.
  • Url Rewrite Filter was upgraded from 2.5.2 to 3.1. The newer version includes support for wildcard matching, mod_rewrite style configuration, and others new features.  This upgrade is backwards compatible with previous versions and customizations should not be affected. The complete changelog can be found at the Url Rewrite Filter site:http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.1/introduction.html#changelog
0 Comments 0 References Permalink