Sunday, July 4, 2010

Learn the basic concepts and significance of functional programming in 10 minutes

Introduction


If you're a Java programmer, this short article will show you the basic concepts of functional programming and the reason why it may be getting more and more important in the near future. All sample code is in Java so it should be very easy to understand.

What is functional programming?


Functional programming is just like our programming in Java or C#, but without assignments. You may wonder is this possible at all? For example, to calculate the total price of a list of product prices, one might write in functional programming style (the code is still in Java):

abstract class List {
}

class EmptyList extends List {
}

class NonEmptyList extends List {
int head;
List tail;
}

class Foo {
int getTotalPrice(List ps) {
if (ps instanceof EmptyList) {
return 0;
} else {
final NonEmptyList nl = (NonEmptyList) ps; //initialization, NOT assignment
return nl.head + getTotalPrice(nl.tail);
}
}
}

Note that in line 17 there seems to be an assignment, but it is not: It is an initialization and the variable is declared as final, so no modification can be made. This is perfectly allowed in functional programming.
So you can see that assignment is not really required. But why the lack of assignment is a good thing?

Why functional programming may be huge in the near future?


To see the benefit, let's assume that if a price is >= 100 then you'll give a 20% off discount. So, you may modify the code as:

class Foo {
int getTotalPrice(List ps) {
if (ps instanceof EmptyList) {
return 0;
} else {
final NonEmptyList nl = (NonEmptyList) ps;
final int headDiscountedPrice = nl.head >= 100 ? (int) (nl.head * 0.8) : nl.head;
final int tailPrice = getTotalPrice(nl.tail);
return headDiscountedPrice + tailPrice;
}
}
}

Note the three initializations. Because all the variables and fields can't be modified, their order is unimportant and, in a real functional programming language, the order can be changed at wish without changing the return value. For example, you could change it like:

class Foo {
int getTotalPrice(List ps) {
if (ps instanceof EmptyList) {
return 0;
} else {
final int tailPrice = getTotalPrice(nl.tail); //nl is not initialized yet, how it works?
final int headDiscountedPrice = nl.head >= 100 ? (int) (nl.head * 0.8) : nl.head;
final NonEmptyList nl = (NonEmptyList) ps;
return headDiscountedPrice + tailPrice;
}
}
}

Note that when initializing the tailPrice variable, the nl variable hasn't been initialized yet. Will this cause a problem? No. In a real functional programming language, each of three variables will be initialized at the same time with a lazy expression. When the value is really needed, the lazy expression will be evaluated. So, if the value of tailPrice is needed but nl hasn't been evaluated yet, it will be evaluated and the calculation will proceed. No matter what execution order is, the final total price will be the same.
Now, let's get to the core issue of why this is important. As the order of these expressions are unimportant, they can be evaluated concurrently. As nowadays we're getting more CPU cores instead of speedier single CPU, this programming model may become the mainstream in the future as the evaluations of different expressions can be done in different cores.
Note that the semicolon in the code now has a different meaning: In Java, it means sequential execution, but in a real functional programming language, it only separates the expressions but there is no ordering at all. That is, in a real functional programming language, there is no obvious concept of sequential execution.

How to maintain states or write to a database?


How to write to a database in functional programming? Let's say there is special built-in methods to perform reading and writing to a certain database record. Let's try to increment the value of the record twice with the code below:

class Foo {
int read() {
//...
}
void write(int v) {
//...
}
void inc() {
final int v = read();
final int w = v+1;
write(w);
final int t = w+1;
write(t); //Problem: It may occur before write(w)!
}
}

The problem with the code is that, because there is no ordering, write(t) may be evaluated before write(w), so finally the value will have been increased by one, not two! The problem here is that, once we have assignment (the write operation to the record), the ordering becomes important, but there is no obvious ordering in functional programming.

Creating sequential ordering in functional programming


In fact, it is possible to create the effect of sequential evaluation in functional programming. For the above example, you can restructure the code as:

interface Function {
Object eval(Object arg);
}

