Friday, 12 March 2010

Codility.com Demo Test

I like online programming challenges like this demo offered by Codility, it reassures me that I might still be able to think, check it out here:

Sample Test

This was my solution:

private static int equi(int[] A) {

  if (null == A) {
    return -1;
  }

  int size = A.length;

  if (size == 0) {
    return -1;
  }

  long runningSum = 0;
  long[] runningSums = new long[size];

  for (int i = 0; i < size; i++) {
    runningSum += A[i];
    runningSums[i] = runningSum;      
  }

  for (int i = 0; i < size; i++) {
    long lhsSum = runningSums[i] - A[i];
    long rhsSum = runningSum - runningSums[i];

    if(lhsSum == rhsSum) {
      return i;
    }
  }

  return -1;
}

Monday, 1 March 2010

Maven, Jython & Glassfish Example

I keep meaning to get stuck in and learn some Python, and especially make use of some Jython. After coming across this post about using Jython with Glassfish, I thought I'd give it a go myself.

This post is about creating a Maven WAR project making use of Python scripts running on embedded Jython on an embedded Glassfish v3 instance.

Here is the projects POM:

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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.adrianwalker.maven.skeleton.war.jython.glassfish</groupId>
  <artifactId>maven-war-jython-glassfish-example</artifactId>
  <packaging>war</packaging>
  <version>0.1.0</version>
  <name>Maven WAR-Jython-Glassfish Example</name>

  <description>
    Example project for creating a Jython WAR running on Glassfish.
    
    Usage: mvn clean install embedded-glassfish:run
  </description>

  <url>http://www.adrianwalker.org</url>

  <organization>
    <name>adrianwalker.org</name>
    <url>http://www.adrianwalker.org</url>
  </organization>

  <developers>
    <developer>
      <name>Adrian Walker</name>
      <email>ady.walker@gmail.com</email>
      <organization>adrianwalker.org</organization>
      <organizationUrl>http://www.adrianwalker.org</organizationUrl>
    </developer>
  </developers>

  <repositories>
    <!--
    Use project lib directory as repository
    -->
    <repository>
      <id>project</id>
      <url>file://${basedir}/lib</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>java.net</id>
      <url>http://download.java.net/maven/glassfish</url>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <finalName>example</finalName>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <webResources>
            <webResource>
              <directory>${basedir}/src/main/python</directory>
              <includes>
                <include>**/*.py</include>
              </includes>
            </webResource>
          </webResources>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.glassfish</groupId>
        <artifactId>maven-embedded-glassfish-plugin</artifactId>
        <configuration>
          <port>8080</port>
          <app>${project.build.directory}/${build.finalName}.war</app>
          <instanceRoot>${project.build.directory}/glassfish</instanceRoot>
          <contextRoot>${build.finalName}</contextRoot>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <!--
    Jython version 2.5.1 and it's standard library
    are included in the project lib directory
    -->
    <dependency>
      <groupId>org.python</groupId>
      <artifactId>jython</artifactId>
      <version>2.5.1</version>
    </dependency>
    <dependency>
      <groupId>org.python</groupId>
      <artifactId>jython-lib</artifactId>
      <version>2.5.1</version>
    </dependency>
  </dependencies>
</project>

I couldn't find the latest version (2.5.1) of the Jython JAR in any Maven repository, so I have included it with the project source code in the lib directory. Also, I wanted the Jython instance to be completely self contained, so instead of referencing an install external to the project, I have JAR'ed up the standard library and included it in the project as lib/jython-lib-2.5.1.jar.

The project uses the embedded Glassfish v3 plugin to quickly start a basic configuration Glassfish server.

PyServlet, distributed with Jython is used to create Java Servlets using Jython source files. It is configured in the project's web.xml:

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="Message" version="2.5">

  <servlet>
    <servlet-name>PyServlet</servlet-name>
    <servlet-class>org.python.util.PyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>PyServlet</servlet-name>
    <url-pattern>*.py</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>Calendar.py</welcome-file>
  </welcome-file-list>
</web-app>

Python code to create a Java servlet which uses the Python calendar library:

Calendar.py

import time
import calendar
from javax.servlet.http import HttpServlet

class Calendar (HttpServlet):
  def doGet(self, request, response):
    response.setContentType ("text/html")
    out = response.getWriter()

    out.println ("""
    <html>
      <head>
        <title>Calendar</title>
      </head>
      <body>
        <h1>Calendar</h1>
        <pre>%s</pre>
      </body>
    </html>
    """ % calendar.calendar(time.localtime()[0]))

Run the project with 'mvn clean install embedded-glassfish:run' and point your brower at http://localhost:8080/example/.

Source Code

Sunday, 28 February 2010

ColdFusion Head First Design Patterns: Observer

Continuing in this design patterns series taken from Head First Design Patterns, is a ColdFusion implementation of the Observer Pattern.

Interfaces

Subject.cfc

<cfinterface>
  <cffunction access="public" returntype="void" name="registerObserver">
    <cfargument required="true" type="Observer" name="o">
  </cffunction>

  <cffunction access="public" returntype="void" name="removeObserver">
    <cfargument required="true" type="Observer" name="o">
  </cffunction>
  
  <cffunction access="public" returntype="void" name="notifyObservers">
  </cffunction>
</cfinterface>

Observer.cfc

<cfinterface>
  <cffunction access="public" returntype="void" name="update">
    <cfargument required="true" type="numeric" name="temperature">
    <cfargument required="true" type="numeric" name="humidity">
    <cfargument required="true" type="numeric" name="pressure">        
  </cffunction>
</cfinterface>

DisplayElement.cfc

<cfinterface>
  <cffunction access="public" returntype="void" name="display">
  </cffunction>
</cfinterface>

Subject Implementation

WeatherData.cfc

<cfcomponent implements="Subject" output="false">

  <cffunction access="public" returntype="Subject" name="init">
    <cfset VARIABLES.observers = arrayNew(1)>
    
    <cfreturn THIS>
  </cffunction> 

  <cffunction access="public" returntype="void" name="registerObserver">
    <cfargument required="yes" type="Observer" name="o" />
    
    <cfset arrayAppend(VARIABLES.observers, ARGUMENTS.o)>
  </cffunction>

  <cffunction access="public" returntype="void" name="removeObserver">
    <cfargument required="yes" type="Observer" name="o" />
    
    <cfset arrayDelete(VARIABLES.observers, ARGUMENTS.o)>    
  </cffunction>

  <cffunction access="public" returntype="void" name="notifyObservers">
    <cfset var LOCAL = {}>
  
    <cfloop index="LOCAL.o" array="#VARIABLES.observers#">
      <cfset LOCAL.o.update(VARIABLES.temperature, VARIABLES.humidity, VARIABLES.pressure)>
    </cfloop>
  </cffunction>
  
  <cffunction access="public" returntype="void" name="measurementsChanged">
    <cfset notifyObservers()>
  </cffunction>
  
  <cffunction access="public" returntype="void" name="setMeasurements">
    <cfargument required="yes" type="numeric" name="temperature" />
    <cfargument required="yes" type="numeric" name="humidity" />
    <cfargument required="yes" type="numeric" name="pressure" />
    
    <cfset VARIABLES.temperature = ARGUMENTS.temperature>
    <cfset VARIABLES.humidity = ARGUMENTS.humidity>
    <cfset VARIABLES.pressure = ARGUMENTS.pressure>
    <cfset measurementsChanged()>
  </cffunction>
</cfcomponent>

Display Elements

CurrentConditionsDisplay.cfc

<cfcomponent implements="Observer, DisplayElement" output="true">

  <cffunction access="public" returntype="CurrentConditionsDisplay" name="init">
    <cfargument required="true" type="WeatherData" name="weatherData">
    
    <cfset VARIABLES.weatherData = ARGUMENTS.weatherData>
    <cfset VARIABLES.weatherData.registerObserver(THIS)>
    
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="void" name="update">
    <cfargument required="true" type="numeric" name="temperature">
    <cfargument required="true" type="numeric" name="humidity">
    <cfargument required="true" type="numeric" name="pressure">
    
    <cfset VARIABLES.temperature = ARGUMENTS.temperature>
    <cfset VARIABLES.humidity = ARGUMENTS.humidity>
    <cfset display()>
  </cffunction>

  <cffunction access="public" returntype="void" name="display">
    <cfoutput>
      Current conditions: #VARIABLES.temperature#F degrees and #VARIABLES.humidity#% humidity
      <br />
    </cfoutput>
  </cffunction>
</cfcomponent>

HeatIndexDisplay.cfc

<cfcomponent implements="Observer, DisplayElement" output="true">

  <cffunction access="public" returntype="HeatIndexDisplay" name="init">
    <cfargument required="true" type="WeatherData" name="weatherData">
    
    <cfset VARIABLES.weatherData = ARGUMENTS.weatherData>
    <cfset VARIABLES.weatherData.registerObserver(THIS)>
    
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="void" name="update">
    <cfargument required="true" type="numeric" name="temperature">
    <cfargument required="true" type="numeric" name="humidity">
    <cfargument required="true" type="numeric" name="pressure">
    
    <cfset VARIABLES.temperature = ARGUMENTS.temperature>
    <cfset VARIABLES.humidity = ARGUMENTS.humidity>
    <cfset VARIABLES.heatIndex = computeHeatIndex(VARIABLES.temperature, VARIABLES.humidity)>
    <cfset display()>
  </cffunction>

  <cffunction access="public" returntype="void" name="display">
    <cfoutput>
      Heat index is #VARIABLES.heatIndex#
      <br />
    </cfoutput>
  </cffunction>

  <cffunction access="private" returntype="numeric" name="computeHeatIndex">
    <cfargument required="true" type="numeric" name="t">
    <cfargument required="true" type="numeric" name="rh">

    <cfset var LOCAL = {}>
    <cfset LOCAL.index = ((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) +
            (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) +
            (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +
            (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 *  
            (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) +
            (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +     
            0.000000000843296 * (t * t * rh * rh * rh)) -
            (0.0000000000481975 * (t * t * t * rh * rh * rh)))>
  
    <cfreturn LOCAL.index>
  </cffunction> 
</cfcomponent>

Test Page

WeatherStation.cfm

<cfset weatherData = createObject("component", "WeatherData").init()>

<cfset currentDisplay = createObject("component", "CurrentConditionsDisplay").init(weatherData)>
<cfset heatDisplay = createObject("component", "HeatIndexDisplay").init(weatherData)>

<cfset weatherData.setMeasurements(80, 65, 30.4)>
<cfset weatherData.setMeasurements(82, 70, 29.2)>
<cfset weatherData.setMeasurements(78, 90, 29.2)>

Source Code

Saturday, 27 February 2010

Maven GWT WAR & Glassfish skeleton project

Another skeleton project implementing the same functionality as this previous post, a Google Web Toolkit front-end, with an embedded Derby database, accessed using the Java Persistence API; but this time running on an embedded Glassfish 3 instance and making use of EJB3.1 features.

Here is the projects POM:

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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.adrianwalker.maven.skeleton.war.gwt.glassfish</groupId>
  <artifactId>maven-war-gwt-glassfish-skeleton</artifactId>
  <packaging>war</packaging>
  <version>0.1.0</version>
  <name>Maven WAR-GWT-Glassfish Skeleton</name>

  <description>
    Skeleton project for creating a GWT WAR running on Glassfish, with a Derby
    database accessed through JPA.

    Usage: mvn clean install embedded-glassfish:run
  </description>

  <url>http://www.adrianwalker.org</url>

  <organization>
    <name>adrianwalker.org</name>
    <url>http://www.adrianwalker.org</url>
  </organization>

  <developers>
    <developer>
      <name>Adrian Walker</name>
      <email>ady.walker@gmail.com</email>
      <organization>adrianwalker.org</organization>
      <organizationUrl>http://www.adrianwalker.org</organizationUrl>
    </developer>
  </developers>

  <repositories>
    <repository>
      <id>java.net</id>
      <url>http://download.java.net/maven/2</url>
    </repository>

    <repository>
      <id>codehaus.org</id>
      <url>http://repository.codehaus.org</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>java.net</id>
      <url>http://download.java.net/maven/glassfish</url>
    </pluginRepository>
  </pluginRepositories>

  <properties>
    <gwt.version>2.0.2</gwt.version>
  </properties>

  <build>
    <outputDirectory>war/WEB-INF/classes</outputDirectory>

    <finalName>message</finalName>

    <resources>
      <resource>
        <directory>${basedir}/src/main/resources</directory>
        <includes>
          <include>META-INF/persistence.xml</include>
        </includes>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <configuration>
          <filesets>
            <fileset>
              <directory>war</directory>
              <includes>
                <include>**/*</include>
              </includes>
            </fileset>
          </filesets>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>gwt-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.glassfish</groupId>
        <artifactId>maven-embedded-glassfish-plugin</artifactId>
        <configuration>
          <app>${project.build.directory}/${build.finalName}.war</app>
          <instanceRoot>${project.build.directory}/glassfish</instanceRoot>
          <contextRoot>${build.finalName}</contextRoot>
          <configFile>${basedir}/src/test/resources/config/domain.xml</configFile>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.glassfish.extras</groupId>
      <artifactId>glassfish-embedded-all</artifactId>
      <version>3.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>com.google.gwt</groupId>
      <artifactId>gwt-servlet</artifactId>
      <version>${gwt.version}</version>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>com.google.gwt</groupId>
      <artifactId>gwt-user</artifactId>
      <version>${gwt.version}</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>cobertura-maven-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jxr-maven-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>findbugs-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </reporting>
