Monday, 19 November 2012

Step builder pattern on youtube

Djorgje Popovic just published an article on the Step builder pattern which includes a nice video explaining the how and the why of this design.

So thanks to Djorgje and enjoy the video.



Thursday, 15 November 2012

Chain of responsibility using Spring @Autowired List

There is a way in Spring 3.1 to auto populate a typed List which is very handy when you want to push a bit the decoupling and the cleaning in your code.

To show you how it works, I will implement a simple chain of responsibility that will take care of printing some greetings for a passed User.

Let start from the (only) domain class we have, the User:
package com.marco.springchain;
public class User {

        private final String name;
        private final char gender;

        public User(String name, char gender) {
                super();
                this.name = name;
                this.gender = gender;
        }

        public String getName() {
                return name;
        }

        public char getGender() {
                return gender;
        }
}



Then we create an interface that defines the type for our command objects to be used in our chain:

package com.marco.springchain;
public interface Printer {

        void print(User user);
}



This is the generic class (the template) for a Printer implementation.
The org.springframework.core.Ordered is used to tell the AnnotationAwareOrderComparator how we want our List to be ordered.
You don't need to implement the Ordered interface and to override the getOrder method if you don't need your chain to have an execution order.
Also notice that this abstract class return Ordered.LOWEST_PRECEDENCE, this because I want some Printer commands to just run at the end of the chain and I don't care about their execution order (everything will be clearer after, I promise!).

package com.marco.springchain;
import org.springframework.core.Ordered;
public abstract class GenericPrinter implements Printer, Ordered {

        public void print(User user) {
                String prefix = "Mr";
                if (user.getGender() == 'F') {
                        prefix = "Mrs";
                }
                System.out.println(getGreeting() + " " + prefix + " " + user.getName());
        }

        protected abstract String getGreeting();

        public int getOrder() {
                return Ordered.LOWEST_PRECEDENCE;
        }
}



This is our first real Printer command. I want this to have absolute precedence in the chain, hence the order is  HIGHEST_PRECEDENCE.

package com.marco.springchain;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class HelloPrinter extends GenericPrinter {

        private static final String GREETING = "Hello";

        @Override
        protected String getGreeting() {
                return GREETING;
        }

        @Override
        public int getOrder() {
                return Ordered.HIGHEST_PRECEDENCE;
        }
}




WelcomePrinter to be executed as first command (After High precedence ones ).

package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class WelcomePrinter extends GenericPrinter {

        private static final String GREETING = "Welcome to the autowired chain";

        @Override
        protected String getGreeting() {
                return GREETING;
        }

        @Override
        public int getOrder() {
                return 1;
        }
}



GoodbyePrinter to be executed as second command

package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class GoodbyePrinter extends GenericPrinter {

        private static final String GREETING = "Goodbye";

        @Override
        protected String getGreeting() {
                return GREETING;
        }

        @Override
        public int getOrder() {
                return 2;
        }
}




These 2 commands need to be executed after the others, but I don't care about their specific order, so I will not override the getOrder method, leaving the GenericPrinter to return Ordered.LOWEST_PRECEDENCE for both.

package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningMemoryPrinter extends GenericPrinter {

        private static final String GREETING = "Cleaning memory after";

        @Override
        protected String getGreeting() {
                return GREETING;
        }
}



package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningSpacePrinter extends GenericPrinter {

        private static final String GREETING = "Cleaning space after";

        @Override
        protected String getGreeting() {
                return GREETING;
        }
}




This is the chain context.
Spring will scan (see the spring-config.xml) the package specified in the config file, it will see the typed (List<Printer>) list, and it will populate the list with an instance of any @Component that implements the type Printer.
To order the List we use AnnotationAwareOrderComparator.INSTANCE that use the getOrder method to re-order the List ( the object with the lowest value has highest priority (somewhat analogous to Servlet "load-on-startup" values)).

package com.marco.springchain;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
@Component
public class PrinterChain {

        @Autowired
        private List<Printer> printers;

        @PostConstruct
        public void init() {
                Collections.sort(printers, AnnotationAwareOrderComparator.INSTANCE);
        }

        public void introduceUser(User user) {
                for (Printer printer : printers) {
                        printer.print(user);
                }
        }
}