class Foo {
int write(int v) {
...
}
void inc() {
final int v = read();
new Function() {

public Object eval(Object arg) {
final int w = v+1;
final int r = write(w);
return new Function() {

public Object eval(Object arg) {
final int t = w+1;
return write(t);
}
}.eval(r); //Force r to be evaluated before going into eval()
}
}.eval(v); //Force v to be evaluated before going into eval()
}

Now, you're putting the logic into three steps: step 1: read the record. step 2: write w to the record. step 3: write t to the record. To make sure step 1 is executed before step 2, you wrap step 2 into a Function object and pass the result of step 1 (the "v" variable) as an argument to its eval() method. In a real functional programming language, when calling a method, its arguments will be fully evaluated. So, this guarantees that step 1 is executed before step 2. You use the same trick to put step 3 into a Function object inside step 2 and pass the result of step 2 (the "r" variable) as an argument to its eval() method. For this to work, the write() method must return something instead of void. So, I changed it to return an int.
It works, but the code looks complex. To make it simpler, you can introduce a method like:

class Foo {
Object chain(Object arg, Function f) {
return f.eval(arg);
}
void inc() {
final int v = read();
chain(v, new Function() {

public Object eval(Object arg) {
final int w = v+1;
final int r = write(w);
return chain(r, new Function() {

public Object eval(Object arg) {
final int t = w+1;
return write(t);
}
});
}
});
}

Once you have such a chain() method, you can perform more interesting things. For example, instead of passing the previous result directly as the argument, you could expect it to be an instruction to access the database so that you perform the database access in the chain() in the top level of your program, so that all the code inside is free of any side-effect:

class Read {
}

class Write {
int v;

public Write(int v) {
this.v = v;
}
}
class Foo {
Object chain(Object arg, Function f) {
if (arg instanceof Read) { //arg is now the instruction
return f.eval(read()); //Perform the side effect here
}
if (arg instanceof Write) {
final int v = ((Write)arg).v;
return f.eval(write(v)); //Perform the side effect here
}
return null;
}
void inc() {
chain(new Read(), new Function() {

public Object eval(Object arg) {
final int w = (Integer)arg+1;
final Write r = new Write(w);
return chain(r, new Function() {

public Object eval(Object arg) {
final int t = w+1;
return chain(new Write(t), ...);
}
});
}
});
}
}

In addition, you can perform other interesting things in the chain() method. For example, the argument could also contain an integer indicating the number of available resources. Every time you could reduce it by one before passing to the next step. If it is zero, you could abort.
BTW, you've just learned one of the most intriguing concepts in functional programming: monad. It is just the way above to achieve sequencing, optionally manipulating the previous result, and combining it with the next step.

Better syntax?


Even though it works, the multiple levels of embedding is still very complicated. In a real functional programming, you won't need to write so much to create the anonymous Function object, to define the eval() method and you probably can use an infix operator in place of the chain() method. For example, in Haskell, the code can be written something like this:

inc =
new Read() >>=
\v ->
w = v+1
new Write(w) >>=
\r ->
t = w+1
new Write(t)

Here the >>= infix operator has replaced for the chain() method. The \x -> expresssion defines an anonymous function and x is the argument. It looks simple, right?

What can you do next?


Now you've learned the significance of functional programming. What to do next? If you'd like to learn more about functional programming, if you prefer static typing, I'd recommend that you study Haskell by going through this excellent tutorial. Then, for production, you may check out Scala which supports functional programming and integration with JVM and all existing Java classes. It borrows a lot of concepts from Haskell. It also supports assignments and OO, so it can ease the migration from Java.
If you prefer dynamic typing, for production, you may check out Clojure which also integrates with JVM and existing Java classes.

Saturday, June 19, 2010

Getting started with Scala, Spring, Hibernate & Wicket

Introduction


Below is a tutorial to document what I did to create a fully working Scala project utilizing the best or the most popular frameworks or tools in enterprise Java such as Spring, Hibernate/JPA, Wicket, Maven and Intellij IDEA. The purpose is to help other Java programmers get started quickly with a fully working enterprise Scala project.

Setting up the IDE


First, download the Intellij IDEA 9.0.x (community edition) as it is the best scala IDE right now. Then choose File | Settings | Plugins, choose the Available tab to install the Scala plugin.

Creating the Maven project


In IDEA, choose File | New Project and choose the Maven module to create a Maven project. Then modify pom.xml as shown below. This will add all the dependencies you need and set up the compilation of Scala classes in the build processes:

<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>com.foo</groupId>
<artifactId>myapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>myapp Java EE 6 Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.0.3.RELEASE</spring.version>
</properties>
<repositories>
<repository>
<id>java.net2</id>
<name>Repository hosting the jee6 artifacts</name>
<url>http://download.java.net/maven/2</url>
</repository>
<repository>
<id>scala-tools.org</id>
<name>Scala-tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</repository>
<repository>
<id>wpt-release</id>
<url>http://wicketpagetest.sourceforge.net/m2-repo/releases</url>
</repository>
<repository>
<id>wpt-snapshot</id>
<url>http://wicketpagetest.sourceforge.net/m2-repo/snapshots</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>scala-tools.org</id>
<name>Scala-tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</pluginRepository>
</pluginRepositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.120</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.4.0.GA</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>com.ttdev</groupId>
<artifactId>wpt-core</artifactId>
<version>1.5.2-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ttdev</groupId>
<artifactId>wpt-runtime-spring</artifactId>
<version>1.5.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.8.0.RC3</version>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket</artifactId>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.9.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>myapp</finalName>
</build>
</project>

Wait for a while and IDEA will prompt you on whether to import the changes into the project. Say yes.

Setting up web.xml


Next, modify main/webapp/WEB-INF/web.xml as below. This sets up the Wicket filter, the Spring filter to open the JPA entity manager and the Spring listener to initialize Spring itself.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>f2</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter>
<filter-name>f1</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.foo.myapp.MyApp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>f1</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>f2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>

Setting up the Spring beans for database access and transaction


To define those Spring beans, create main/resources/beans.xml with the content below. This defines the entity manager factory, the transaction manager and etc.

<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="com.foo.myapp"/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:/META-INF/my-persistence.xml"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
<tx:annotation-driven />
</beans>

The entity manager factory will read the database configuration from the my-persistence.xml file. So, create it in main/resources/META-INF with the content below. Here, you'll access an H2 database named myapp in your home directory.

<persistence 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"
version="2.0">
<persistence-unit name="myapp" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/~/myapp"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>

Creating the Wicket page


Here, you'll create a Wicket page to display some products loaded from the database. So, create the main/scala folder, right click it and choose New | Scala Class. Name the class as MyPage and put it into the com.foo.myapp package. The class is shown below:


package com.foo.myapp

import org.apache.wicket.markup.html._
import basic.Label
import list.{ListItem, ListView}
import org.apache.wicket.spring.injection.annot.SpringBean
import org.apache.wicket.model.CompoundPropertyModel

class MyPage extends WebPage {
@SpringBean
var ps: ProductService = _
val productListView = new ListView[Product]("productListView", ps.getAll) {
def populateItem(item: ListItem[Product]) = {
item.setModel(new CompoundPropertyModel[Product](item.getDefaultModelObject))
item.add(new Label("name"))
item.add(new Label("price"))
}
}
add(productListView)
}

Note that it is using a ProductService object to load the products. You'll create it later. In addition, note that the field is assigned to an underscore (_), which tells the Scala compile to NOT initialize, but leave it at the default state (null in this case). This is required for the injection to work. If you assign it to null explicitly, you
will overwrite the Spring bean as the injection will occur before the constructor of MyPage is executed.
Now, create the MyPage.html file in src/main/resources/com/foo/myapp:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<table border="1">
<tr wicket:id="productListView">
<td wicket:id="name"></td>
<td wicket:id="price"></td>
</tr>
</table>
</html>

Creating the ProductService


Right click the com.foo.myapp package in the src/main/scala folder and choose New | Scala Class, then choose to create a trait named ProductService:

package com.foo.myapp

import java.util.List

trait ProductService {
def getAll: List[Product]
}


This is the interface. To create the implementation, create a DefaultProductService Scala class in the same package:

package com.foo.myapp

import javax.persistence.{PersistenceContext, EntityManager}
import org.springframework.stereotype.{Service}
import org.springframework.transaction.annotation.Transactional
import org.springframework.beans.factory.annotation.Autowired

@Service
@Transactional
class DefaultProductService extends ProductService {
@Autowired
var products: Products = _

def getAll = products.getAll
}

Note that it is using a DAO named of type Products to do the work.

Creating the Products DAO


To create the DAO, create a trait named Products in the same package:

package com.foo.myapp

import java.util.List

trait Products {
def getAll: List[Product]
}

Then create the implementation Scala class DefaultProducts in the same package:

package com.foo.myapp

import javax.persistence.{PersistenceContext, EntityManager}
import org.springframework.stereotype.Repository
import java.util.List

@Repository
class DefaultProducts extends Products {
@PersistenceContext
var em: EntityManager = _

def getAll = {
em.createQuery("select p from Product p").getResultList.asInstanceOf[List[Product]]
}
}

Creating the entity class


Create the Product class and map it to the database:

package com.foo.myapp

import javax.persistence.{GeneratedValue, Id, Entity}

@Entity
class Product {
@Id
@GeneratedValue
var id: Long = _
var name: String = _
var price: Double = _
}

Creating the Wicket application class


Finally, create MyApp Scala class in the same package:


package com.foo.myapp

import org.apache.wicket.protocol.http.WebApplication
import com.ttdev.wicketpagetest.MockableSpringBeanInjector

class MyApp extends WebApplication {
def getHomePage = classOf[MyPage]

override def init = {
MockableSpringBeanInjector.installInjector(this)
}
}

Here you specify MyPage as the home page and install an injector that can inject Spring beans (as well as mock objects, even though you won't use this capability here).

Running the application


As the Intellij IDEA community edition doesn't include the integration with app servers, you'll embed Jetty to run your application. This is easy. Just create a Scala class ManualTest in the com.foo.myapp package in the test/scala folder (NOT the main/scala folder). The content is below:

package com.foo.myapp

import com.ttdev.wicketpagetest.{WebAppJettyConfiguration, WicketAppJettyLauncher}

object ManualTest {
def main(args: Array[String]) {
val l = new WicketAppJettyLauncher
l.startAppInJetty(new WebAppJettyConfiguration)
}
}

To run the application, you need to have the H2 database server running first. So, go to http://www.h2database.com to download and unpack it. Then change into h2/bin and run h2.bat (or h2.sh on Linux).
While the ManualTest class is the active editor in IDEA, choose Run | Run in IDEA. It will run ManualTest which will launch Jetty to run your application.
To test it, try accessing http://localhost:8888/app in a browser. It should display nothing as there is no product in the database. However, it will create the table required.
To add some products, go to http://localhost:8082 to access the H2 web client. Enter jdbc:h2:tcp://localhost/~/myapp as the JDBC URL. Click Connect. Then issue the SQL statement:

SELECT * FROM PRODUCT


to select the product. Nothing should be there. That's fine. In the result display, click the plus sign to create a product record. Feel free to add more.
Finally, reload http://localhost:8888/app and you should see the products displayed in the Wicket page.
Updated: You can download the project folder.

Friday, June 18, 2010

Scala IDE has matured for the mass

For a language to be readily used by the mass, in addition to the language itself, it needs a production quality runtime, rich libraries and IDE (I know superstar programmers can use Emacs or vi to program, but I believe the mass including myself really need an IDE that works). As Scala is using the JVM and can use all the libraries written in Java, the first two conditions are already checked. What has been holding it back is the IDE. The good news is, the free intellij IDEA community edition now meets all the needs of the majority of web programmers.
Why? First of all, code complete actually works. Second, it supports Maven project mixing Java and Scala. Third, even though the community edition doesn't support integration with app servers, we can easily launch an embedded Jetty to run the webapp right in the IDE (to see an example, see the example given by Larry H there). The effect is no different from having an integration with Jetty.
Before trying intellij IDEA, I also tried Eclipse and NetBeans. The Scala plugin for Eclipse is of alpha quality (and has always been so for the past several years). Every time I tried it always had all kinds of obvious problems like code-completion not working while it should, showing errors while the code compiles fine with scalac.
The Scala plugin for NetBeans is much better than the Eclipse one and is quite close to being production ready. Basically code complete works. However, when auto-completing a class name, it won't add the import statement for you. In addition, it can't generate the method signature for you when you want to override a method or implement an abstract method. In my opinion these shortcomings must be fixed before it can be used in day-to-day work.

Thursday, June 17, 2010

Three time-saving tips you didn't know in testing Wicket pages

If you use the excellent Wicket framework to development web applications, with the Wicket Page Test library, the following tips will greatly reduce your turn-around time during development:

Tip 1: Install mock objects into your page so that it won't hit the database during the unit test


For example, the page below usually will use a Spring bean to load a Product object from the database:

public class Page1 extends WebPage {
@SpringBean
private MyService service;

public Page1(String productId) {
Product p = service.loadProduct(productId);
...
}
}

In the unit test, you can install a mock object to replace the service like:

@Test
public class Page1Test {
private Product p1;

public void test1() {
p1 = new Product(...); //hard code Product
MockableSpringBeanInjector.mockBean("service", new MyService() {
public Product loadProduct(String productId) {
return productId.equals("p1") ? p1 : null;
}
});
DefaultSelenium selenium = ...;
selenium.open(...); //open the page
assert ...; //inspect the HTML elements
}
}

Tip 2: Test real AJAX effect and wait for AJAX completion easily


You can, say, click an AJAX link or AJAX button and wait for the completion easily like:

@Test
public class Page1Test {
public void test1() {
Selenium selenium = ...;
WicketSelenium ws = new WicketSelenium(selenium);
...
selenium.click("link=Buy"); //click an AJAX link
ws.waitUntilAjaxDone(); //wait until page is refreshed
assert ...; //inspect the HTML elements
}
}

Tip 3: Locate the HTML element generated by a given Wicket component easily


For example, to click the link generated by a Wicket Link component whose ID is "productDetails", just the special wicket locator:

@Test
public class Page1Test {
public void test1() {
Selenium selenium = ...;
...
//locate the link whose Wicket ID is productDetails
selenium.click("wicket=//productDetails");
selenium.waitForPageToLoad("3000");
assert ...; //inspect the HTML elements
}
}

You can even look further for a descendant component using something like //product//order (the order button for the product) or even use an index (if you have a loop) like //product[3]//order (the order button for the 3rd product).


To apply these tips, get the open source Wicket Page Test library. There is a step-by-step tutorial there.


Disclosure: I am the creator of Wicket Page Test.

Saturday, June 12, 2010

Applying scala to solving real world problems: making delegation super easy

In Java it is very common to write boring code like below to perform logging:

public class Foo {
private static Logger logger = LoggerFactory.getLogger(Foo.class);

public void m1() {
logger.debug("...");
...
logger.debug("...");
}
public void m2() {
logger.debug("...");
...
logger.debug("...");
}
}

As you keep typing the delegation call logger.debug(...) repeatedly, you'll wonder if there is an easy way to do that. For example, you can create your own debug() method, then you can just call debug() instead of logger.debug():

public class Foo {
private static Logger logger = LoggerFactory.getLogger(Foo.class);

public void debug(String msg) {
logger.debug(msg);
}
public void m1() {
debug("...");
...
debug("...");
}
public void m2() {
debug("...");
...
debug("...");
}
}

The problem is that,you'll need to create other similar methods like info(), warn() and error(). In addition, when you work on another class Bar, you will need to create those  methods in Bar again! To solve these problems, you may extract this code into a common base class to be reused:

public class DelegatingLogger {
protected static Logger logger;

public void debug(String msg) {
logger.debug(msg);
}
public void info(String msg) {
logger.info(msg);
}
...
}

public class Foo extends DelegatingLogger {
static {
logger = LoggerFactory.getLogger(Foo.class);
}
public void m1() {
debug("...");
...
debug("...");
}
}

However, because Java only support single inheritance, if Foo needs to inherit a real base class, then this approach won't work. To solve this problem in Scala, we can make the DelegatingLogger class a "trait" which is an auxiliary base class (any class can be a trait as long as its constructor takes no argument):

trait DelegatingLogger {
val logger: Logger = LoggerFactory.getLogger(getClass());

def debug(msg: String) {
logger.debug(msg)
}
def info(msg: String) {
logger.info(msg)
}
}

class Foo extends SomeParent with DelegatingLogger {
def m1 {
debug("...")
...
debug("...")
}
}

What the trait mechanism does here is essentially allowing us to easily turn the Foo class from a logger user into a logger itself, that is, turning a "use" relationship into an "is" relationship.
If you're careful, you may notice that now the logger is an instance variable, not a static variable. If you're concerned about it, you can let a singleton object (which is also named Foo here but could be anything else) inherit DelegatingLogger, then use a static import to make the static methods available in the Foo class:

object Foo extends DelegatingLogger {

}

import Foo._

class Foo extends SomeParent {
def m1 {
debug("...")
}
}

Sunday, May 30, 2010

Architectural improvements for JVM to be enterprise ready

Time proven architecture for long running services


I've observed that once in a while our long running Tomcat instance will get slower and slower, until it (the JVM) is restarted. Obviously the Tomcat developers are experts in enterprise Java, why is it still happening and how to fix it? One could look for specific problems in the code, but a much better approach is to adopt a time proven architecture, particularly well-known in traditional Unix daemon processing:

  1. The master daemon process is started.

  2. The master daemon process spawns some child processes to handle client requests

  3. After handling a limited number of requests, a child process will terminate itself (or done by the master). The key point here is that the OS will free any resources (e.g., memory, file handles, sockets) allocated to that child process; there is no way to leave anything behind after its death.


This architecture ensures a long-running service without any degrading, even if the code is poorly written and has resource leaks.

How can Java support this architecture?


So, does Java support this currently? The answer is no. To do that:

  1. The JVM needs to support the  concept of isolated process.

  2. Objects created by the JVM itself and different a process must NOT be allowed to refer to one other, otherwise there would be no way to cleanly kill a process.

  3. The JVM must allow efficiently forking a process to quickly create a child process. This way, the master process can perform all kinds of lengthy initialization (e.g., Hibernate and Spring initialization), while it is still very quick to spawn a child in the initialized state.

Friday, May 21, 2010

Open letter to certification providers

Dear certification providers,
In recent months I've interviewed three candidates with CCNP certifications and I was very disappointed to find that two of them didn't know how a switch differs from a hub or how it learns the MAC addresses. My first reaction was my disappointment with the lack of integrity of the people and the general availability of brain dump or even real test questions. However, from a more positive view, this has stroked me to think about what we can do to help you improve the situation?
If we consider certifications as a service in the perspective of quality management, then we can clearly see there is a huge problem in it: the exam candidate is both a client and a user (and also a piece of client-provided material :-) ), but there are many other users of this service out there; they are the prospective employers, job interviewers, peers and etc. A key requirement in quality management is to measure if the users are satisfied with the service output. Obviously, as a prospective employer, I am very unhappy with the service output because the CCNP certificate is not reflecting the real expertise of the certificate holders. However, none of you are providing ways for unhappy users like me to provide feedback on your service output. Without such a feedback mechanism, I really don't see how you can ensure the quality of your service.
Therefore, I'd request that you establish a mechanism to accept feedback. For example, provide a website to let me report on those certificate holders who obviously know little about the subject matter. Then follow up with investigation, re-certify as required and revoke their certificates. Just like a digital certificate whose private key has been compromised, such revoked certificates should be published on a website like a CRL.
This is about handling an individual incident. If there are a significant number of such incidents, you should escalate to become a problem (in ITIL term). It means that you must then identify the root cause and to plug the hole to prevent similar incidents, like introducing performance-based exams, reference-based certifications and whatever it takes to fix the problem and save your reputation.