</project>

The embedded Glassfish server is configured using a domain.xml taken from a fresh install of Glassfish 3, located \src\test\resources\config\domain.xml and referenced from the embedded Glassfish Maven plugin configuration element in the pom.xml

The default domain.xml has been amended to include jdbc-resource and jdbc-datasource entries for the web applications database. The domain.xml below shows the amendments, with the rest of the file removed for brevity:

domain.xml

<domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" version="10.0">

  ...

  <resources>

    ...

    <jdbc-resource pool-name="MessagePool" jndi-name="jdbc/message" />

    ...

    <jdbc-connection-pool name="MessagePool" datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource" res-type="javax.sql.DataSource">
      <property name="databaseName" value="target/database/message" />
      <property name="connectionAttributes" value=";create=true" />
    </jdbc-connection-pool>
  </resources>
  <servers>
    <server name="server" config-ref="server-config">

      ...

      <resource-ref ref="jdbc/message" />
    </server>
  </servers>

  ...

</domain>

The configured datasource is referenced in the projects persistence.xml, which uses EclipseLink to implement the JPA.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="messagePersistenceUnit" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/message</jta-data-source>
    <class>org.adrianwalker.maven.skeleton.jpa.entity.MessageEntity</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="eclipselink.ddl-generation" value="create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

