Spring Data and MongoDB in under 10 minutes

This is a quick, less than 10 minutes tutorial on getting your application bootstrapped to use Spring Data to persist data to MongoDB.

Creating your Spring project
1. Create a Maven project in your favourite IDE

2. Add the following dependencies to your pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.c0deattack.examples</groupId>
    <artifactId>springdatamongodb</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springdatamongodb</name>
    <url>http://c0deattack.wordpress.com</url>

    <properties>
        <org.springframework-version>3.1.0.RELEASE</org.springframework-version>
        <org.springframework.data-version>1.0.2.RELEASE</org.springframework.data-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>${org.springframework.data-version}</version>
        </dependency>
    </dependencies>

</project>

3. Add the following to your Spring application context file, I’ve named my file application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">

    <mongo:db-factory dbname="testuserexample" host="localhost" />

    <bean id="mongoTemplate">
        <constructor-arg ref="mongoDbFactory" />
    </bean>

    <mongo:repositories base-package="com.c0deattack.examples.springdatamongodb" />

</beans>

4. Add the following classes to your project

package com.c0deattack.examples.springdatamongodb;

public class User {

	private String id;
	private String name;

	public User(String name) {
		this.name = name;
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

}

package com.c0deattack.examples.springdatamongodb;

import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, String> {
}

package com.c0deattack.examples.springdatamongodb;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

		UserRepository userRepository = context.getBean("userRepository", UserRepository.class);

		User user = new User("C0deAttack", "28");

		userRepository.save(user);

		String id = user.getId();
                System.out.println(id);

                User userFromDb = userRepository.findOne(id);
                System.out.println(userFromDb.getName());
        }
}

Installing and Running MongoDB

5. Now that your app has been built you need to install and run MongoDB. It’s pretty simple to install and run MongoDB just follow the instructions for you system here: http://www.mongodb.org/display/DOCS/Quickstart

If  you’re using Ubuntu to install MongoDB it’s as easy are running:

sudo apt-get install mongodb-10gen

6. Make sure MongoDB is running on your system. If you’re using Ubuntu just run:

mongo

Run your App

7. Now, run App.java and check your System console, you should see a string like 50510a66472829882bfa7610. This is the Id generated by MongoDB. And you should also see the user name that was returned from the findOne() query.

Summary

That’s some powerful (not to mention very cool!) stuff right there. We didn’t write a single line of the usual CRUD boilerplate code we typically do when writing DAOs. By implementing a specific Spring Data Repository interface we were able to Create a new document in our MongoDB database.

There’s definitely a lot happening behind the scenes here which if you have questions I can answer in the comments, or you can refer to the Spring Data documentation.

, , ,

Leave a comment

Cucumber-JVM Example Continued – Refactoring

In my previous post I showed you how to use Cucumber-JVM to execute a JUnit test. We’ll continue with that example in this post by refactoring the work we’ve done.

Open DepositStepDefinitons.java and notice the 2 private classes, User and Account which we added. Clearly, these are our domain objects that the real system will need, and that other scenarios would likely make use of too. So lets extract these private classes in to their own class files and make them public.

Once you create the User.java and Account.java classes, execute RunTests.java to make sure the scenario is still passing. Still passes? Great!

The next section I would like to highlight is the problem in our When step: When £100 is deposited in to the account. If this step was reused in another scenario we could potentially have a problem with the account object, it may be null, since we were initializing it in the Given step which we might not use in a new scenario. So lets refactor this part of the class so we always have a correctly initialized domain.

Like with regular JUnit steps there are hooks to allow us to run some code before and after each test, or in our case, each scenario. Cucumber has the same hooks, cucumber.annotation.Before. Refactor your class to look like this:

src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

package com.c0deattack.cucumberjvmtutorial;

import static org.junit.Assert.assertTrue;

import com.c0deattack.cucumberjvmtutorial.domain.Account;
import com.c0deattack.cucumberjvmtutorial.domain.User;

import cucumber.annotation.Before;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;

public class DepositStepDefinitions {

	private User user;
	private Account account;

