2 weeks earlier than expected my second son is born: Scott. He and mums are doing very well!
PS: Is it just coincidence that he was born during SpringOne 2GX at the day official Grails support was announced for SpringSource Tool Suite/Eclipse?
Wednesday, October 21, 2009
Scott is born
Posted by Marcel Overdijk at 9:27 PM 7 comments
Labels: Scott
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;
}
}
Posted by Marcel Overdijk at 1:24 PM 2 comments
Labels: ConfigObject, Groovy, Spring
Determining runtime environment on Google App Engine
Google recommends to determine the runtime environment of a Google App Engine application using ServletContext.getServerInfo(). In development this will be "Google App Engine Development/x.x.x" and in production it will be "Google App Engine/x.x.x".
But in some places, like Service classes, you might not have a access to the ServletContext object. Easiest way to work around this is to create a ServletContextListener which determines the environment and then stores it in a System property. The System property can be accesses from any place. You can of course also write a (static) Environment.get() utility class which return the System property.
Below you can find an example implementation of such a ServletContextListener to determine the runtime environment. As you can read the javadocs you can also use other environments then development and production. To start the application in test mode, just add a VM argument when you start your application using "-Druntime.environment=test".
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* Simple listener to set the App Engine runtime environment via a system property.
*
* Example web.xnl definition:
*
* <listener>
* <listener-class>com.footdex.web.listener.RuntimeEnvironmentConfigurerListener</listener-class>
* </listener>
*
* The runtime environment can then be accessed from any place (without reference to
* ServletContext) via System.getProperty(RuntimeEnvironmentConfigurerListener.KEY).
*
* In case a system property is already set for the RuntimeEnvironmentConfigurerListener.KEY,
* the system property will not be overridden. This allows to startup the application
* in a custom environment other than development or production. This can be done typically
* using a VM argument like "-Druntime.environment=test".
*
* @author Marcel Overdijk
*/
public class RuntimeEnvironmentConfigurerListener implements ServletContextListener {
public static final String KEY = "runtime.environment";
public static final String DEVELOPMENT = "development";
public static final String PRODUCTION = "production";
@Override
public void contextInitialized(ServletContextEvent event) {
if (System.getProperty(KEY) == null) {
String serverInfo = event.getServletContext().getServerInfo();
// ServletContext.getServerInfo() will return "Google App Engine Development/x.x.x"
// when run locally, and "Google App Engine/x.x.x" otherwise.
if (serverInfo.contains("Development")) {
System.setProperty(KEY, DEVELOPMENT);
}
else {
System.setProperty(KEY, PRODUCTION);
}
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
}
}
Posted by Marcel Overdijk at 12:58 PM 1 comments
Labels: GAE, Google App Engine
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:
- I love Grails (and Groovy), and if I could make the decision I would use it on every project! But...
- 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.
- 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:
- RuntimeEnvironmentPropertiesConfigurer - A subclass of PropertyPlaceholderConfigurer which uses a specific config file based on a system property
- Configleon - Also an interesting mini framework for per environment configs
- GroovyPlaceholderConfigurer - A subclass of PropertyPlaceholderConfigurer which uses a Groovy ConfigSlurper
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.
Posted by Marcel Overdijk at 12:51 PM 7 comments
Labels: Google App Engine, Grails, Groovy, Spring
Thursday, August 20, 2009
Grails on Cloud Foundry: Step by Step
After being acquired themselves last week, SpringSource has now announced acquiring Cloud Foundry. Currently Cloud Foundry only supports Amazon AWS/EC2 but in the future also VMware vSphere will be supported (surprising isn't it?).
This evening I experimented with Cloud Foundry and have uploaded a simple Grails application to the SpringSource Cloud Foundry Enterprise Java Cloud. I like to share my experiences with this step by step guide.
- Sign up for Cloud Foundry at https://www.cloudfoundry.com/cfapp/reg.html?_flowId=register-flow.
- Sign up for Amazon AWS at http://www.amazon.com/gp/aws/registration/registration-form.html.
- Create an EC2 keypair using the AWS Management Console or ElasticFox FireFox plugin. For detailed info and screenshots check Chris Richardson's blog post about this subject.
- Enable SSH using the AWS Management Console or ElasticFox. See Security Groups section. Again, for more info check Chris Richardson's blog post about this subject.
- Also enable HTTP access on port 80. If you forget this you won't be able to access your application in the cloud. I searched more than a hour for this...
- Change DataSource.groovy:
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
driverClassName = "com.mysql.jdbc.Driver"
username = "book"
password = "book"
url = "jdbc:mysql://${System.getProperty("dbHostName", "localhost")}/book"
}
}
}
Change the username, password and database name (in url property). You will need to enter these credentials in Cloud Foundry later.
The "dbHostName" property is specific for Cloud Foundry as explained in Cloud Foundry Getting Started. - Download the MySQL Connector/J jar and add it to your project's lib folder.
- After changing DataSource.groovy and adding the MySQL jar build a Grails war file using
grails war
. - Login to Cloud Foundry at http://www.cloudfoundry.com/. Don't use IE7! Be warned.
- Navigate to the applications tab and upload you war file. Important things to enter are the application name, the war file to upload, context name and the database section. Leave the rest as is.
- After your application is uploaded it's time to deploy it. Click the application's deploy button. In the next screen just enter a deployment name and leave the rest as is. Now hit the Launch button.
- This will take some time, but it's worth it ;-)
- After lauching your application click to view the deployment details. There is a Go To Home Page link to access your application!
Note: If you are using Google Chrome you won't see the link... That's why my first deployment 'failed' (and a hour gone) as I didn't know how to access it. As IE7 doesn't work either I guess Cloud Foundry only supports FireFox currently (I don't mind about IE, but I would be happy with Chrome).
To be honest Cloud Foundry has some rough edges in terms of documentation and tooling support but at the end I'm very happy how simple it is to deploy a Grails application. No Apache, Tomcat or MySQL setup anymore. This is the future!
Now only pricing should be more affordable. $79,20 p/month (Amazon AWS) for a toy project/application is a little bit high.
Posted by Marcel Overdijk at 1:46 PM 17 comments
Labels: Amazon, Coud Foundry, EC2, Grails, SprigSource
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.
Posted by Marcel Overdijk at 11:28 PM 1 comments
Labels: Grails, Groovy, Oracle, Spring, SpringSource, VMware
Grails w/ Dojo enabled forms
Didn't touched my Blogger account for almost a month now and I think regular tweeting is not good for the number of entries on your blog... But twitter is limited to 140 characters and I needed a little bit more this time.
While playing with Spring Roo the other day I noticed Roo is using Dojo - and to be more specific Dijit Forms - to enhance plain htlm input fields with javascript. For example Number fields are decorated with a Dojo dijit.form.NumberTextBox; what this means is that the user can only enter digits and no text. The lack of this feature with plain html inputs is a problem that has always bothered me when developing 'business' web applications.
So I dived into the magic of Dojo and it's Dijit form controls last week, and it does not only validate values using javascript, but it also contains nice widgets.
During the weekend I decided to create a small Grails application to leverage all Dijit form controls using a tag library. The following Dijit enabled form controls are available in this tag library:
- actionSubmit
- checkBox
- currencyTextBox
- comboBox (note: do not confuse this one with a filteringSelect)
- dateTextBox
- editor
- filteringSelect
- form
- multiSelect
- numberTextBox
- numberSpinner
- passwordTextBox
- radioButton
- radioGroup
- simpleTextarea
- submitButton
- textarea
- textBox
- validationTextBox
Example screenshots:
The complete application code and a little bit more information can be found at: http://code.google.com/p/grails-snippets/wiki/DojoForm. I will use this repository to share more Grails snippets in the future.
Posted by Marcel Overdijk at 3:07 AM 6 comments