The spring-config.xml in the src/main/resources.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd" default-lazy-init="true">

    <context:component-scan base-package="com.marco.springchain"/>
</beans>



Finally, a main class to test our chain.

package com.marco.springchain;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {

        public static void main(String[] args) {
                ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
                PrinterChain printerChain = (PrinterChain) context.getBean("printerChain");
                printerChain.introduceUser(new User("Marco Castigliego", 'M'));
                printerChain.introduceUser(new User("Julie Marot", 'F'));
        }
}



OUTPUT:


Hello Mr Marco Castigliego
Welcome to the autowired chain Mr Marco Castigliego
Goodbye Mr Marco Castigliego
Cleaning space after Mr Marco Castigliego
Cleaning memory after Mr Marco Castigliego
Hello Mrs Julie Marot
Welcome to the autowired chain Mrs Julie Marot
Goodbye Mrs Julie Marot
Cleaning space after Mrs Julie Marot
Cleaning memory after Mrs Julie Marot


Hope you enjoyed the example. see ya.



Thursday, 8 November 2012

JBoss HornetQ for Kids, Parents and Grandparents – Chapter 1


It’s now almost 4 years that I’m working with HornetQ and I think it’s time to share part of what I learnt so far.

The main purpose of this post is not to rewrite the official documentation, but it’s to clarify, in simple ways, the concepts we use most here in PaddyPower .

What is HornetQ


HornetQ is a JMS implementation. JMS is a message oriented middle-ware API to exchange information between producers and consumers in an asynchronous way.
HornetQ is one of the numerous framework out there that implement the JMS API.

Configuration


All the HornetQ configuration we care about is in 1 folder. How beautiful is that?! The folder is hornetq (or hornetq.sar dipending on the jboss version you are using) and you can find it in your jboss profile deploy folder.
In this folder we have up to 7 xml configuration files. We really care only about 2:
hornetq-jms.xml and hornetq-configuration.xml.

hornetq-jms.xml

This is where you want to define your JNDI names for queues, topics and connection factories.
By default all the Connection factories, the dead letter and the expiry Queue are already configured.
What you need to add is only the queues or topics that your application needs to use.
For example:
<queue name="phaseQueueFromEngine">
     <entry name="/queue/phaseQueueFromEngine"/>
</queue>
the entry name is the JNDI name used by your producer and consumer to discover the queue.

hornetq-configuration.xml

This is where you want to define acceptors, connectors, bridges and other cool stuff.

Understanding Connectors & Acceptors
Ok, this can be tricky, so I’ll try to be simple and essential.
HornetQ run in a server (JBoss for example) or as standalone application.
In any of the above cases, HornetQ works by communicating with his own server, the HornetQ server.
In order to communicate with it, we have to tell how we connect to and what we accept as connection.
  • Acceptors define which type of connection are accepted by the HornetQ Server.
  • Connectors define how to connect to the HornetQ server.
Luckily, only 2 kind of connectors and acceptors are possible, in-vm and netty.
in-vm is used when the producer and the consumer lives in the same virtual machine.
Example:
<acceptor name="in-vm">
        <factory-class>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</factory-class>
</acceptor>
<connector name="in-vm">
       <factory-class>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</factory-class>
</connector>
netty must be used when the producer and the consumer lives in different virtual machines.
Example:
Producer/Consumer in the same machine:
<acceptor name="netty">
         <factory-class>org.hornetq.integration.transports.netty.NettyAcceptorFactory</factory-class>
         <param key="host"  value="${host:localhost}"/>
         <param key="port"  value="${port:5445}"/>
      </acceptor>
<connector name=”netty”>
<factory-class>org.hornetq.integration.transports.netty.NettyConnectorFactory</factory-class>
<param key=”host”  value=”${host:localhost}”/>
<param key=”port”  value=”${port:5445}”/>
</connector>
Producer/Consumer in different machines:
Consumer Box
<acceptor name=”netty-external-acceptor”>
<factory-class>org.hornetq.integration.transports.netty.NettyAcceptorFactory</factory-class>
<param key=”host”  value=”172.x.x.62″/>
<param key=”port”  value=”5445″/>
</acceptor>
Producer Box
<connector name="remote-engine-connector">
         <factory-class> org.hornetq.integration.transports.netty.NettyConnectorFactory</factory-class>
         <param key="host" value="172.x.x.62"/>
         <param key="port" value="5445"/>
      </connector>
