Wednesday, February 20, 2013

From Spring to Guice

For the past two and a half years I have worked primarily on standalone Java applications using Spring/Relational databases and messaging software such as Websphere MQ.

The Well Grounded Java Developer by Ben Evans and Martijn Verburg mentions Guice as an alternative to Spring for dependency injection. I like learning new technologies so I've decided to give it ago!

Here's my attempt at getting a little Guice application up and running. Firstly, I'm going to use Gradle and I'm going to get the Guice jars from the maven central repo. Here is my gradle build file:


apply plugin: 'java'
apply plugin: 'idea'

repositories {
  mavenCentral()
}

dependencies {
  compile 'com.google.inject:guice:3.0'
  testCompile 'junit:junit:4.11'
  testCompile 'org.mockito:mockito-all:1.9+'
}

I've also applied the idea plugin as I am trying out IntelliJ this week after seven years of Eclipse!

So I want a simple application that stores expenses. I am currently spending far too much money on coffee and want to start tracking it.

Lets start with a simple interface:

package com.batey.expense.store;

public interface ExpenseStorer {
    void storeExpense(Expense e);
    Expenses lookupExpenses(String name);
}

With a simple implementation:

package com.batey.expense.store;

import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

@Singleton
public class InMemoryExpenseStorer implements ExpenseStorer {
    private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryExpenseStorer.class);
    private static final Expenses NULL_EXPENSE = new Expenses();
    private Map<String, Expenses> expenses = new HashMap<>();
    @Override
    public void storeExpense(Expense e) {
        Expenses expenses1 = expenses.get(e.getName());
        if (expenses1 == null) {
            expenses1 = new Expenses();
            expenses.put(e.getName(), expenses1);
            expenses1.setGroupName(e.getName());
        }
        expenses1.getExpenses().add(e);
        LOGGER.info("Got {}", expenses1);
        LOGGER.info("Updated expenses {}", expenses);
    }

    @Override
    public Expenses lookupExpenses(String name) {
        Expenses expenses1 = expenses.get(name);
        LOGGER.info("Current expenses {}", expenses);
        if (expenses1 == null) {
            expenses1 = new Expenses();
            expenses1.setGroupName(name);
            expenses.put(name, expenses1);
        }
        LOGGER.info("Returning {}", expenses1);
        return expenses1;
    }
}

Now I want to use this class in another part of my system. Lets say we have another class called BudgetTracker:

package com.batey.expense.budget;

import com.batey.expense.store.ExpenseStorer;
import com.batey.expense.store.Expense;
import com.batey.expense.store.Expenses;
import com.google.inject.Inject;

import java.math.BigDecimal;

public class BudgetTracker {

    @Inject
    private ExpenseStorer expenseStorer;

    public void buySomething(String description, String who, BigDecimal howMuch) {
        Expense expense = new Expense();
        expense.setAmount(howMuch);
        expense.setName(who);
        expense.setDescription(description);
        expenseStorer.storeExpense(expense);
    }

    public BigDecimal howMuchHaveISpent(String who) {
        Expenses expenses = expenseStorer.lookupExpenses(who);
        return expenses.getTotal();
    }
}

Everything above was done without thinking about dependency injection. Then rather than instantiate an ExpenseStorer directly I then read through Google's getting started guide at http://code.google.com/p/google-guice/wiki/GettingStarted and added the Guide annotations in red.

So how do we run this? For that we need a Guide module:

package com.batey.expense.store;

import com.google.inject.AbstractModule;

public class ExpenseModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(ExpenseStorer.class).to(InMemoryExpenseStorer.class);
    }
}

And then I put together a very simple main method:

package com.batey.expense.budget;

import com.batey.expense.store.ExpenseModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

import java.math.BigDecimal;

public class Main {
    public static final void main(String[] args) {
        Injector injector = Guice.createInjector(new ExpenseModule());
        BudgetTracker budgetTracker = injector.getInstance(BudgetTracker.class);

        budgetTracker.buySomething("A tv", "Chris", new BigDecimal("100.00"));
        budgetTracker.buySomething("A cake", "Chris", new BigDecimal("50.00"));

        System.out.println("Chris has spent: " + budgetTracker.howMuchHaveISpent("Chris"));
    }
}