	@Before
	public void initialize() {
		if (user == null) {
			user = new User();
		}

		if (account == null) {
			account = new Account();
			user.setAccount(account);
		}
	}

	@Given("^a User has no money in their account$")
	public void a_User_has_no_money_in_their_current_account() {
	    assertTrue("The balance is not zero.", account.getBalance() == 0L);
	}

	@When("^£(\\d+) is deposited in to the account$")
	public void £_is_deposited_in_to_the_account(int amount) {
	    account.deposit(amount);
	}

	@Then("^the balance should be £(\\d+)$")
	public void the_balance_should_be_£(int expectedBalance) {
		int currentBalance = account.getBalance();
	    assertTrue("The expected balance was £100, but actually was: " + currentBalance, currentBalance == expectedBalance);
	}

}

Here, I’ve added an initialize method with a @Before annotation. This annotation will execute for every scenario, regardless of which Feature the scenario is in. What would make this better is if we can tell Cucumber to only invoke that Before hook on specific scenarios. We can actually do this, by tagging the Scenarios, and passing the same tag expression to the @Before annotation, like this:

src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

package com.c0deattack.cucumberjvmtutorial;

import static org.junit.Assert.assertTrue;

import com.c0deattack.cucumberjvmtutorial.domain.Account;
import com.c0deattack.cucumberjvmtutorial.domain.User;

import cucumber.annotation.Before;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;

public class DepositStepDefinitions {

	private User user;
	private Account account;

	@Before(value="@UserAccounts")
	public void initialize() {
		if (user == null) {
			user = new User();
		}

		if (account == null) {
			account = new Account();
			user.setAccount(account);
		}
	}

	// rest of class....
}

src/test/resources/com/c0deattack/cucumberjvmtutorial/deposit.feature

Feature: Depositing money in to a User account

@UserAccounts
Scenario: Depositing money in to User's account should add money to the User's current balance
Given a User has no money in their account
When £100 is deposited in to the account
Then the balance should be £100

If you wanted a particular tag expression to apply to the all Scenarios within a Feature file then you can move the tag expression up to the first line of the file, before the word Feature.

This pretty much concludes the basics of refactoring your Cucumber step definitions. Some key points to remember:

  • Make your steps reusable by thinking about the objects they interact with and the lifecycle of the objects
  • Use the@Before/@After hooks to setup/teardown data
  • Use tag expressions to specify when you want the @Before/@After hooks to be applied

Please leave a comment if you have any questions.

, ,

9 Comments

Cucumber-Jvm with Cucumber-Java + Cucumber-JUnit Example

In this post I will show you how to add Cucumber-Jvm to your project, how to write a scenarios and step definitions using JUnit 4, and of course how to execute those scenarios, all that using the Java language. No more Ruby dependency, :).

I have created a simple Banking application using Eclipse IDE to demonstrate writing and executing scenarios. Well, the application hasn’t been built, at this point I have just a blank Maven project. I’ll be employing Behaviour Driven Development (BDD) to write the tests and then the implementation, using outside-in development to ensure that the only code I write is code that is needed to meet the acceptance criteria.

After creating a blank Maven project, you need to add the following dependencies to your project’s pom.xml file:

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.0.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.0.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>

A standard Maven project directory structure will have a source folder src/test/resources, this is the directory where you should create your .feature files. So let’s create a feature for depositing money in to a Users bank account.

Create a file called deposit.feature in src/test/resources. You can of course create packages in this source folder to organize your feature files.

Let’s write our first simple scenario. We want to test that when an amount has been deposited in to a User’s account that the User’s current balance has been updated by that amount.

src/test/resources/com/c0deattack/cucumberjvmtutorial/deposit.feature

Feature: Depositing money in to a User account

Scenario: Depositing money in to User's account should add money to the User's current balance
Given a User has no money in their account
When £100 is deposited in to the account
Then the balance should be £100

This first scenario describes the steps that will have to be executed successfully for the Scenario to pass. At this point you might be wondering how to execute that scenario?

You run the .feature using a JUnit Runner, which we already have from the Cucumber-Junit Library. So all we need to do is create a blank test class, and annotate it with JUnit’s @RunWith annotation as follows:

