Creating a “Simple” MongoDB + Groovy + Maven Project
Currently, I am experimenting with writing a MOO (Programmable text based game). To facilitate the dynamic behavior I want to encourage, I decided to write it using Groovy and MongoDB with Maven[1] doing the actual building. However, the “real world” documentation of this combination has been rather lacking and thus, this post.
First let’s tackle Maven and Groovy. There are currently two Maven plugins for Groovy: GMaven and groovy-eclipse-compiler. GMaven generates .java stub files and tends to have a little bit better integration with Java. However, this leads to having lots of “weird”[2] errors which require a clean and build to fix. groovy-eclipse-compiler doesn’t generate stubs and works a little bit more smoothly in a mostly Groovy project, and that is the plugin I chose to use.
With that out of the way, let’s create the maven project.
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes
For this example, I used “net.saga.blog” as my groupId and “GroovyMongoBlogPost” as my artifactId. If you choose to use different ones, make sure to update your package names accordingly.
Now let’s update the pom to include the groovy builders. First we have to add Groovy to our dependencies:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.8.5</version>
</dependency>
Next, let’s add the groovy-eclipse-compiler and our groovy source directories to our builders. Create a directory named “groovy” in both the src/main and src/test directories. Then add the following to your pom:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/groovy</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/groovy</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<verbose>true</verbose>
<source>1.7</source>
<target>1.7</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.6.0-01</version>
</dependency>
</dependencies>
</plugin>
Perform a quick build and make sure everything is set up correctly so far, I’ll wait.
Now let’s add in our first test. Create in “src/test/groovy” a file:SimpleGroovyTest.groovy.
package net.saga.blog.groovy
/**
*
* @author summers
*/
class SimpleGroovyTest extends GroovyTestCase {
void testPass() {
assert false
}
}
Now perform a build and ensure that the build fails. Once you have a failing build, change false to true and rebuild for the green bar. We now have a fully functional Groovy project being built with Maven.
One of the things I ran into was that JUnit Suites and Groovy don’t behave as much as I would like. Also, a lot of libraries for Java still work “better” in a Java source file. To get around this, I overrode Maven’s default and used JUnit 4.10 and create a class to setup my database and then run the Groovy tests.
First, we replace the JUnit dependency with the following:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
Then we change our test class:
package net.saga.blog.groovymongoblogpost
import org.junit.Test
import com.gmongo.GMongo
/**
*
* @author summers
*/
class SimpleGroovyTest extends GroovyTestCase {
@Test
void testPass() {
assert true
}
}
Now we create a Java class in src/test/java/net/saga/blog/groovymongoblogpost directory.
package net.saga.blog.groovymongoblogpost;
import junit.framework.TestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
/**
* Unit test for simple App.
*/
@RunWith(value = org.junit.runners.Suite.class)
@Suite.SuiteClasses({net.saga.blog.groovymongoblogpost.SimpleGroovyTest.class})
public class AppTestSuite
extends TestSuite
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
}
Finally, we reconfigure surefire in build/plugins in the pom to only run app suites.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<includes>
<include>**/*TestSuite.java</include>
</includes>
</configuration>
</plugin>
Now rebuild your application and make sure your test is run. Once you get that, let’s move on to actually using MongoDB.
Installing MongoDB is beyond the scope of this tutorial (sorry if you were waiting this long for that), but it is rather trivial on a majority of systems. Ubuntu users, for instance, can sudo apt-get install mongodb. Your mileage may vary, but there are plenty of resources. What IS important is that you have Mongo running on your box (at 127.0.0.1) on the default port (27017).
For my project, I have chosen GMongo as my Groovy Mongo driver. It wraps the Java driver and makes is slightly Groovy-er. You will notice the code you write looks much like the Javascript code in your Mongo shell.
Now, add GMongo to your dependencies in your POM:
<dependency>
<groupId>com.gmongo</groupId>
<artifactId>gmongo</artifactId>
<version>0.9.3</version>
</dependency>
Now let’s write some Mongo code. We will create a file that will populate some seed data in our database. This file will be called from the java test suite class. In the groovy test directory (src/test/groovy) create the file TestSetup.groovy.
import com.gmongo.GMongo assert System.properties.database_address //assert System.properties.database_user assert System.properties.database_name //assert System.properties.database_password def port = System.properties.database_port?:27017 def address = System.properties.database_address //def userName = System.properties.database_user def databaseName = System.properties.database_name //def password = System.properties.database_password def mongo = new GMongo(address, port) assert mongo // Get a db reference in the old fashion way def db = mongo.getDB(databaseName) db.users.insert([name:'jesse', password:'scherer']); db.users.insert([name:'kim', password:'berly']); assert db.users.find([name:'jesse', password:'scherer'])[0] != null
And now we need to call it from AppTestSuite
Add some imports:
import groovy.lang.Binding; import groovy.util.GroovyScriptEngine; import java.io.IOException; import junit.framework.TestSuite; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.Suite;
Some static code:
private final static String[] roots = new String[]{"src/test/groovy/net/saga/blog/groovymongoblogpost"};
private final static GroovyScriptEngine gse;
static {
System.setProperty("database_address", "127.0.0.1");
System.setProperty("database_name", "Testing");
try {
gse = new GroovyScriptEngine(roots);
} catch (IOException ex) {
throw new RuntimeException("failed to start tests", ex);
}
}
And actually call the file:
@BeforeClass
public static void setUpSuite() throws Exception {
Binding binding = new Binding();
gse.run("TestSetup.groovy", binding);
}
Now we can add a test to our SimpleTestCase file
@Test
void testSimpleMongoFetch() {
def port = System.properties.database_port?:27017
def address = System.properties.database_address
def databaseName = System.properties.database_name
def mongo = new GMongo(address, port)
def db = mongo.getDB("Testing")
def userResult = db.users.find([name:'jesse', password:'password'])[0]
assertNotNull( userResult )
assertEquals ('jesse', userResult.name)
}
Now if we build out app we should see that we have records in out database AND that groovy can query them.
Asides/Footnotes:
[1]: I understand Gradle may be a better technology (lord knows it can’t be worse), but Maven works much better in Netbeans and that has some pretty powerful side effects.
[2]: Basically if you update your groovy code, the linking will fail and trying to run your tests using the IDE will get a error until you clean and build.
Using an XBOX 360 Controller on Android
I’ve been working on a few Android games in my spare time. With the rollout of Honeycomb to my Logitech Revue, I’ve been able to finally test these games on it. One of the things I noticed was that the Revue has USB Host support and (wired) Xbox 360 controllers are simply plug and play. Using them is quite simple as well; the button presses are mostly mapped to the key event. The left and right triggers, right directional stick, and analog inputs are not mapped through this method however. The left analog stick and directional pads have their inputs mapped to direction buttons.
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_BUTTON_L1:
case KeyEvent.KEYCODE_BUTTON_R1:
case KeyEvent.KEYCODE_BUTTON_THUMBR:
case KeyEvent.KEYCODE_BUTTON_THUMBL:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_BUTTON_START:
case KeyEvent.KEYCODE_BUTTON_MODE://Big button in the middle
case KeyEvent.KEYCODE_BUTTON_B:
case KeyEvent.KEYCODE_BUTTON_A:
case KeyEvent.KEYCODE_BUTTON_X:
case KeyEvent.KEYCODE_BUTTON_Y:
default:
return super.onKeyDown(keyCode, keyEvent);
}
}
Of special note, KeyEvent.KEYCODE_BUTTON_B goes back and KeyEvent.KEYCODE_BUTTON_START pulls up home bar in the default implementation. Also, the “A” button has special behaviors which I don’t fully understand.
For the analog controls however, we must override the method onGenericMotionEvent as follows:
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
Log.d("Right Trigger Value", event.getAxisValue(MotionEvent.AXIS_RTRIGGER) + "");
Log.d("Left Trigger Value", event.getAxisValue(MotionEvent.AXIS_LTRIGGER) + "");
Log.d("Left Stick X", event.getX() + "");
Log.d("Left Stick Y", event.getY() + "");
Log.d("Right Stick Y", event.getAxisValue(MotionEvent.AXIS_RZ) + "");
Log.d("Right Stick X", event.getAxisValue(MotionEvent.AXIS_Z) + "");
return super.onGenericMotionEvent(event);
}
Google Dart Lightning Talk
A few months ago I gave a talk about Google Dart. Here is the presentation.
Getting Started Writing Groovy Tests With Maven and Netbeans
Lately I’ve been trying my hand at non Java languages on the JVM. Since Groovy is quite popular and a well supported language, I was giving it a go. Maven and Netbeans are my preferred project and IDE systems, and I had used GMaven at work so I knew it COULD be done. As a good TDD Developer I decided my first task would be to write a failing unit test and thus began my troubles.
GMaven works by generating Java stubs which are then compiled. This way the IDE has excellent intellisense, static analysis, and other goodies when you use the Groovy code in Java. This has the side effect of requiring a clean and build for every change. The extra step ends up really slowing down my rhythm and I tried to avoid it. Browsing around, it seemed like the groovy-eclipse-compiler plugin would help here. After setting that up, however, my trivial unit test always passed when it should have failed. Eventually I gave up and went back to GMaven.
The GMaven plugin has a project archetype. (mvn archetype:generate -DarchetypeGroupId=org.codehaus.gmaven.archetypes -DarchetypeArtifactId=gmaven-archetype-basic for the lazy), but the default implementation has busted unit tests. I had to remove the import statements from the examples before I could run them. Finally I was given my red bar and could begin coding in earnest.
Overall, this has been far more work than I had hoped. It seems like the GMaven project is thinking about merging with the eclipse compiler project. They hope to solve the stub issue this way, but that seems to be a ways off.