Run the project with 'mvn clean install embedded-glassfish:run' and point your brower at http://localhost:8080/message/.

Source Code

Monday, 22 February 2010

ColdFusion Head First Design Patterns: Singleton

Everyone's favorite, The Singleton Pattern, is probably the most overused and least well implemented design pattern.

There are at least seven different variations on the singleton implementation in Java, some are detailed in Head First Design Patterns, some are documented in Joshua Bloch's awesome book Effective Java, and some I've found along the way on the web.

Not all of the variations can be implemented in ColdFusion, but lets list them and pick the best one to code in CFML.

None of them can be implemented in ColdFusion, but lets list them and see why.

Lazily created Singleton with static factory method

Introduced as the first singleton example in Head First Design Patterns. It isn't thread safe.

public final class Singleton {

  private static Singleton instance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (null == instance) {
      instance = new Singleton();
    }

    return instance;
  }
}

Synchronized lazily created Singleton with static factory method

Introduced as the second example in Head First, it is thread safe but uses a computationally expensive synchronized method.

public final class Singleton {

  private static Singleton instance;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (null == instance) {
      instance = new Singleton();
    }

    return instance;
  }
}

Eagerly created Singleton with static factory method

Detailed as an alternative to synchronizing the getInstance() method in Head First, and presented as a possible implementation in Joshua Bloch's Effective Java. Bloch goes on to note that this implementation and the following implementation can not be made serializable by just adding implements Serializable. All instance fields would need to be declared transient and a readResolve() method provided.