src/test/java/com/c0deattack/cucumberjvmtutorial/RunTests.java

package com.c0deattack.cucumberjvmtutorial;

import org.junit.runner.RunWith;
import cucumber.junit.Cucumber;

@RunWith(Cucumber.class)
@Cucumber.Options(format={"pretty", "html:target/cucumber"})
public class RunTests {
}

You can now run RunTests.java like you would any other JUnit test. Take a look at the JUnit Tab in your Eclipse IDE. You’ll see that the test appears to have passed – how can this be if we never created a User, or an Account or a method to deposit money?
Take a closer look, the scenario steps were actually skipped, they were not executed because no step definitions were found. Take a look at the output in the Console Tab in Eclipse. You’ll see some very helpful information about the scenario that was executed and the steps which were skipped.
The output also has shown you default implementations for the step definitions, how awesome is that!

Let’s create a class for the step definitions.
src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

package com.c0deattack.cucumberjvmtutorial;

import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import cucumber.runtime.PendingException;

public class DepositStepDefinitions {

    @Given("^a User has no money in their account$")
    public void a_User_has_no_money_in_their_current_account() {
        // Express the Regexp above with the code you wish you had
        throw new PendingException();
    }

    @When("^£(\\d+) is deposited in to the account$")
    public void £_is_deposited_in_to_the_account(int arg1) {
        // Express the Regexp above with the code you wish you had
        throw new PendingException();
    }

    @Then("^the balance should be £(\\d+)$")
    public void the_balance_should_be_£(int arg1) {
        // Express the Regexp above with the code you wish you had
        throw new PendingException();
    }
}

At this point we’re ready to implement the step definitions. Let’s start with the Given step; Given a User has no money in their current account. The step hints at us to create a User entity and an Account entity. Let’s create these locally in DepositStepDefinitions.java, we will refactor our code later on.

src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

package com.c0deattack.cucumberjvmtutorial;

import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import cucumber.runtime.PendingException;

public class DepositStepDefinitions {

	@Given("^a User has no money in their account$")
	public void a_User_has_no_money_in_their_current_account() {
	    User user = new User();
	    Account account = new Account();
	    user.setAccount(account);
	}

	@When("^£(\\d+) is deposited in to the account$")
	public void £_is_deposited_in_to_the_account(int arg1) {
	    // Express the Regexp above with the code you wish you had
	    throw new PendingException();
	}

	@Then("^the balance should be £(\\d+)$")
	public void the_balance_should_be_£(int arg1) {
	    // Express the Regexp above with the code you wish you had
	    throw new PendingException();
	}

	private class User {
		private Account account;

		public void setAccount(Account account) {
			this.account = account;
		}
	}

	private class Account {
	}
}

This isn’t quite right, the Given step is saying that the balance should be zero, but all we’re doing in the step definition is creating a User and an Account. So let’s also add an assert statement to ensure the balance is zero.

src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

@Given("^a User has no money in their account$")
public void a_User_has_no_money_in_their_current_account() {
	User user = new User();
	Account account = new Account();
	user.setAccount(account);
    assertTrue("The balance is not zero.", account.getBalance() == 0);
}

Adding the assertion at Line 6 also guided us to create a balance in the Account.

Try running RunTests.java now and you’ll see we have to now implement the When step; When £100 is deposited in to the account. Let’s do that now. We need to take the amount, which is passed to our step definition as a method argument, and deposit it in to the account which was created in the previous step. So we need access to the account which we created. Let’s refactor the code so that we can access the account, like this:

src/test/java/com/c0deattack/cucumberjvmtutorial/DepositStepDefinitions.java

package com.c0deattack.cucumberjvmtutorial;

import static org.junit.Assert.assertTrue;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import cucumber.runtime.PendingException;

public class DepositStepDefinitions {

	private Account account;

	@Given("^a User has no money in their account$")
	public void a_User_has_no_money_in_their_current_account() {
	    User user = new User();
	    account = new Account();
	    user.setAccount(account);

	    assertTrue("The balance is not zero.", account.getBalance() == 0L);
	}