So far so good.
Pay attention when you configure acceptors and connectors because in order to communicate properly they have to be the same kind with the same host and port.
netty acceptor with netty connector (same host and port ) GOOD
in-vm acceptor with in-vm connector GOOD
in-vm acceptor with netty connector BAD
netty acceptor port 5445 with netty connector 5446 BAD
netty acceptor host 172.x.x.60 with netty connector 172.x.x.62 BAD
Understanding Bridges
Another feature I widely used is the bridge.
If you have a producer living in the box 172.x.x.60 and the consumer sitting in the box 172.x.x.62 you need to connect them and you do this configuring a bridge in our beloved configuration file hornetq-configuration.xml
Example :
<bridge name=”from60to62Bridge”>
<queue-name>jms.queue.phaseQueueToEngine</queue-name>
<forwarding-address>jms.queue.phaseQueueFromInput</forwarding-address>
<reconnect-attempts>-1</reconnect-attempts>
<connector-ref connector-name=”remote-engine-connector”/>
</bridge>
Yes, you use the connector to specify where to connect to the other hornetQ server. Easy!
I hope this will clarify a couple of aspects and it will help to understand better the sometime scary Hornetq configuration.
Coming soon.. HornetQ for Kids, Parents and Grandparents – Chapter 2: the magic of address-settings

JUnit4 Parameterized and Theories


Parameterized

I always relied on TestNG to pass parameters to test methods in order to give a bit of flexibility to my tests or suites.
However, the same flexibility can be achieved using JUnit4.
To use it it’s simple:

package com.marco.test;
import java.util.Arrays;
import java.util.Collection;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ParameterizedTest {
@Parameters
public static Collection data() {
return Arrays.asList(new Object[][] {
/* Sport Nation year totWinners */
{ “basket”, “usa”, 2002, 5, },
{ “soccer”, “argentina”, 2003, 2 },
{ “tennis”, “spain”, 2004, 10 },
{ “chess”, “ireland”, 2005, 0 },
{ “eatingbananas”, “italy”, 2006, 20 }
});
}
private final String sport;
private final String nation;
private final int year;
private final int totWinners;
public ParameterizedTest(String sport, String nation, int year, int totWinners) {
this.sport = sport;
this.nation = nation;
this.year = year;
this.totWinners = totWinners;
}
@Test
public void test() {
Assert.assertTrue(isDataCorrect(sport, nation, year, totWinners));
}
private boolean isDataCorrect(String sport2, String nation2, int year2, int totWinners2) {
return true;
}
}
JUnit will create an instance of the ParameterizedTest class and run the testCombination() method (or any method marked as @Test) for each row defined in the static collection.

Theories

This another interesting feature from JUnit4 that I like.  You use Theories in JUnit 4 to test combinations of inputs using the same test method:

package com.marco.test;
import static org.hamcrest.CoreMatchers.is;
import java.math.BigDecimal;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
@RunWith(Theories.class)
public class TheoryTest {
@DataPoint
public static int MARKET_FIRST_GOALSCORERE_ID = 2007;
@DataPoint
public static int MARKET_WDW_ID = 2008;
@DataPoint
public static BigDecimal PRICE_BD = new BigDecimal(6664.0);
@DataPoint
public static double PRICE_1 = 0.01;
@DataPoint
public static double PRICE_2 = 100.0;
@DataPoint
public static double PRICE_3 = 13999.99;
@Theory
public void lowTaxRateIsNineteenPercent(int market_id, double price) {
Assume.assumeThat(market_id, is(2008));
Assume.assumeThat(price, is(100.0));
// run your test
Assert.assertThat(price, is(100.0));
}
@Theory
public void highTaxRateIsNineteenPercent(int market_id, double price) {
Assume.assumeThat(market_id, is(2007));
Assume.assumeThat(price, is(13999.99));
Assert.assertThat(price, is(13999.99));
}
@Theory
public void highTaxRateIsNineteenPercent(int market_id, BigDecimal price) {
Assume.assumeThat(market_id, is(2007));
Assert.assertThat(price, is(BigDecimal.valueOf(6664)));
}
}
This time you need to mark the test class as @RunWith(Theories.class) and use @DataPoint to define properties that you want to test.
JUnit will call the methods market as @Theory using all the possible combinations based on the DataPoint provided and the type of the variable. PRICE_BD DataPoint will be used only in the last method, the only one accepting BigDecimal in its method parameters.
Only parameters that satisfy the Assume.assumeThat() condition will make through the asser test. The combinations that don’t satisfy the Assume.assumeThat() condition will be ignored silently.

