Saturday, April 30, 2011

Spring 3.1 Bean Definition Profiles - Use Case

As I am diving deeper into VMware's Cloud Foundry, I decided to make the DevNexus conference web-application fit for Cloud Foundry. However, instead of creating an explicit version of the application for Cloud Foundry, my goal is to have one War file that can be deployed without modifications to either CloudFoundry or a stand-alone servlet container.

Here one new Spring 3.1 feature comes in handy: Bean definition profiles. Bean definition profiles allow you to conditionally load Spring beans. There are some great resources already out there on how to use Bean definition profile, and thus I won't go into the details here:
How am I using Bean Definition Profiles for the DevNexus web-application? 

Personally, I like to develop web applications that can run in a wide variety of environments with as little configuration as necessary. For my use-case, I want to create a single war file that can be deployed to the cloud,  but which can also be deployed into your locally running Tomcat, Jetty, etc.

Furthermore, I believe that bean definition profiles can also be very useful for demo/integration testing purposes. For web applications, I like the concept of "application home directories". They contain configuration files (e.g. DB connectivity parameters), data files such as for Hibernate Search etc.) and the web application will reference the home directory either through a system property, environment variable or looks in a default directory in your user directory. But what if the home directory does not exist?

If the home directory does not exist, then the application runs in demo mode (or embedded mode), which means, the application use an embedded database for persistence and to also loads a set of seed+demo data at application startup-up.

Summarizing, I can think of the following Web application "modes" aka profiles:
  • Embedded mode (Integration testing and Demo mode)
  • Cloud Foundry mode (e.g. reference the MySql service, don't use file-system properties)
  • Stand-alone deployment mode (Uses home directory)
Thus, I can create a dedicated Bean definition profile in my Spring application context for each mode. Here is an example I have:

 <beans profile="default">
        <bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="searchSystemEnvironment" value="true" />
            <property name="locations">
                <list>
                    <value>file:${TING_HOME}/ting.properties</value>
                </list>
            </property>
        </bean>
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName" value="${database.jdbc.driverClassName}" />
            <property name="url" value="${database.jdbc.url}" />
            <property name="username" value="${database.jdbc.username}" />
            <property name="password" value="${database.jdbc.password}" />
            <property name="maxActive" value="100" />
            <property name="maxIdle" value="30" />
            <property name="maxWait" value="1000" />
            <property name="poolPreparedStatements" value="true" />
            <property name="defaultAutoCommit" value="true" />
        </bean>
        <bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
            <property name="persistenceUnitName" value="base" />
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.dialect">${database.hibernate.dialect}</prop>
                    <prop key="hibernate.query.substitutions">true '1', false '0'</prop>
                    <prop key="hibernate.generate_statistics">true</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="hibernate.cache.use_query_cache">true</prop>
                    <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
                    <prop key="hibernate.show_sql">${database.hibernate.show_sql}</prop>
                    <prop key="hibernate.format_sql">true</prop>
                </props>
            </property>
        </bean>
    </beans>
    <beans profile="cloud">
        <cloud:data-source id="devnexus-db"/>
        <bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="devnexus-db" />
            <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
            <property name="persistenceUnitName" value="base" />
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.query.substitutions">true '1', false '0'</prop>
                    <prop key="hibernate.generate_statistics">true</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="hibernate.cache.use_query_cache">true</prop>
                    <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">true</prop>
                    <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
                </props>
            </property>
        </bean>
    </beans>
    <beans profile="embedded">
        <jdbc:embedded-database type="H2" id="dataSource"/>
        <bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
            <property name="persistenceUnitName" value="base" />
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                    <prop key="hibernate.query.substitutions">true '1', false '0'</prop>
                    <prop key="hibernate.generate_statistics">true</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="hibernate.cache.use_query_cache">true</prop>
                    <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">false</prop>
                </props>
            </property>
        </bean>
    </beans>

What about integration testing? 

As of writing this blog posting the latest Spring 3.1 release is: 3.1.0.M1 and there is no explicit support for selecting profiles in your test declaratively. There is, though, the following new feature request Jira:

https://jira.springsource.org/browse/SPR-7960 - "TestContext framework should support declarative configuration of bean definition profiles"

This feature is scheduled for Spring 3.1 M2, but in the meantime, I use a static block which does the trick:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
        locations={
          "classpath:spring/applicationContext-core-data.xml",
          "classpath:spring/mainApplicationContext.xml"
                 })
public abstract class BaseDaoIntegrationTest {
 
static {
  System.setProperty("spring.profiles.active", "embedded");
 }
 
    protected @PersistenceContext(unitName="base") EntityManager entityManager;

}

Over the next few days I hope to deploy an updated DevNexus application to Cloud Foundry, so stay tuned for updates.

Labels: , ,