	@When("^£(\\d+) is deposited in to the account$")
	public void £_is_deposited_in_to_the_account(int amount) {
	    account.deposit(amount);
	}

	@Then("^the balance should be £(\\d+)$")
	public void the_balance_should_be_£(int arg1) {
	    // Express the Regexp above with the code you wish you had
	    throw new PendingException();
	}

	private class User {
		private Account account;

		public void setAccount(Account account) {
			this.account = account;
		}
	}

	private class Account {
		private int balance;

		public Account() {
			this.balance = 0;
		}

		public int getBalance() {
			return balance;
		}

		public void deposit(int amount) {
			this.balance += amount;
		}
	}

}

Here we have made an Account a class member. It is initialized in the Given step, and in the When step we deposit an amount. The step has guided us to create an account.deposit(amount) method. After adding the When step definition implementation we execute the Feature again and we’re told that we still need to properly implement the final Then step; Then the balance should be £100;

    @Then("^the balance should be £(\\d+)$")
    public void the_balance_should_be_£(int expectedBalance) {
	int currentBalance = account.getBalance();
        assertTrue("The expected balance was £100, but actually was: " + currentBalance, currentBalance == expectedBalance);
    }

That’s it! You’ve now written your first Feature file, with your first Scenario and implemented your first step definitions which execute the Scenario. What’s next? Refactor! Clearly we have plenty of opportunity to refactor our DepositStepDefinitons.java class, for instance we don’t want to leave those private classes in there. And we don’t really want to leave the Account class member like that either. We want our steps to be reusable across many scenarios. But at the moment the When step cannot be reused without first ensuring an account exists (ie. is not null).

In my next post we will refactor this class to address those issues. But hey, why wait for me, give it a go yourself!

, , , , ,

27 Comments

Change of focus

I was going to use this blog to focus solely on Android development but I find myself doing more work with Java, Spring, Hibernate, Grails, Gorm and Groovy these days. So as my focus has changed so will the focus of this blog.

I never managed to finished my Tanks vs. Turret game, but at least I did release Tap In Time on the market :)

So I’m drawing a line here to let people know, people who mostly end up here via the AndEngine website, that I won’t be blogging about AndEngine. I will probably continue to mention Android every now again but it will not be a primary focus. I’ll leave all the old posts here as there’s no point in deleting them since there is some useful information in them.

The Line is drawn.

____________________________________________________________________________

1 Comment

New site for my apps and games

I’ve setup http://vidoapps.wordpress.com to advertise my applications and games which I publish. That keeps all the promo stuff away from this blog so I can keep this one clean and continue to blog about development and what not.

Anyway, if you’ve not checked out my game head over to my new game site to checkout more details: http://vidoapps.wordpress.com/tap-in-time/

Leave a comment

Tap in Time, my first game!

I’ve actually managed to stick with a game project for once and finish it! It’s a pretty nice feeling.

Tap in Time is on the Android Market Place and can be downloaded for FREEEEEE from this link http://market.android.com/details?id=com.vidoapps.tapintime

I would absolutely love any feedback or comments so speak freely, thank you!

2 Comments

AndEngine: Using the Object Pool

When developing a game or application for a mobile device you, as the developer, must concern yourself in actively keeping your memory footprint small. One of the best ways to do this is to reuse Objects. Android does this, the best example must be the ListView. To achieve the super smooth, super fast scrolling the list items are reused! This is performant as you will not be wasting precious CPU cycles creating and destroying objects, so you see why that’s important in a game, right!?