public final class Singleton {

  private static final Singleton INSTANCE = new Singleton();

  private Singleton() {
  }

  public static Singleton getInstance() {
    return INSTANCE;
  }
}

Eagerly created Singleton with public final field

Presented by Bloch as an alternative to the above implementation, it's main advantage is that the class definition clearly shows it is a singleton.

public final class Singleton {

public static final Singleton INSTANCE = new Singleton();

  private Singleton() {
  }
}

Double checked locking

The third and final example in Head First, only synchronizes the first time through the getInstance() method. This implementation of the singleton makes use of the volatile keyword. In Java versions 1.4 and earlier, volatile could allow improper synchonization, this implementation is not portable to older JVMs.

public final class Singleton {

  private volatile static Singleton instance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (null == instance) {
      synchronized (Singleton.class) {
        if (null == instance) {
          instance = new Singleton();
        }
      }
    }

    return instance;
  }
}

The solution of Bill Pugh

The solution of Bill Pugh uses a nested class to be as lazy as possible, is thread safe without using synchronized or volatile, and is usable with all JVM versions.

public final class Singleton {

  private Singleton() {
  }

  private static class SingletonHolder {

    private static final Singleton INSTANCE = new Singleton();
  }

  public static Singleton getInstance() {
    return SingletonHolder.INSTANCE;
  }
}

