Constructor Injection vs Setter Injection
My opinion is that we should initialize an object by passing all collaborators in the constructor. That’s the Java natural way to initialize an object correctly. Other mechanisms such as Spring annotations (@Required) are artificial ways to achieve the same goal.
Why?
- Constructor-injection automatically enforces the order and completeness of the instantiated.In other words, it prevents the object to work with ‘null’ collaborators.
- Enforces the order of initialization and prevents circular dependencies
Are you insane? My constructor has lots of arguments!
If you have many collaborators in the constructor, that means your class may have too many responsabilities. That’s not a good practice. Remember the Single Responsability Principle. More than three is too many! Your tests will get complicated because you’ll have lots of different combinations to setup each scenario.
That doesn’t mean that in some situations we need to use setters (Legacy code and no time for refactoring?). In this case, use the @Required annotation to ensure Spring initializes all dependencies.
Information about this:
Spring Blog:
Minsko Hevery, Agile Coach at Google:
http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/
Richard Paul about testing these objects:
http://www.rapaul.com/2011/07/10/constructor-injection-unit-tests/
Using Git and Subversion
After reading Richard Paul’s about using git on a subversion repository, I always wanted to give it a try. I don’t regret so far. Git handles branches and merging very well and I haven’t seen any weird thing such “obstruction” or “tree conflicts”.
This is my recipe to use git on a subversion repository from bash, also inspired on this very good article “Effectively using Git with Subversion” and completed by reading a lot.
How to use git on subversion
1.- Clone Subversion repository on your local computer using git
Git is a distributed version control system. Distributed means that every machine has a copy of the repository. In order to use Git on a Subversion repository you need to clone the svn repository on your machine: trunk, branches and tags.
git-svn clone -s http://example.com/my_subversion_repo local_dir
Notice that you should point to the root of the subversion repository, not to trunk. This was one of my problems in the begining.
The option -s means “I have the standard svn layout”, trunk, branches and tags.
You might want to add your svn ignore files:
git-svn show-ignore > .gitignore
2.- Create a story branch and use it
Once you have your git repository cloned from subversion you can start working. I normally create a “story branch” like this:
git checkout -b story_branch
You can see git branches using this command:
git branch
Or all git and subversion branches:
git branch -a
If you only want to work on a svn branch, just checkout the remote branch like this:
git checkout remote/svnbranch
This does not mean you are working on the remote repo, you are still working on your local copy. Once you finish your work, you have to send your changes to subversion. Keep reading.
3.- Staging and committing changes
Before committing your changes you need to “stage” them. Git has an intermediate area called “stage” and only commits files stored in the stage. Think about it as a mail outbox.
Before staging files you might need to know which ones have been changed. This command will tell you which files have been changed or created but untracked:
git status
In order to “stage” the files you want to commit, run this command:
git add path/to/file
If you just want to stage all modified files just run:
git add .
Run git status again to verify that all the files you want to commit are in the stage area and then commit:
git commit
This will start your editor (vi for example) so you can enter a commit message. Remember that a good commit message should have:
- A title summarizing what’s been done, ideally containing the issue number from your project tracking application (Jira for example)
- A blank line
- A thorough description if necessary
If you want to skip the editor just run:
git commit -m "message"
4.- Get other developer changes into your branch (update)
Many times, other developers commit changes before you finish your task. If you want to incorporate other developers changes, first commit your changes, then rebase:
git svn rebase
This command is awesome! It just merges down changes from the original branch into your local branch. In other words, if someone modifies the remote ‘subversion trunk’ and your ‘git story branch’ was forked from your ‘git master branch’ (which is a copy of trunk), git will fetch those changes from svn trunk and will merge them into your ‘git story branch’. The documentation explains this command very well.
Updating without having to commit
Sometimes it isn’t reasonable since your changes are not yet ready to be committed (you haven’t finished/tested/improved your work). But don’t worry, git has a native solution also for this problem, just follow these steps:
- put aside your changes using the command: git-stash
- update your working copy using: git-svn rebase as usual
- take back your changes typing: git-stash apply
- clear “the stash” typing: git-stash clear
5.- Reverting uncommitted changes
In git this is called “reset”.
git reset --hard HEAD
I don’t understand completely how this command works yet but as far as I understand it moves the index of changes to the previous state.
6.- Reverting committed changes
git revert HEAD
This will create a new commit which undoes the change in HEAD
7.- Merging branch
Once you finish your task on your local ‘story branch’, you’ll probably want to merge it up into ‘master’. Change to the branch master first:
git checkout master
Rebase possible changes made on subversion trunk:
git svn rebase
Merge:
git merge story_branch
This will try to run a “fast forward” merge by default, in other words, it will incorporate each commit on the ‘story branch’ and master will look as if no branch had existed before. I don’t like this because if you want to check the history you don’t have a way of knowing in which the branch was merged down into master.
My preferred option is “no fast forward”:
git merge --no-ff -m "commit message"
This does exactly the same as fast forward but it also generates an empty commit message so you can see in which commit the branch was merged. Besides, when you send your changes to svn you will see only one commit which looks very clean.
8.- Solving conflicts
This is just a question of editing the conflict, add it to the stage area and commit.
I usually edit changes with a normal editor or with the plugin JGit/EGit for Eclipse. There is a built-in tool on git called “git-mergetool” but I’ve never used it.
9.- Send your changes to subversion
git svn dcommit
10.- Amending commit messages
I had problems sending my changes to svn the first time because we are using pre-commit hooks and I forgot to include my issue number in the commit message. In order to modify commit messages, first I need to know the commit hash id:
git log
And then I run the following command:
git rebase --interactive $parent_of_flawed_commit
Be aware you have to use the commit parent hash id.
An editor will come up, with a list of all commits since the one you gave.
- Change pick to reword (or on old versions of Git, to edit) in front of any commits you want to fix.
- Once you save, git will replay the listed commits.
Git will drop back you into your editor for every commit you said you want to reword, and into the shell for every commit you wanted to edit. If you’re in the shell:
- Change the commit in any way you like.
- git commit –amend
- git rebase –continue
11.- Get new branches from subversion
If you need to update your cloned version of subversion repository, just run:
git svn fetch
Final step: convince all your colleagues to use git and move to it!
Turning off HtmlUnit driver logging messages
HtmlUnit was throwing lots of log messages while using cuke4duke (cucumber) to test our website from maven and I wanted to turn them off temporary but I struggled a bit. This is the solution I found on Stack Overflow:
I created the commons-logging.properties file under /src/main/resources and I specify that my logging framework is log4j (commons is just a wrapper):
# JDK Logging #org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger # Log4j logging (also required log4j.jar to be in classpath) org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
I created the log4j.xml file in the same folder /src/main/resources:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="out" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd, HH:mm:ss} %p - %m%n" />
</layout>
</appender>
<root>
<priority value="error" />
<appender-ref ref="out" />
</root>
</log4j:configuration>
and I added the missing dependency to log4j in the pom.xml file:
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency>
Error handling and HTTP status codes with Spring MVC
The best way of handling errors in Spring MVC is implementing HandlerExceptionResolver interface or using the annotation @ExceptionHandler.
Here you have an example using DefaultHandlerExceptionResolver, the default implementation of HandlerExceptionResolver.
public class MyExceptionResolver extends DefaultHandlerExceptionResolver {
@Override
protected ModelAndView doResolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
try {
if (ex instanceof PossibleSpamException) {
return handlePossibleSpamException((PossibleSpamException) ex, request, response);
}
}
catch (Exception handlerException) {
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
}
return super.doResolveException(request, response, handler, ex);
}
private ModelAndView handlePossibleSpamException(PossibleSpamException ex,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); // HTTP Status code 503
return new ModelAndView();
}
}
This resolver is defined in the applicationContext.xml:
<bean id="exceptionResolver" class="domain.MyExceptionResolver" />
And the corresponding JSP is declared in web.xml:
<error-page> <error-code>503</error-code> <location>/WEB-INF/views/errors/503.jsp</location> </error-page>
Mixing instances in a Cucumber World
I recently had the problem of calling a step from another step definition in cucumber using groovy (cuke4duke). Example:
Given (~/I look for "(.*)" in "(.*)"/) { what, where ->
// groovy code
}
to be called from another step:
When (~/I perform more than (.*) searches per minute/) { int number ->
(1..number).each {
Given('I look for "John Smith " in "London"')
}
}
It’s possible to do this using Ruby (the cucumber native language), Java or Scala; but apparently it is not currently possible on groovy.
After posting my question on Cukes Groups I came up with this solution:
HomeSteps.groovy
Given (~/I look for "(.*)" in "(.*)"/) { what, where ->
lookFor(what, where)
}
ErrorsSteps.groovy
When (~/I perform more than (.*) searches per minute/) { int number ->
(1..number).each {
lookFor("John Smith","London")
}
}
env.groovy
import geb.Browser
import org.openqa.selenium.firefox.FirefoxDriver
this.metaClass.mixin(cuke4duke.GroovyDsl)
class Searcher {
def lookFor(what, where) {
go('/')
$('form')[0].looking_for = what
$('form')[0].location = where
$('input', value: "Search")[0].click()
}
}
World() {
def world = new Browser("http://localhost:8080/myApp") // mixing an instance of Browser
world.metaClass.mixin Searcher
return world
}
After() {
clearCookies()
}
Notice that I am not mixing an Object as Richard Paul suggested. In my case, I need to get an specific instance of Browser to be used across steps.
Anyway, I am posting this solution for people who might need something like this. In my case, I found out that my problem is in the way the step definitions are organized. Most of the times this kind of problem is caused by wrong organization of concepts so I recommend you think twice or even three times if you are placing your step in the right place before using a solution like the one I suggested here.
Hope this helps!
Handling form errors on Grails
I have not found clear information about how to deal with form errors on Grails so I made my own investigation.
How to deal with form field errors
We need to bear in mind that each field might have more than one error.
E.g.: Imagine a age field and we enter “abcde”. Having the right constraints, we’d display two error messages: “maximum 3 digits”, “only numbers please”.
In order to do this, Grails provide the following tags: renderErrors, hasErrors and eachError. This is well explained in the user guide.
How to print the list of messages using different formats
What if I don’t want to use the standard as=”list” which generates output?
This is an example of how to print error messages in a paragraph separated by<br/>
<g:hasErrors bean="${customer}" field="email">
<p>
<g:eachError bean="${customer}" field="email">
<g:message error="${it}" /><br/>
</g:eachError>
</p>
</g:hasErrors>
How to print global errors
I could not find a better way of doing this than through the standard Spring Errors interface:
Having a customer bean, in the controller:
customer.errors.reject("registration.data.access.error")
error()
And in the view:
<g:each var="error" in="${customer.errors.globalErrors}">
<g:message error="${error}" />
</g:each>
Grails 1.3.6 & JNDI on Tomcat
We’ve been struggling for a couple of days to configure grails to pick up JNDI resources using the embedded tomcat plugin (run-app). After some googling I found an article which solved my problem. At least for now. You will find the link to the article at the end of this post. For completeness, I’ve added a few comments in this blog post + the steps for how to get this working.
Before we start. Some notes about Tomcat and JNDI.
Tomcat support a number of different JNDI resource types (normally configured in Tomcat’s context xml file).
These are:
<Environment>
<Resource>
<ResourceLink>
<Transaction>
On a side note, also Jetty support at least the first three resource types but additional configuration is needed which is beyond the scope of this post.
The <Environment> type is mainly used to configure environmental properties within an application while <Resource> and <ResourceLink> types link to external resources such as JDBC, JMS or LDAP. I won’t elaborate on <Transaction> since I’m unfamiliar with this type.
When it comes to configuring the embedded tomcat plugin (1.2-M2) with JNDI it took a little while to get this right.
If you are only using <Resource> types you won’t have any problems \:) The problem you will encounter is with applications using the <Environment> type. As of version 1.2-M2 the tomcat plugin doesn’t support <Environment> JNDI types. On the other hand, the Jetty plugin support both of them. The very quick solution is to switch to Jetty obviously. Hopefully next version of the tomcat plugin will have better JNDI support. In the meantime we have to fall back on the following hack.
There is an easy way to get the Tomcat plugin to accept other types of JNDI resources and this is what the following article is about [http://6by9.wordpress.com/2010/12/10/grails-1-3-5-tomcat-plugin-and-jndi-environment-variables/]
I’ve also provided the steps here but please read the article before following the steps below.
Do the following:
- Locate the following file TomcatServer.groovy. Mine was located under:C:\Documents and Settings\alejandro.cuesta\.grails\1.3.6\projects\trace\plugins\tomcat-1.3.6\src\groovy\org\grails\tomcat
- Replace the private preStart() method with the following methods
private preStart() {
eventListener?.event("ConfigureTomcat", [tomcat])
def jndiEntries = grailsConfig?.grails?.naming?.entries
if(jndiEntries instanceof Map) {
def envs = jndiEntries.remove('environments')
if (envs instanceof Map) {
envs.each { name, cfg ->
if (cfg) {
addEnvironment(name, cfg)
}
}
}
def ress = jndiEntries.remove('resources')
if (ress instanceof Map) {
ress.each { name, cfg ->
if (cfg) {
addResource(name, cfg)
}
}
}
jndiEntries.each { name, cfg ->
if(cfg) {
addResource(name, cfg)
}
}
}
}
private addEnvironment(name, envCfg) {
if (!envCfg["type"]) {
throw new IllegalArgumentException("Must supply a environment type for JNDI configuration")
}
def env = loadInstance('org.apache.catalina.deploy.ContextEnvironment')
env.name = name
env.type = envCfg.type
env.description = envCfg.description
env.override = envCfg.override as boolean
env.value = envCfg.value
context.namingResources.addEnvironment env
}
private addResource(name, resCfg) {
if (!resCfg["type"]) {
throw new IllegalArgumentException("Must supply a resource type for JNDI configuration")
}
def res = loadInstance('org.apache.catalina.deploy.ContextResource')
res.name = name
res.auth = resCfg.remove("auth")
res.scope = resCfg.remove("scope")
res.type = resCfg.remove("type")
res.description = resCfg.remove("description")
// now it's only the custom properties left in the Map...
resCfg.each {key, value ->
res.setProperty (key, value)
}
context.namingResources.addResource res
}
- The tomcat plugin has now been configured to also read environment resource types
- You should now be able to define your resources in Config.groovy. Such as
grails.naming.entries = [
"resources" : [
"jms/bananas": [
type: "org.apache.activemq.command.ActiveMQTopic",
description: "Fruit salad",
factory: "org.apache.activemq.jndi.JNDIReferenceFactory",
physicalName: "bananas"
]
],
"environments" : [
"/app/config/db.mysql.username": [
type: "java.lang.String",
value: "MYUSERNAME",
override: "true"
],
"/app/config/db.mysql.password": [
type: "java.lang.String",
value: "MYPASSWORD",
override: "true"
]
]
]
Using snapshots stored in your maven repository with Grails
In my current project, we are developing a core domain library to be shared across different web applications of different companies. We are also developing the new website of one of those companies in Grails. Therefore, we need to declare a Grails dependency on the core domain library which is stored on a Maven repository.
Grails, by default, uses Ant to build the project and Ivy to resolve dependencies. Using maven as a repository is very easy: you only need to declare it on the “BuildConfig.groovy” file.
The problem is that this simple approach does not pick up changes on snapshots. The way I solved this was using “useOrigin true” in the same file.
Here you have the BuildConfig.groovy file:
grails.project.dependency.resolution = {
useOrigin true
...
repositories {
...
mavenLocal()
mavenCentral()
...
}
...
}
Gradle on Grails
I am taking my first steps on grails on a real project after playing around with it for a while.
The first problem I came across was: how to deal with dependencies? In my project, we have some dependencies on libraries stored in our internal maven repository.
You have three options here:
- Use Ivy which comes out-of-the-box in Grails. Ivy is just a dependency manager for ant. I have never used it and looks old-fashioned, so I went to the next step.
- Mavenize your project.
- Use gradle, which is the latest cool builder. A mix of Ant and Maven with the power of the Groovy language.
As I said, I ignored Ivy.
My first successful attempt was Maven. It is quite easy following the steps in the documentation.
Anyway, I really wanted to use Gradle because it looks really easy to read, so I gave it a go. My starting point was this article by Peter Ledbrook but it was confusing because the build script contains errors. So after reading the comments, I went to the grails-gradle-plugin project instead.
After a couple of hours, I ended up with this solution:
- Create an empty folder for your project
- Go to root of your new project folder and store the build.gradle script below.
- Run ‘gradle init’ to create the grails layout
- Use the normal grails commands using the “grails-” prefix.
$ gradle grails-run-app
This is the build.gradle script
buildscript {
repositories {
mavenCentral()
mavenRepo urls: "http://repository.jboss.org/maven2/"
}
dependencies {
classpath "org.grails:grails-gradle-plugin:1.0",
"org.grails:grails-bootstrap:1.3.6"
}
}
apply plugin: "grails"
version = '1.0-SNAPSHOT'
// this is your local maven repository
def localMavenRepository = new File( System.getProperty("user.home" ), ".m2/repository" ).toURL().toString()
repositories {
mavenCentral()
mavenRepo urls: "http://repository.jboss.org/maven2/"
mavenRepo urls: "http://download.java.net/maven/2/"
mavenRepo name:'localMavenRepo', urls: localMavenRepository
}
configurations {
compile.exclude module: "xml-apis"
}
dependencies {
compile "org.grails:grails-crud:1.3.6",
"org.grails:grails-gorm:1.3.6"
runtime "org.slf4j:slf4j-log4j12:1.5.5",
"hsqldb:hsqldb:1.8.0.5",
"jstl:jstl:1.1.2"
}
You may need to add or remove dependencies. This depends on your project.
Hope this saves you some time.
UPDATE 4 JAN 2011
The example above was done using gradle 0.9. The new version 0.9.1 supports mavenLocal() so you can remove the localMavenRepository definition and replace the last mavenRepo with mavenLocal()
Groovy & Grails eXchange 2010
I’ve just come from the Groovy & Grails eXchange 2010. I am not an expert on Groovy or Grails but I must admit that I have learned lots of things and I can’t wait to start using this technology on my next project.
My highlights of these two days of talks:
- I really loved Tomas Lin‘s talk about Geb. This is just a web testing framework based on Spock using a groovy DSL based on the JQuery language. In other words, bye bye WebDriver’s findElementBy and welcome JQuery selectors. It uses the Page Object pattern so tests are organized better. This also comes as a Grails plugin.
- I loved the talk by the guys from Sky.com who developed the whole site in Grails after comparing the productivity between two teams implementing the same features in two weeks. Groovy represents 95% of their code whereas 5% is Java. They test absolutely everything: unit testing and lots of functional testing to guarantee releases every week. They even test deployments!
- Gradle is becoming the next building tool. I really like it. It seems to be easy to use because it is just a combination of Ant and Maven with the power of Groovy.
- From Graeme Rocher‘s keynote:
- DB reverse engineering to create domain classes from a database schema.
- Database migration
- New GORM implementations for nosql databases: mongodb, redis, gemfire…
- A demo of Spring insight, a tc server profiling tool. Very cool but JavaMelody looks better and independent from tc Server.
- From Laforge’s keynote I liked:
- Default values for maps via .withDefault()
- Inline dependency declaration with Grape via @Grab
- Powerful asserts
- Currying: rcurry, ncurry
- Memoization in the next version of Groovy 1.8 (caching of results returned by closures)
- Plugins for almost everything!