Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Tuesday, October 13, 2009

Even more useful: ConfigObjectFactoryBean for Spring



Last week I blogged about a ConfigSlurperPlaceholderConfigurer for Spring. I've now come up with something more useful: a ConfigObjectFactoryBean for Spring!

It just creates a Groovy ConfigObject from the specified arguments (config file locations, environment and default environment).

It's more useful because you can use it to populate Spring's standard PropertyPlaceholderConfigurer and even expose the config properties map as a servlet context attribute using the ServletContextAttributeExporter. To populate the PropertyPlaceholderConfigurer and ServletContextAttributeExporter classes with appropriate beans derived from the ConfigObject (resp, java.util.Properties and java.util.Map), the factory-bean and factory-method attributes of the bean definition are used.

Source code of ConfigObjectFactoryBean can be found below. It includes extensive javadoc with example how to configure it in combination with the PropertyPlaceholderConfigurer and ServletContextAttributeExporter.


import groovy.util.ConfigObject;
import groovy.util.ConfigSlurper;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;

/**
* {@link org.springframework.beans.factory.FactoryBean} that exposes a
* {@link groovy.util.ConfigObject} object loaded using a Groovy
* {@link groovy.util.ConfigSlurper}.
*
* Supports the concept of per environment configuration via "environment"
* and "defaultEnvironment" properties. The "environment" property will be
* typically set using a system property.
*
* Can be used in combination with a
* {@link org.springframework.beans.factory.config.PropertyPlaceholderConfigurer}
* as demonstrated in the example below.
*
* Example XML context definition:
*
* <bean id="configObject" class="com.footdex.beans.factory.config.ConfigObjectFactoryBean">
* <property name="targetClass" value="javax.persistence.Persistence" />
* <property name="targetClass" value="javax.persistence.Persistence" />
* <bean>
*
* <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
* <property name="properties">
* <bean factory-bean="configObject" factory-method="toProperties" />
* </property>
* </bean>
*
* <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
* <property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
* <property name="url"><value>${dataSource.url}</value></property>
* <property name="username"><value>${dataSource.username}</value></property>
* <property name="password"><value>${dataSource.password}</value></property>
* </bean>
*
* Example config.groovy:
*
* dataSource {
* driverClassName = "org.hsqldb.jdbcDriver"
* username = "sa"
* password = ""
* }
* environments {
* development {
* dataSource {
* url = "jdbc:hsqldb:mem:devDB"
* }
* }
* test {
* dataSource {
* url = "jdbc:hsqldb:mem:testDb"
* }
* }
* production {
* dataSource {
* url = "jdbc:hsqldb:file:prodDb;shutdown=true"
* password = "secret"
* }
* }
* }
*
* {@link groovy.util.ConfigObject} properties can be exposed as servlet
* context attribute easily:
*
* <bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
* <property name="attributes">
* <map>
* <entry key="configProperty">
* <bean factory-bean="configObject" factory-method="flatten" />
* </entry>
* </map>
* </property>
* </bean>
*
* And than can be accessed in jsp's like ${configProperty["sample.foo"]}.
*
* @author Marcel Overdijk
* @see #setEnvironment
* @see #setDefaultEnvironment
* @see #setLocations
* @see groovy.util.ConfigObject
* @see groovy.util.ConfigSlurper
*/
public class ConfigObjectFactoryBean implements FactoryBean, InitializingBean {

private String environment;
private String defaultEnvironment;
private Resource[] locations;
private ConfigObject config;

private String getEnvironment() {
if (this.environment == null || this.environment.trim().length() == 0) {
return this.defaultEnvironment;
}
else {
return this.environment;
}
}

public void setEnvironment(String environment) {
this.environment = environment;
}

public void setDefaultEnvironment(String defaultEnvironment) {
this.defaultEnvironment = defaultEnvironment;
}

public void setLocation(Resource location) {
this.locations = new Resource[] { location };
}

public void setLocations(Resource[] locations) {
this.locations = locations;
}

@PostConstruct
public void yeah() {
System.out.println("yeah!");
}

@Override
public void afterPropertiesSet() throws Exception {
config = new ConfigObject();
ConfigSlurper configSlurper = new ConfigSlurper(getEnvironment());
for (Resource location : locations) {
config.merge(configSlurper.parse(location.getURL()));
}
}

@Override
public Object getObject() throws Exception {
return this.config;
}

@Override
public Class getObjectType() {
return ConfigObject.class;
}

@Override
public boolean isSingleton() {
return true;
}
}