Thursday, April 14, 2011

First explorations into SpringSource's CloudFoundry

I received my credentials last night for SpringSource's CloudFoundry and I am now in the process of going through the examples. Next, I plan to make some of my applications (home-projects) work on the cloud. The general documentation so far seems to be a still a bit scattered. Therefore, below I summarize all the documentation and resources I have used so far to immerse myself into the services provided by the CloudFoundry. Hopefully it provides a good starting point for you as well.

Background information
There are quite a few examples posted on GitHub, that are a tremendous help in getting started:
Deploy Applications to the cloud from within Eclipse (STS)
Deploy Applications to the cloud using the command line tool vmc
Spring Roo Support
Groovy/Grails 
Further reading
Mark Fisher published a great general article covering both, the vmc command line tool and Eclipse:
Make also sure you hit the forums:
And when you really want to look under the hood, take a look at the source code for CloudFoundry at:
It seems like that when checking out CloudFoundry, it is also a great opportunity to familiarize yourself with Spring 3.1 (see this Spring blog post detailing some of the new features). While I think it is not strictly required it provides functionality that is quite useful for cloud deployment scenarios such as:
More details on that in my next blog post. Back to the cloud...

Labels: , ,

Monday, April 4, 2011

Spring Integration - Camellos Continued

We had a great DevNexus conference this year and we were extremely blessed, that the project leads of both, Apache Camel (Claus Ibsen) and Spring Integration (Mark Fisher), spoke at the conference. In my opinion both frameworks are probably the best integration frameworks on the JVM!

Back in late 2009 I had written a blog post, where I presented some results from my Apache Camel learning experience. Now in 2011 it is time to do the same for Spring Integration. I am in the process of creating a few examples for Spring Integration that I create while learning it. So my hope is to create a little series of blog posts covering Spring Integration and Enterprise Integration Patterns (EIP) in general.

Nevertheless, don't forget to check out the wonderful examples that are provided via the Spring Integration Git repo at: http://git.springsource.org/spring-integration/samples/. It contains a sophisticated list of examples and is the best place to get started.

Well, let's get started - The source code for my example is available via GitHub, and will be successively expanded with additional examples in the coming weeks:
For right now the implemented core Spring Integration functionality in Camellos si is the following:

 
  1. A user drops a file in a local directory (/camellos-si/data/inbox/), that is continuously polled by Spring Integration.
  2. The file is picked up by Spring Integration and converted to a byte array with the original file being deleted.
  3. The resulting byte array is sent to an in-memory channel.
  4. A custom transformer will pick up the data array and compress the data using a ZipOutputStream
  5. The resulting byte array is yet again being sent to another channel.
  6. Finally an Outbound Channel Adapter will grab the data from the channel and send it via Ftp to an embedded Ftp server (stored under: /camellos-si/data/ftp/).
In order to try it out - just download camellos-si-distribution-1.0.zip from the downloads section at https://github.com/ghillert/camellos-spring-integration. Unzip it and start the application by executing:

java -jar camellos-si.jar

That's it. Spring Integration should boot up and you can drop files you want to zip up into '/camellos-si/data/inbox/'.

* * *

Some interesting additional features covered by my example:


Maven Shade Plugin (http://maven.apache.org/plugins/maven-shade-plugin/)

The Maven Shade Plugin can be a nice simplifier in stand-alone deployment scenarios. Let's say you have a project with multiple jar dependencies, then you can use this plugin to merge all jar dependencies into one single jar. You can also configure the Maven Shade Plugin so that it generates the Main-Class property in META-INF/MANIFEST.MF and consequently, you can deliver a single jar (No class-path hell) and execute the application like my simple example:

java -jar camellos-si.jar

Maven Assembly Plugin (http://maven.apache.org/plugins/maven-assembly-plugin/)

The Maven Assembly plugin helps with creating distributable packages. For instance for my example I need not only the compiled jar file but I also need a few directories in the right place, e.g. Apache FtpServer requires the users.properties file to be an actual file (having it as a class path resource embedded in your jar won't work).

Basically, you can use the Maven Assembly Plugin to move things around and to mold your resulting distributable package (a Zip file in my case).

Embedded Ftp Server using Apache FtpServer (http://mina.apache.org/ftpserver/)

Something I always find intriguing with Spring is the simple embedability of additional services such as running ActiveMQ embedded in your Spring context by just adding a single line of Xml, or in this case embedding Apache FtpServer. I know it is a blurry line where you start building your own application server but mentally I still find it easier to do it in Spring than using an app server, particularly when you only want to do it for testing, showcasing etc. and move on to use external ActiveMQ, Ftp Server instances for production etc.

I hope this example has been enlightening for your own Spring Integration discoveries - stay tuned for more. 



Labels: , , , ,