So here I present a tutorial for using Object Pools in AndEngine (http://www.andengine.org).

The Object Pool

As you may know, I’ve been making a game which involves shooting (If you don’t know, see here), naturally a shooting game means many bullets will be fired in the game. This could mean that you will create a large number of objects which represent those bullets. Bullets will move offscreen or they may collide with other objects. These bullets are ideal candidates for reuse, once they’re offscreen or they’ve hit something we can hide them from being drawn, and recycle them by sending them to the pool and then requesting one again if we need one.

If you’re on the ball you might at this point think “what will happen if I ask the pool for a bullet but there aren’t any?”, well you’ll get a brand new one. Which you can put back in the pool once you’re done with it.

If you’re struggling to understand how the pool would work, you could think of it as such:

Game: I need a bullet! Mr. Object Pool can I have an instance of a Bullet please?
Mr. Object Pool: Let me check my pool…I don’t have spare Bullets, I’ll create a new Bullet for you
Game: Thanks!
Game: Mr. Object Pool, this bullet has moved offscreen so I don’t need it anymore, please recycle it for me
Mr. Object Pool: Ok, thanks, I’ll put that instance in my pool
Game: Hey, I need another Bullet again
Mr. Object Pool: No problem, I have one in my pool which you gave me, I don’t need to waste time making a new Bullet, you can have this one!

Creating the Object Pool

First thing to do is to create the Pool that will hold and return Bullets. There is an abstract class named GenericPool.java which you extend to implement a few methods. So let’s do that.

public class BulletPool extends GenericPool<BulletSprite> {
 private TextureRegion mTextureRegion;

 public BulletPool(TextureRegion pTextureRegion) {
  if (pTextureRegion == null) {
   // Need to be able to create a Sprite so the Pool needs to have a TextureRegion
   throw new IllegalArgumentException("The texture region must not be NULL");
  }
  mTextureRegion = pTextureRegion;
 }

 /**
 * Called when a Bullet is required but there isn't one in the pool
 */
 @Override
 protected BulletSprite onAllocatePoolItem() {
  return new BulletSprite(mTextureRegion);
 }

 /**
  * Called when a Bullet is sent to the pool
 */
 @Override
 protected void onHandleRecycleItem(final BulletSprite pBullet) {
  pBullet.setIgnoreUpdate(true);
  pBullet.setVisible(false);
 }

 /**
  * Called just before a Bullet is returned to the caller, this is where you write your initialize code
  * i.e. set location, rotation, etc.
 */
 @Override
 protected void onHandleObtainItem(final BulletSprite pBullet) {
  pBullet.reset();
 }
}

That’s pretty straight forward right? I’ll explain a couple of the methods though just in case. onHandleRecycleItem() this is one of the methods you need to implement in your subclass. In this method I’ve set the sprite to be invisible, this doesn’t really matter if the bullet has gone offscreen but it does matter if the bullet has collided with an object on screen. Also, I’ve called setIgnoreUpdate(true), this will exclude the sprite from being updated whilst the game continues to run, for example; if you had set a Velocity on your sprite you don’t want to continue to have the position of the bullet updated based on that velocity if you’re putting the bullet in the pool. onHandleObtainItem() this is called just before the Sprite is returned to the caller. In the code above I’ve called reset() which just sets the initial values of the bullet back to what they were when the sprite was first created. You could put the reset()  call in the onHandleRecycleItem, I just put it there as an example.

And that’s it, now you’re ready to use the pool.

Using the Object Pool

Now that we’ve created a pool to fetch and send objects to and from we’re ready to make use of it. For berevity I’ll only show relevant code rather than the whole Game Activity.

public class ShooterActivity extends BaseGameActivity {
 private static BulletPool BULLET_POOL;

 @Override
 public void onLoadResources() {
  // Set up the bullets pool so bullet sprites can be created and reused
  BULLET_POOL = new BulletPool(mBulletTextureRegion);
 }

 /**
 * Called because the bullet can be recycled
 */
 private void sendBulletToBulletPool(BulletSprite pBulletSprite) {
  BULLET_POOL.recyclePoolItem(pBulletSprite);
 }

 /**
 * The player fired, we need a bullet to display
 */
 private BulletSprite getBulletFromBulletPool() {
  return BULLET_POOL.obtainPoolItem();
 }
}

Really simple uh! I’ve not included how the sendBulletToBulletPool() or getBulletFromBulletPool() are invoked as that’s not important. The important part is the using the Pool. When the game starts and the resources are loaded we make sure we create an instance of the BulletPool, the mBulletTextureRegion is needed when the Pool needs to create new bullets. The rest should be simple enough to understand, but if you don’t understand just leave a question in the comments area below.

17 Comments

Follow

Get every new post delivered to your Inbox.