And then running this:

20:39:46.168 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Got Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}], total=0, groupName='Chris'}
20:39:46.171 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Updated expenses {Chris=Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}], total=0, groupName='Chris'}}
20:39:46.172 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Got Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}, Expense{name='Chris', amount=50.00, description='A cake'}], total=0, groupName='Chris'}
20:39:46.172 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Updated expenses {Chris=Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}, Expense{name='Chris', amount=50.00, description='A cake'}], total=0, groupName='Chris'}}
20:39:46.172 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Current expenses {Chris=Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}, Expense{name='Chris', amount=50.00, description='A cake'}], total=0, groupName='Chris'}}
20:39:46.172 [main] INFO  c.b.e.store.InMemoryExpenseStorer - Returning Expenses{expenses=[Expense{name='Chris', amount=100.00, description='A tv'}, Expense{name='Chris', amount=50.00, description='A cake'}], total=0, groupName='Chris'}
Chris has spent: 150.00



Key points:
  • We use the @Singleton on the ExpenseStorer to say we only want one of these in our application. Singleton is the default in spring: not so in Guice.
  • We use @Inject to identify a field needs injected. This could have also been done via the constructor. This is like the spring @Autowired
  • Inside the ExpenseModule we bind any injected ExpenseStorers to the InMemoryExpenseStorer implementation.
Success! From never having used Guice getting this together was very straightforward and took under thirty minutes. My initial thoughts of Guice for dependency injection:
  • It is very simple! I don't remember how long my first Spring application took me to get going but I bet it was longer than this!
  • No XML! Some people love configuration XML; others hate it. Personally, I'm sitting on the fence. In the latest applications I've written I've used a combination of annotations Java config along with XML config. Guice is pure Java config and I'd have to see a large scale project using it before passing judgement on that.
  • Standardisation! Guice is the first implementation of JSR330 - making DI standardized in Java can only be a good thing.
I'm going to keep building my expense application with Guice and will post more about it when I have used it more!

Krav Maga, clipless peddling and unemployment (by choice)

Today I tried Krav Maga and decided to switch to a clipless pedal system on my bike. I am quite surprised I am in once piece given I ventured across central London with no practise! I also became unemployed; busy day!

7 Languages in 7 weeks: Ruby day 3


Ruby Day 3: Serious change 

The final day on Ruby is all about metaprogramming. It takes you through:
  • Adding methods to open classes
  • Using method missing to produce very human readable syntax
  • Adding functionality to classes via Modules
Having used Java reflection, Java IDL Dynamic Invocation Interface (DII) and the Java IDL Dynamic Seketon Interface extensively when I used to develop IBM's Websphere Message Broker I know how cumbersome any form of metaprogramming is in Java. So I enjoyed playing around with a language that does it much better!

Now to the Self study. Only one this time! Modify the Csv application to support an each method to return a CsvRow object. E.g for the following csv file:

one, two
lions, tigers

allow an API that works like this:

csv = RubyCsv.new
csv.each{|row| puts row.one}

This should print "lions".

Well I decided to work with the following input:

one, two, three
1, 2, 3 
uno, dos, tres

And here is my solution using modules and method missing:

module ActsAsCsv
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def acts_as_csv
      include InstanceMethods
    end
  end

  module InstanceMethods
    def read
      @csv_contents = []
      filename = self.class.to_s.downcase + '.txt'
      file = File.new(filename)
      @headers = file.gets.chomp.split(', ')

      file.each  do |row|
        @csv_contents << row.chomp.split(', ')
      end
    end

    def each(&block)
      @csv_contents.each_index do |index|
        hash = Hash[@headers.zip @csv_contents[index]]
        block.call(CsvRow.new(hash))  
      end
    end
  end

  attr_accessor :headers, :csv_contents
  def initialize
    read
  end