Enum Type

Since version 1.5, Java has had support for enums. The final implementation in Effective Java uses an enumerated type with one element. This is equivalent to the public final field implementation but takes care of serialization automatically, and guarantees only a single instance.

public enum Singleton {

  INSTANCE;
}

From Effective Java:

"a single-element enum type is the best way to implement a singleton."

ColdFusion

ColdFusion doesn't support enum types or nested CFCs, so those are out straight away.

Lazily created Singleton with factory method

A lazily created Singleton fails to be initialized because the component can't see its own private constructor.

LazyFactoryMethod/Singleton.cfc

<cfcomponent output="false" >

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="Singleton" name="getInstance">
    <cfif NOT isDefined("VARIABLES.INSTANCE")>
      <cfset VARIABLES.INSTANCE = createObject("component", "Singleton").init()>
    </cfif>
  
    <cfreturn VARIABLES.INSTANCE>  
  </cffunction>
  
</cfcomponent>

Eagerly created Singleton with factory method

An eagerly created Singleton with a factory method goes in to a self referential loop and fills up the stack.

EagerFactoryMethod/Singleton.cfc

<cfcomponent output="false" >

  <cfset VARIABLES.INSTANCE = createObject("component", "Singleton").init()>

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="Singleton" name="getInstance">
    <cfreturn VARIABLES.INSTANCE>  
  </cffunction>
  
</cfcomponent>

Eagerly created Singleton with a public field

Same as with the previous eagerly created Singleton, a java.lang.StackOverflowError is thrown on instantiation.

EagerField/Singleton.cfc

<cfcomponent output="false" >

  <cfset THIS.INSTANCE = createObject("component", "Singleton").init()>

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

</cfcomponent>

