Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

@since Sunday, May 15, 2011

Using Compile-Time AspectJ Weaving as @Transactional Proxy Provider

@throws 0 exception(s)
With my continued effort to annihilate the use of CGLib library, I reached the point of dealing with Spring Framework's Transaction management. Like with other support libraries from Spring Framework, transaction support is enabled via AOP proxies.
These proxies are often created using CGLib and as such they require our beans to violate Item 13 (Minimize the accessibility of classes and members) from "Effective Java (2nd Edition) by Joshua Bloch". CGLib proxy creation requires a non-final class with default empty constructor which prevents us from declaring our fields as final (Item 15?).

I could try and use Java dynamic proxy (supported by Spring Framework) but sometimes even dynamic proxies have their limitations (we reached such limitation by declaring a type @Transanctional and @ManagedResource - both tried to create different proxy types). Simply by looking at Spring TX schema I noticed it supports AspectJ mode. After reading some posts on bytecode weaving, comparing Spring AOP with AspectJ and performance charts (you got to read this) - I decided to use AspectJ to replace any AOP usage we have in our context (other than transaction support, we use advices). Another decision I made was to use compile-time weaving instead of load-time. Spring Framework has a very easy configuration if we wish to enable load-time weaving but it requires us to modify our application server configuration.

pom.xml
First of all, to enable compile time weaving, we need to add an AspecJ compiler to our build cycle. Maven has an aspectj maven plugin that can be easily added to enable compile time weaving.



Spring Framework Application Context Configuration
Now comes the part where we tell Spring that we want transaction support using the aspectj mode.


Notice that I also included </tx:advice> which tells Spring what are the basic transaction attributes to apply for each transactional call (e.g. method calls starting with count shouldn't be allowed to modify the database state).

Bean


Note that now we can declare our bean as final and reduce the implementation visibility to package only. Not needing the default empty constructor we can also declare our fields as final. Let's review the affect made by adding the @Transanctional to our service: If we were to leave the declaration on the type we would have to wrap each and every method with a transaction support (even private methods and even when calling this from within our service). If our service implementation contains only public methods, it wouldn't make any difference, but I would still recommend annotating only the public methods and by that proxy the concrete flow with transaction support.

In conclusion, we started with a runtime retention annotation and transformed its behavior to function like it is compile time. The performance benefits are immediately shown and even other aspects enjoy the benefits of compile time weaving. I think anyone who uses Spring Framework transaction management should consider using the above solution. Now go ahead and apply it on your project!

@since Tuesday, February 1, 2011

Configure Spring's Hibernate SessionFactory with Connection Pooling

@throws 0 exception(s)
Ever seen the following exception and had no clue how to solve it?

0000-00-00 00:00:00,000 ERROR org.hibernate.transaction.JDBCTransaction - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was37277 seconds ago.The last packet sent successfully to the server was 37277 seconds  ago, which  is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the serv er configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

The simplest explanation is that Hibernate was trying to use a connection that was closed (timed out) by the database (MySQL in the example above). You google the exception and find endless solutions when most of them are telling you you need a connection pool. Sounds easy, right? Simply add some Hibernate properties to your session factory bean and the problem solved.... Not really.

When using Spring ORM to create our session factory, we usually use some LocalSessionFactoryBean implementation which configure Hiberante and initialize it properly. What it doesn't tell us is that Spring is actually overriding connection settings - specifically the connection provider. The following was taken from the actual session factory initialization code in LocalSessionsFactoryBean:

if(dataSource != null) {
  Class providerClass = LocalDataSourceConnectionProvider.class;
  if(isUseTransactionAwareDataSource()||dataSource instanceof TransactionAwareDataSourceProxy) {
    providerClass = TransactionAwareDataSourceConnectionProvider.class;
  } else if(config.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY) != null) {
    providerClass = LocalJtaDataSourceConnectionProvider.class;
  }
  // Set Spring-provided DataSource as Hibernate ConnectionProvider.
  config.setProperty(Environment.CONNECTION_PROVIDER, providerClass.getName());
}

So how do we configure our connection to use some connection pooling? Instead of configuring our session factory, we configure the data source to use a pooled data source. By using c3p0's ComboPooledDataSource we're able to wrap our current data source with a connection pool by configuring few simple properties. The following is an example how to declare our data source bean (values shouldn't be hard-coded, visible here for example purpose):

<bean id="dataSource" 
    class="com.mchange.v2.c3p0.ComboPooledDataSource" 
    p:driverClass="com.mysql.jdbc.Driver"
    p:jdbcUrl="jdbc:mysql://localhost:3306/db"
    p:user="myuser" p:password="secret" 
    p:minPoolSize="5" p:maxPoolSize="20" 
    p:maxIdleTime="7200"
    p:idleConnectionTestPeriod="300" 
    p:preferredTestQuery="select 1" />

Another property you might wish to add is p:testConnectionOnCheckIn="true" but you may have to pay a price - performance wise. This property tells our connection provider to re-validate the connection before performing any database operations. If you think your connections will be violently closed - use it.

That's it, we're done. Our data source is wrapped with a connection pool and Spring session factory is guaranty to have an available connection - a live one. I recommend having some performance tuning to figure out the optimal settings for your application.

@since Sunday, December 19, 2010

Adding additional information to unit test logs

@throws 0 exception(s)
Usually, when we write unit tests with debug enabled or data base tests with Hibernate show_sql property turned on, we end up with a huge output log were it's hard to see where each test case method started (or ended).

Comes to your rescue - TestExecutionListener with Spring TestContext Framework. By simply implementing the TestExecutionListener interface, you can add various functionalities to your test cases. These customized listeners can be easily put in action by annotating your test class with @TestExecutionListeners and providing your implementation to the framework

Here's a simple implementation for outputting additional information to your test logs with test name (class containing your test methods) and test case you're currently running: 

public class ExtraInfoListener extends AbstractTestExecutionListener {

    private static final Log logger = LogFactory.getLog(ExtraInfoListener.class);

    @Override
    public void beforeTestMethod(final TestContext testContext) throws Exception {
        final String testName = testContext.getTestInstance().getClass().getSimpleName();
        final String testCaseName = testContext.getTestMethod().getName();
        logger.info("******************************************************************");
        logger.info("  Running test case: " + testName + "#" + testCaseName);
        logger.info("******************************************************************");
        super.beforeTestMethod(testContext);
    }
}

@since Tuesday, June 15, 2010

@throws 0 exception(s)
Excellent presentation on working with 3 major J2EE frameworks in a layered application. This group has a lot of great presentations to follow. If you can pass the accent, you’ll get a great overview on GWT+Spring+Hibernate best practice.