Wednesday, October 7, 2009

ConfigSlurperPlaceholderConfigurer for Spring



Lately I'm working on Spring 3.0 hobby project in my spare time. Frequent readers of my blog or followers me on Twitter might think: Why plain Spring and not just Grails? So let me explain that first:


  1. I love Grails (and Groovy), and if I could make the decision I would use it on every project! But...

  2. I want to host my hobby project cheap, and even Amazon EC2/AWS is to expensive currently. So I decided to host my application on Google App Engine. And to be honest, Grails support for GAE is just alpha/beta state in my opinion (I hope it will change one day). So Grails was not an option.

  3. I've been coding Groovy and Grails for a while now and also doing commercial projects. But I have the feeling my basic Java and Spring knowledge might become a little bit rusty. And to face the facts, there is a change that one of my next clients will not use Groovy/Grails, but just Java and one of the 1,000,000 Java frameworks outhere. So with my hobby project I will be up to date with the latest Java and Spring 3.0 expertise!



But let's get back to the title of this post: ConfigSlurperPlaceholderConfigurer for Spring. In my hobby project I needed the concept of per environment configuration. Yes, in Grails you have it out-of-the-box but in Spring not.

I searched the web and found some interesting thoughts:


What I like about Grails' concept of per environment configuration is that you can define global config properties and just override them in a specific environment if needed. So if 90% of my properties are the same for each environment I don't need to specify them for all environment but just once.

This concept was not supported by the RuntimeEnvironmentPropertiesConfigurer, and also not by the GroovyPlaceholderConfigurer. I know the GroovyPlaceholderConfigurer uses a Groovy ConfigSlurper and this does support per environment configuration (Grails uses it!). So I decided to create a proper ConfigSlurperPlaceholderConfigurer which also supports different environments using a system property. At the end this is how my Spring config now looks:

Example XML context definition:

<bean class="org.springframework.beans.factory.config.ConfigSlurperPlaceholderConfigurer">
<property name="environment" value="#{systemProperties['runtime.environment']}" />
<property name="defaultEnvironment" value="production" />
<property name="location" value="/WEB-INF/config.groovy" />
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
<property name="url"><value>${dataSource.url}</value></property>
<property name="username"><value>${dataSource.username}</value></property>
<property name="password"><value>${dataSource.password}</value></property>
</bean>


Example config.groovy:

dataSource {
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
environments {
development {
dataSource {
url = "jdbc:hsqldb:mem:devDB"
}
}
test {
dataSource {
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
password = "secret"
}
}
}


I created a new issue in Spring JIRA to add this to core. If you are interested you can vote for the issue. It also contains the source code if you want to use it in your own project.

Monday, August 10, 2009

Will Rod Johnson be the next Marc Fleury?



Yesterday VMware announced it is going to acquire SpringSource for around $420 million. They expect the deal to be closed in Q3 2009. This means not only acquiring the Spring framework, but also Groovy, Grails, SpringSource tc Server (Apache Tomcat), SpringSource dm Server, Roo, etc.

As a Java developer I'm making use of a lot of SpringSource products (Spring framework, Groovy, Grails) so I'm wondering what this will mean for us. The VMware blog stated that the Spring framework (and I assume the same counts for the other products) will stay open and that Rod Johnson will continue to lead SpringSource. Let's hope Rod will not go on a "Paternity Leave" like Marc Fleury did ;-)

I think a lot of attention will go to cloud computing. Both the VMware blog and SpringSource Team Blog speak a lot about it. To quote Rod Johnson: "Working together with VMware we plan on creating a single, integrated, build-run-manage solution for the data center, private clouds, and public clouds". Also Graeme Rocher (Head of Grails Development - SpringSource) tweeted that we can expect exciting developments around Grails + Cloud coming in the not too distant future.



The VMware SpringSource acquisition also means my latest prophecy that Oracle will buy SpringSource someday needs a slight change... I think Oracle will buy VMware someday.

Wednesday, July 22, 2009

Spring Roo vs Grails generated controllers



As I already tweeted earlier today I was trying out Spring Roo 1.0.0.RC1 as it was released today.

After playing a couple of hours with Roo I must say really like Roo using AspectJ inter-type declarations (ITDs). For example Roo will automaitcally generate id and version fields and getters and setters for your persistent fields in your domain class. Roo generates these at development time in separate AspectJ .aj files. As a developer you won't touch them as Roo will manage and update them automatically as you add fields etc. to domain classes. The great thing is the generated code will not interfere with your custom code and you don't have to be scared you custom or overwritten methods are overwritten by Roo again. During compilation all .aj files belonging to the Java class are compiled into just 1 .class file.

What I really liked is that when you are developing in SpringSource Tool Suite (based on Eclipse) code completion works also for methods contained in the AspectJ .aj files. So also debugging your code is a real breech as you can step through the methods generated by Roo easily.

Roo also contains scaffolding. However as a long term Grails user I got scared when I saw the controller code generated by Roo. See the example below:

Roo generated controller code:


@org.springframework.web.bind.annotation.RequestMapping(value = "/nation", method = org.springframework.web.bind.annotation.RequestMethod.GET)
public java.lang.String NationController.list(org.springframework.ui.ModelMap modelMap) {
modelMap.addAttribute("nations", com.footdex.domain.Nation.findAllNations());
return "nation/list";
}


Grails generated controller code:

def list = {
params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
[nationList: Nation.list(params), nationTotal: Nation.count()]
}


OK, the Roo generated code could look better if we remove all the package information before the classes:

@RequestMapping(value = "/nation", method = RequestMethod.GET)
public String list(ModelMap modelMap) {
modelMap.addAttribute("nations", Nation.findAllNations());
return "nation/list";
}


But then we should also just create the same functionality in the Grails controller (without paging):

def list = {
[nationList: Nation.list()]
}


So which one do you prefer?

I really think Spring Roo will have a great future. The use of ITDs for generated code and it's support in SpringSource Tool Suite will really aid adoption. Also in case Grails is not allowed within your company, Roo could really help you to get more productive.

As I expressed already in my example I really like Grails/Groovy effectiveness and readiness of code. Also the deep level of code by convention empowered by Grails is unbeatable.

With Grails and Roo, SpringSource has 2 remarkable frameworks in it's portfolio. Let them be as innovative as always and we as developers are the winners!

Thursday, May 28, 2009

Spring Roo coming alive



Spring Roo was announced just recently at JavaOne, and after the first alpha releases it's now time for M1.

If you are interested in this new "code generating" / productivity framework led by SpringSource you defintely have to read this introduction and example by project lead Ben Alex. Currently there is not much documentation available but this will change in the near future.

Similar to Grails, Roo wil have a plugin architecture using "add-ons". Looks like I've published the first community add-on - integrating SiteMesh - myself according to Ben's blog. Follow the steps below to try out the SiteMesh add-on:


  1. Follow the Roo installation instructions from Ben Alex's getting started blog post

  2. Download spring-roo-addon-sitemesh-1.0.0.M1.jar from http://jira.springframework.org/browse/ROO-41

  3. Copy spring-roo-addon-sitemesh-1.0.0.M1.jar to ROO_HOME\dist

  4. Start Roo and create a project as described in Ben's blog post

  5. After creating the project install SiteMesh to your project. Type 'ins' and press tab. Roo's shell will already display the availability of the install sitemesh command. Finish the command 'install sitemesh'

  6. That's it. The Maven pom file is updated so it contains the SiteMesh dependency. The SiteMesh filter and filter-mapping are added to web.xml. And default sitemesh.xml, decorators.xml and main.jsp files are created within your project.

  7. Open webapp\decorators\main.jsp to change your main layout and continue your project creating persistent classes, controllers, views etc.



It's really easy to create add-ons. If you are interested in creating your own add-ons have a look at the sources of the SiteMesh add-on or see the Roo core add-ons using Fisheye or SVN.

I think Spring Roo will have a bright future as it is led by SpringSource and primary uses best practices and boosts developer productivity. For companies/developers already using the Spring framework, Roo will be an easy and natural next step. This is a real strong point for Roo. Also integration with the SpringSource Tool Suite integration since day one will have huge benefits.

As a long time Grails adept I'm wondering how SpringSource will position both frameworks in the future. At least we have another choice for productivity again.

Wednesday, January 30, 2008

Code by convention with Flex and Spring

Some years ago XML configuration was considered as a great way to configure applications. Take for example Struts' struts-config.xml, in the beginning it was like heaven how you could define all your action mappings etc. But as applications grow it gets harder and harder to maintain this bunch of XML.

The point is applications and application frameworks evolve. In modern application frameworks code by convention is becoming an important feature which reduces repetition and increases uniformity and productivity.

Take for example Grails and Ruby on Rails which are build from the ground up with code by convention in mind. For example in Grails a *Controller.groovy class is a automatically a controller and a *Service.groovy class is automatically a service. You do not need any XML configuration.

Back in my holidays in December I tried Adobe's BlazeDS. From Adobe Labs: BlazeDS is the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Adobe Flex and Adobe AIR applications for more responsive rich Internet application (RIA) experiences.

What this means is that Flex clients can communicate with Java objects deployed on the server. BlazeDS contains a Java Adapter which forms the infrastructure to make this possible. With Jeff Vroom's Spring Integration you can even use Spring beans to communicate with.

The only drawback with the standard Java Adapter (and so also the Spring Integation) is that each Java object you want to call on the server, you need to configure in remoting-config.xml. Guess what? I don't like that! So what I did is I created a JDK5 annotation to autowire Spring beans directly into BlazeDS. It means when you use Spring and JDK5 you can annotate your service classes with a @RemotingDestination annotation, and they get automatically registered in BlazeDS. Some sort of code by convention I would say!

How it works:


  1. Download the @RemotingDestination annotation for Spring supporting files at http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1398018. It also includes Jeff Vroom's Spring Factory.

  2. Expand remotingdestination-annotation.zip

  3. Copy dist\remotingdestination-annotation.jar in the WEB-INF\lib directory of your web application. Instead you could also include the Java sources (located in src) in your project.

  4. Download the Spring framework at http://www.springframework.org/download

  5. Locate spring.jar in the dist directory and copy it in the WEB-INF\lib directory of your web application

  6. In your Flex services-config.xml configure the SpringAutowiringBootstrapService:

    <?xml version="1.0" encoding="UTF-8"?>
    <services-config>

    <services>
    <service-include file-path="remoting-config.xml" />
    <service-include file-path="proxy-config.xml" />
    <service-include file-path="messaging-config.xml" />

    <service id="spring-autowiring-bootstrap-service" class="flex.contrib.services.SpringAutowiringBootstrapService"/>

    <default-channels>
    <channel ref="my-amf"/>
    </default-channels>

    </services>

    ....
    The SpringAutowiringBootstrapService checks all @RemotingDestination annotated classes and registers them within BlazeDS at runtime. It also dynamically creates the Spring Factory.
    Note that the default channel is required when using runtime registration of remoting destinations.

  7. Finally annotate your service classes with the @RemotingDestination annotation:

    package flex.contrib.samples.mortgage;

    import org.springframework.beans.factory.annotation.Autowired;

    import flex.contrib.stereotypes.RemotingDestination;

    @RemotingDestination(destination="mortgageService")
    public class Mortgage {

    @Autowired
    RateFinder rateFinder;

    public void setRateFinder(RateFinder rateFinder) {
    this.rateFinder = rateFinder;
    }

    public double calculate(double amount) {
    int term = 360; // 30 years
    double rate = rateFinder.findRate();
    return (amount*(rate/12)) / (1 - 1 /Math.pow((1 + rate/12), term));
    }

    }

    By default the Spring bean name is used to register the remoting destination. The name can be overridden using the destination attribute of the annotation. The example class uses Spring annotation-based configuration using the @Autowired annotation. In this case the Spring application context would look like:

    <?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-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="flex.contrib.samples"/>
    </beans>


That's it! The Mortgage service will be automatically registered without any XML configuration. The @RemotingDestination annotation allows you to easily expose services within BlazeDS. Together with Spring's annotation-based configuration this provides a productive code by convention experience for writing Flex applications with Spring on the server-side.

For more info about the @RemotingDestination annotation, SpringAutowiringBootstrapService see the Javadocs in docs\api.