So ColdFusion can't create real singletons, how bad does that suck?

Source Code

Thursday, 18 February 2010

ColdFusion Head First Design Patterns: Strategy

Following on from my previous post on a ColdFusion implementation of the Head First Design Patterns web MVC Pattern is a ColdFusion implementation of the Strategy Pattern.

The Strategy Pattern is probably the most useful pattern, to quote the Head First book:

"The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it."

Abstract Duck

Duck.cfc

<cfcomponent output="true">

  <cffunction access="public" returntype="void" name="display">    
  </cffunction>
  
  <cffunction access="public" returntype="void" name="performFly">
    <cfset VARIABLES.flyBehaviour.fly()>    
  </cffunction>
  
  <cffunction access="public" returntype="void" name="performQuack">
    <cfset VARIABLES.quackBehaviour.quack()>    
  </cffunction>

  <cffunction access="public" returntype="void" name="swim">
    <cfoutput>All ducks float, even decoys!<br/></cfoutput>    
  </cffunction>

  <cffunction access="public" returntype="void" name="setFlyBehaviour">
    <cfargument required="true" type="FlyBehaviour" name="flyBehaviour">
    <cfset VARIABLES.flyBehaviour = ARGUMENTS.flyBehaviour>
  </cffunction>

  <cffunction access="public" returntype="void" name="setQuackBehaviour">
    <cfargument required="true" type="QuackBehaviour" name="quackBehaviour">
    <cfset VARIABLES.quackBehaviour = ARGUMENTS.quackBehaviour>
  </cffunction>
    
</cfcomponent>

Quack Strategies

Quack.cfc

<cfcomponent implements="QuackBehaviour" output="true">

  <cffunction access="public" returntype="Quack" name="init">
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="void" name="quack">
    <cfoutput>Quack<br/></cfoutput>  
  </cffunction>
  
</cfcomponent>

Fly Strategies

FlyWithWings.cfc

<cfcomponent implements="FlyBehaviour" output="true">
  
  <cffunction access="public" returntype="FlyWithWings" name="init">
    <cfreturn THIS>
  </cffunction>   
  
  <cffunction access="public" returntype="void" name="fly">
    <cfoutput>I'm flying!<br/></cfoutput>
  </cffunction>
  
</cfcomponent>

FlyNoWay.cfc

<cfcomponent implements="FlyBehaviour" output="true">
  
  <cffunction access="public" returntype="FlyNoWay" name="init">
    <cfreturn THIS>
  </cffunction>
  
  <cffunction access="public" returntype="void" name="fly">
    <cfoutput>I can't fly<br/></cfoutput>
  </cffunction>
  
</cfcomponent>

FlyRocketPowered.cfc

<cfcomponent implements="FlyBehaviour" output="true">
  
  <cffunction access="public" returntype="FlyRocketPowered" name="init">
    <cfreturn THIS>
  </cffunction>  
  
  <cffunction access="public" returntype="void" name="fly">
    <cfoutput>I'm flying with a rocket!<br/></cfoutput>
  </cffunction>
  
</cfcomponent>

Duck Implementations

MallardDuck.cfc

<cfcomponent extends="Duck" output="true">

  <cffunction access="public" returntype="MallardDuck" name="init">
    <cfset VARIABLES.flyBehaviour = createObject("component", "FlyWithWings").init()>
    <cfset VARIABLES.quackBehaviour = createObject("component", "Quack").init()>
    <cfreturn THIS>
  </cffunction>
  
  <cffunction access="public" returntype="void" name="display">
    <cfoutput>I'm a real Mallard duck<br/></cfoutput>
  </cffunction>
   
</cfcomponent>

ModelDuck.cfc

<cfcomponent extends="Duck" output="true">

  <cffunction access="public" returntype="ModelDuck" name="init">
    <cfset VARIABLES.flyBehaviour = createObject("component", "FlyNoWay").init()>
    <cfset VARIABLES.quackBehaviour = createObject("component", "Quack").init()>
    <cfreturn THIS>
  </cffunction>
  
  <cffunction access="public" returntype="void" name="display">
    <cfoutput>I'm a model duck<br/></cfoutput>
  </cffunction>
   