end

class RubyCsv
  include ActsAsCsv
  acts_as_csv
end

class CsvRow
  def initialize(arg)
    @arg = arg
  end
  
  def method_missing name, *args
    key = name.to_s
    return @arg[key]
  end
end


m = RubyCsv.new
m.each do |row| 
  puts row.send(ARGV[0])
end


And that is it for Ruby!

Monday, February 18, 2013

7 Languages in 7 weeks: Ruby day 2


Day 2: Floating Down from the sky


On day 2 we're introduced to code blocks, arrays, hashes and mixins. The more I see code blocks in other languages the more I am looking forward to Java 8. Coming from Java I get particulary jealous of languages with syntaxctic sugar for arrays and hashes; initialising them in Java is cumbersome.

Self-Study

1) Print the contents of an array 4 elements at a time:

Sticking to the verbose solution for now:


array = Array(1..16)

array.each do |x|
  if (x % 4 == 0) 
    print "#{x}\n"
  else
    print "#{x},"
  end
end

Now with slice:

irb(main):014:0> array = Array(1..16)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
irb(main):015:0> array.each_slice(4) {  |slice| puts slice.join(",") }
1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16

2) Tree with a nice constructor:

After finishing this I found a nicer solution with collect, but here is my original:

class Tree
  attr_accessor :children, :node_name

  def initialize( fullTree={})
    @children = []
    @node_name = fullTree.keys.first
    fullTree[@node_name].each do |key,value| 
      children.push(Tree.new( {key=>value} ))
    end
  end
  
  def visit_all(&block)
    visit &block
    children.each{ |c| c.visit_all &block }
  end

  def visit(&block)
    block.call self
  end
end

ruby_tree = Tree.new({ 'grandad' => { 'dad' => { 'child 1' => {}   }, 'uncle'   => {}  } })

ruby_tree.visit_all { |t| puts t.node_name  }

3) Ruby grep!

pattern = Regexp.new(ARGV[0])
file = File.new(ARGV[1], "r")

counter = 0
file.each_line do |line|
  if line.match(pattern)
    puts "#{counter}: #{line}"
  end
  counter = counter + 1
end

Day 3 to come some time this week hopefully!

Saturday, February 16, 2013

7 Languages in 7 weeks: Ruby day 1

Having decided I spend far too much time programming with Java I added the 7 languages in 7 weeks to my Amazon wish list and come Christmas it turned up.

Day 1: Finding a Nanny (Ruby)

Firstly we're introduced to Ruby's interactive console. My first conclusion is that all languages should have an interactive console!

A few differences to Java that stand out:

  • Interpreted: Nuff said.
  • You have the unless conditional so you can write lines that read quite nicely: order.calculate_tax unless order.nil?
  • Everything is an Object, including primitives.
  • Duck typing: You can call any method on an object and if it has it at runtime it will be called. You don't have to have classes inherit from the same class to be used in the same way.

The homework

Print the string Hello, World.

puts 'hello, world'

For the string "Hello, Ruby" find the index of the word "Ruby"

irb(main):007:0> "Hello, Ruby!".index('Ruby')
=> 7

Print your name ten times

irb(main):009:0> for i in 1..10
irb(main):010:1> puts "Christopher"
irb(main):011:1> end

Print the string "This is sentence number 1" where the number 1 changes from 1 to 10

irb(main):009:0> for i in 1..10
irb(main):010:1> puts "This is sentence number #{i}"
irb(main):011:1> end

Run a Ruby program from a file

chbatey ~/dev/7languages/ruby $ cat day1.rb 
#!/usr/bin/env ruby

puts "Hello"

Bonus problem: Guess a number between one and ten:


#!/usr/bin/env ruby
rand = rand(10)
puts "A number between  0 and 9"
user = gets().to_i

if user < rand
  puts "Less"
elsif user > rand
  puts "More"
else
  puts "Equal equal!!"
end

puts "The number was #{rand}"

Well that's day one of Ruby done. I look forward to tomorrow!