Have fun...

Monday, 8 October 2012

Step Builder Pattern - WIKI-Definition


Definition


The step builder pattern is an extension of the builder pattern that fully guides the user through the creation of the object with no chances of confusion. [1]

Contents


The intent of the Step Builder design pattern is to separate the construction of a complex object from its representation by creating defined steps and exposing to the user only selected methods per time.

Advantages of using the Step Builder over the Builder pattern

    • The user will see only one or few selected methods per time during the Object creation.
    • Based on the user choice different paths can be taken during the Object creation.
    • The final build step will be available only at the end, after all mandatory steps are completed, returning an Object in a consistent state.
    • The user experience will be greatly improved by the fact that he will only see the next step methods available.

    Examples

    Java

     /** "Product" */
     class UserConfiguration {
        private final String name;
        private final String filePath;
        private ServerDetails serverDetails;
     
        public UserConfiguration(String name, String filePath){
           this.name = name;
           this.filePath = filePath;
        }
        public void setServerDetails(ServerDetails serverDetails)     { this.serverDetails = serverDetails; }
     
        //all the getters
        ...
     }
     
    class ServerDetails {
        private final String host;
        private String user;
        private String password;
     
        public ServerDetails(String host){
           this.host = host;
        }
        public void setUser(String user)     { this.user = user; }
        public void setPassword(String password)     { this.password = password; }
     
        //all the getters and isLocalhost() method
        ...
     }
     
     
     
     /** "Step Builder" */
    public class UserConfigurationBuilder {
       public static NameStep newBuilder() {
          return new Steps();
       }  
       private UserConfigurationBuilder() {}
     
       public static interface NameStep {
          /**
           * @param name unique identifier for this User Configuration
           * @return FileStep
           */
          FileStep name(String name);
       }
     
       public static interface FileStep {
          /** 
           * @param filePath absolute path of where the User Configuration exists.
           * @return ServerStep
           */
          ServerStep filePath(String name);
       }
     
       public static interface ServerStep {
          /**
           * The hostname of the server where the User Configuration file is stored will be set to "localhost".
           * @return BuildStep
           */
          public BuildStep onLocalhost();
     
          /**
           * The hostname of the server where the User Configuration file is stored.
           * @return CredentialsStep
           */
          public CredentialsStep onRemotehost(String host);
       }
     
       public static interface CredentialsStep {
          /**
            * Username required to connect to remote machine
            * Password required to connect to remote machine
            * @return BuildStep
            */
           public BuildStep credentials(String user, String password);
       }
     
       public static interface BuildStep {
          /** 
           * @return an instance of a UserConfiguration based on the parameters passed during the creation.
           */
          public Profile build();
       }
     
       private static class Steps implements NameStep, FileStep, ServerStep, CredentialsStep, BuildStep {
     
          private String name;
          private String host;
          private String user;
          private String password;
          private String filePath;
     
          @Override
          public FileStep name(String name) {
             this.name = name;
            return this;
          }
     
          @Override
          public ServerStep filePath(String filePath) {
             this.filePath = filePath;
             return this;
          }
     
          @Override
          public BuildStep onLocalhost() {
             this.host = "localhost";
             return this;
          }
     
          @Override
          public CredentialsStep onRemotehost(String host) {
             this.host = host;
             return this;
          }
     
          @Override
          public BuildStep credentials(String user, String password) {
             this.user = user;
             this.password = password;
             return this;
          }
     
          @Override
          public UserConfiguration build() {
             UserConfiguration userConfiguration = new UserConfiguration(name, filePath);
             ServerDetails serverDetails = new ServerDetails(host);
             if (!serverDetails.isLocalhost()) {
                serverDetails.setUser(user);
                serverDetails.setPassword(password);
             }
             userConfiguration.setServerDetails(serverDetails);
             return userConfiguration;
          }
       }
    }
     
     
     /** A user creating a configuration. */
     class StepBuilderExample {
        public static void main(String[] args) {
            // A local user configuration
            UserConfiguration localUserConfiguration = UserConfigurationBuilder
                                                  .newBuilder()
                                                  .name("aLocalConfiguration")
                                                  .filePath("/opt/conf/user.txt")
                                                  .onLocalhost()
                                                  .build();  
            // A remote user configuration
            UserConfiguration remoteUserConfiguration = UserConfigurationBuilder
                                                  .newBuilder()
                                                  .name("aRemoteConfiguration")
                                                  .filePath("/opt/conf/user.txt")
                                                  .onRemotehost("172.x.x.x")
                                                  .credentials("user","password")
                                                  .build();  
        }
     }

    C#

    namespace StepBuilder
    {
        class Program
        {
            static void Main(string[] args)
            {
    
    
    
             UserConfiguration localUserConfiguration = UserConfigurationBuilder                        .CreateNewBuilder()
                            .SetName(@"aLocalConfiguration")
                            .SetFilePath(@"/opt/conf/user.txt")
                            .OnLocalhost()
                            .Build();
    UserConfiguration remoteUserConfiguration = UserConfigurationBuilder .CreateNewBuilder() .SetName(@"aRemoteConfiguration") .SetFilePath(@"/opt/conf/user.txt") .OnRemoteHost("172.x.x.x") .SetCredentials("user", "password") .Build(); } } public class UserConfiguration { public UserConfiguration(string name, string filePath) { Name = name; FilePath = filePath; } private ServerDetails _serverDetails; public string Name { get; private set; } public string FilePath { get; private set; } public void SetServerDetails(ServerDetails serverDetails) { _serverDetails = serverDetails; } } public class ServerDetails { public ServerDetails(string host) { Host = host; } public string Host { get; private set; } public string User { get; set; } public string Password { get; set; } public bool IsLocalhost { get { return Host == "localhost"; } } } public class UserConfigurationBuilder { public static INameStep CreateNewBuilder() { return new Steps(); } private UserConfigurationBuilder() { } public interface INameStep { /// <param name="name">Unique identifier for this User Configuration</param> IFileStep SetName(string name); } public interface IFileStep { /// <param name="filePath">Absolute path of where the User Configuration exists</param> IServerStep SetFilePath(string filePath); } public interface IServerStep { /// <summary> /// The hostname of the server where the User Configuration file is store will be set to "localhost". /// </summary> IBuildStep OnLocalhost(); /// <param name="host">The hostname of the server where the User Configuration is stored</param> ICredentialsStep OnRemoteHost(string host); } public interface IBuildStep { /// <summary> /// Returns an instance of a UserConfiguration based on the parameters passed during the creation. /// </summary> UserConfiguration Build(); } public interface ICredentialsStep { /// <param name="user">Username required to connect to remote machine</param> /// /// <param name="password">Password required to connect to remote machine</param> IBuildStep SetCredentials(string user, string password); } private class Steps : INameStep, IFileStep, IServerStep, IBuildStep, ICredentialsStep { private string _name; private string _host; private string _user; private string _password; private string _filePath; public IFileStep SetName(string name) { _name = name; return this; } public IServerStep SetFilePath(string filePath) { _filePath = filePath; return this; } public IBuildStep OnLocalhost() { _host = "localhost"; return this; } public ICredentialsStep OnRemoteHost(string host) { _host = host; return this; } public UserConfiguration Build() { UserConfiguration userConfiguration = new UserConfiguration(_name, _filePath); ServerDetails serverDetails = new ServerDetails(_host); if (!serverDetails.IsLocalhost) { serverDetails.Password = _password; serverDetails.User = _user; } userConfiguration.SetServerDetails(serverDetails); return userConfiguration; } public IBuildStep SetCredentials(string user, string password) { _user = user; _password = password; return this; } } } }