</cfcomponent>

Test Page

MiniDuckSimulator.cfm

<cfset mallard = createObject("component", "MallardDuck").init()>
<cfset mallard.performQuack()>
<cfset mallard.performFly()>

<cfset model = createObject("component", "ModelDuck").init()>
<cfset model.performFly()>
<cfset model.setFlyBehaviour(createObject("component", "FlyRocketPowered").init())>
<cfset model.performFly()>

Source Code

Tuesday, 16 February 2010

ColdFusion Head First Design Patterns: MVC

Head First Design Patterns is a pretty good book, with loads of good code examples in Java and not nearly as dry as GoF. It's even got a fit bird on the front cover. Careful though, looks like she's rocking an itchy twunt.

Source code for the book is available here.

For this post I've taken the web application MVC code written in Java/Servlets/JSP and re-coded it in CFML.

Model

BeatModel.cfc

<cfcomponent output="false">

  <cfset VARIABLES.bpm = 90>

  <cffunction returntype="BeatModel" name="init">
    <cfreturn this>
  </cffunction>

  <cffunction returntype="void" name="on">
    <cfset setBPM(90)>
  </cffunction>

  <cffunction returntype="void" name="off">
    <cfset setBPM(0)>
  </cffunction>

  <cffunction returntype="void" name="setBPM">
    <cfargument required="yes" type="numeric" name="bpm" />

    <cfset VARIABLES.bpm = ARGUMENTS.bpm>
  </cffunction>

  <cffunction returntype="numeric" name="getBPM">
    <cfreturn VARIABLES.bpm>
  </cffunction>
  
</cfcomponent>

View

DJView.cfm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>DJ View</title>
  </head>
 <body>
    <h1>DJ View</h1> 
    Beats per minute = <cfoutput>#APPLICATION.beatModel.getBPM()#</cfoutput>    
    <br />
    <hr />
    <br />    
    <form method="post" action="DJView.cfc">
      BPM: <input type="text" name="bpm" value="<cfoutput>#APPLICATION.beatModel.getBPM()#</cfoutput>" />
       
      <input type="submit" name="set" value="set" />
      <br />
      <input type="submit" name="decrease" value="<<" />
      <input type="submit" name="increase" value=">>" />
      <br />
      <input type="submit" name="on" value="on" />
      <input type="submit" name="off" value="off" />
    </form>
  </body>  
</html>

Controller

DJView.cfc

<cfcomponent output="false">

  <cfif NOT isDefined("FORM.bpm")>
    <cfset FORM.bpm = APPLICATION.beatModel.getBPM()>
  </cfif>
  
  <cfif isDefined("FORM.set")>
    <cfset APPLICATION.beatModel.setBPM(trim(FORM.bpm))>
  </cfif>
  
  <cfif isDefined("FORM.decrease")>
    <cfset APPLICATION.beatModel.setBPM(APPLICATION.beatModel.getBPM() - 1)>
  </cfif>
 
  <cfif isDefined("FORM.increase")>
    <cfset APPLICATION.beatModel.setBPM(APPLICATION.beatModel.getBPM() + 1)>
  </cfif>
 
  <cfif isDefined("FORM.on")>
    <cfset APPLICATION.beatModel.on()>
  </cfif>

  <cfif isDefined("FORM.off")>
    <cfset APPLICATION.beatModel.off()>
  </cfif>

  <cflocation url="DJView.cfm">

</cfcomponent>

Initialization

Application.cfc

<cfcomponent output="false">

  <cfset THIS.Name = "Head First MVC" />
   
  <cffunction access="public" returntype="void" name="onApplicationStart">
    <cfset APPLICATION.beatModel = createObject("component", "BeatModel").init()>
  </cffunction>
  
</cfcomponent>

Source Code