Using a Wiki for School

I recently started an MBA program, and like most, it requires a lot of group work.  Groups often collaborate on projects by emailing Word documents.  I abhor this because it is so painful to work on the same document concurrently.  As the geek of the group, pitched the idea of using a Wiki and setup a Doku instance for us on my TextDrive account.  Doku doesn’t have a WYSIWYG editor, so asking a group of non-techies to use a markup language was a bit of a hard sell.

Two courses and four projects later, the Wiki is really working for everyone.  Everyone loves the fact that our project content is always fresh, everyone can jump in an edit, and old versions are tracked.  We have created a namespace for each class and enter all of our contents for project drafts.  The Wiki format means we get lots of content and minimal formatting.  When it comes time to turn in the assignment, one of us copies the content into a Word doc.  It has been gratifying to see our mostly non-techie group using it.

We hit some snags along the way.  A couple in the group tried to just dump Word documents into the Wiki and were frustrated with the garbage that was displayed.  I offered to fix up any formatting issues right away and eventually everyone got the hang of the simple syntax.  And since most of the work is just headings, text, and bullet lists, it wasn’t much of an issue.  The group also had a problem working with the Wiki when I broke up projects into smaller documents with links.  In fact, everyone really got on board when I changed the format and put all of the content for a project on a single page

Wikis are better than emailing Word documents.  If you find yourself struggling to coordinate group work, give a Wiki a try.  Plain text is your friend.

Goosh - Google Made Better

Goosh is the unofficial Google search shell.  It is really, really cool. Give it a try at http://goosh.org.  I really like this because I do all I can in a command shell - preferably bash.  The mouse annoys me; keystrokes are so much more efficient.  Some tips:

  • Type h for help.
  • Type addengine to add it to your Firefox search bar.
  • Try the auto-completion by typing in part of your search phrase and hitting <Tab>

Google is all about content, not fluff.  I hope other sites will follow this lead and be shell friendly. Click on the following for some samples:

goosh1.pnggoosh2.pnggoosh3.png

Mocking a Stub with EasyMock

I use EasyMock extensively to create mock objects for unit testing. The behavior verification is great for thoroughly testing an object’s interactions with other objects, known as collaborators. Sometimes, however, a mock cannot do all that is needed. Martin Fowler, in his article “Mocks aren’t Stubs”, identifies injected collaborators, or “test doubles”, as being mocks or stubs. Using EasyMock, it is possible to create an object which is both.

I recently ran into a scenario where I needed such a hybrid. Consider save method the following Struts action. This method handles both new and existing products, differentiated by the nullity of the id property of product.

Here is the class under test:

public class CustomerEditAction extends ActionSupport implements Preparable {

  private CustomerDao customerDao;
  private Long id;
  private Customer customer;

  public void setCustomerDao(CustomerDao customerDao) {
    this.customerDao = customerDao;
  }
  public Long getId() {
    return id;
  }
  public void setId(Long id) {
    this.id = id;
  }
  public Customer getCustomer() {
    return customer;
  }
  public void setCustomer(Customer customer) {
    this.customer = customer;
  }

  public void prepare() throws Exception {
    /* Sets up the id and the customer.  Removed for brevity */
  }

  public String save() {

    if (customer.getId() == null) {
      customerDao.insert(customer);
      setId(customer.getId());
  } else {
    customerDao.update(customer);
  }

  return Action.SUCCESS;
}

And here is the collaborating dao:

public interface CustomerDao {

  List getAll();

  Customer getForId(Long id);

  void insert(Customer customer);

  void update(Customer customer);

}

Testing the “update” case of the save method where product.getId() is not null with a mock object is simple, all we need to verify that the update method of product dao is called with the right argument.

The “insert” case is not as straightforward, and is a case where a simple mock is not sufficient.
This issue is with verifying the additional step of setting the id of the product to the action after the insert is performed. It is assumed that the productDao itself modifies the id of the product after inserting it into the database. Since a mock object is just an empty shell which follow scripted behaviors without any implementation, there is no way to use one to actually modify the product as the actual dao would. But without actually modifying the product passed as an argument to productDao, there is no way to verify that the id property of the action is set with the value from the id property of the product. The alternative is to use a stub in our test case instead of a mock, like the following:

private static abstract class StubCustomerDao implements CustomerDao {

  static final Long ID = 9999L;

  public void insert(Customer customer) {
    customer.setId(ID);
  }

}

The class is actually an inner class of my test class. It is abstract for a reason - keep reading for the explanation.

The resulting unit test for the insert case would be:

public class CustomerEditActionTest {

  private CustomerEditAction action;
  private StubCustomerDao customerDao;
  private Long id;
  private Customer customer;

  @Before
  public void setUp() throws Exception {

    action = new CustomerEditAction();

    /*
    * Here we are creating a mock of our stub, a private inner class
    */
    customerDao = createMock(StubCustomerDao.class,
    StubCustomerDao.class.getMethod("getForId", Long.class),
    StubCustomerDao.class.getMethod("update", Customer.class));

    id = 1L;
    customer = new Customer();
    customer.setId(id);

    action.setCustomerDao(customerDao);
  }

  /* Some tests removed for brevity */

  @Test
  public void testSaveInsert() {

    reset(customerDao);
    customer.setId(null);
    action.setCustomer(customer);
    replay(customerDao);
    assertSame("result not success", Action.SUCCESS, action.save());
    assertEquals("customer id is equals", StubCustomerDao.ID,
    action.getId());
    verify(customerDao);

  }

  @Test
  public void testSaveUpdate() {

    reset(customerDao);
    action.setCustomer(customer);
    customerDao.update(customer);
    replay(customerDao);
    assertSame("result not success", Action.SUCCESS, action.save());
    verify(customerDao);

  }

  /* Stub class */
  private static abstract class StubCustomerDao implements CustomerDao {

    static final Long ID = 9999L;

    public void insert(Customer customer) {
      customer.setId(ID);
    }
  }

}

Switching from a mock to a stub for the insert method means that I am exclusively verifying state, and no longer verifying behavior. Asserting that the product id and the action have the correct value in their id property gives me reasonable assurance that the action is doing what I want it to do.

But why an abstract class for ProductDaoStub? Because I only want to use a stub for this one test method. It still makes sense to use a mock for calls to to the other methods of the class, like update and getForId. This is where the class extension of EasyMock really shines. With the class extension MockControl, mocks can be created from concrete types, like HttpServletRequest, not just from interface types like ProductDao. By default, a class mock causes all methods to be mocked. You can, however, specify that only certain methods be mocked, and the rest of the class methods are invoked in the class itself. I am using this feature to mock my stub. This gives me all of the power of a mock and the ability to carve out a stub for the one method which needs it. This table shows the effect:

Mock Stub

Method interface ProductDao ProductDaoStub Mock of ProductDaoStub Net Effect
getAll unimplemented unimplemented unimplemented unimplemented
getForId unimplemented unimplemented mocked mocked
insert unimplemented stubbed unimplemented stubbed
update unimplemented unimplemented mocked stubbed

The full code can be browsed here and checked out with the following command:

svn co http://bentomasini.com/svn/repo1/demos/mockstub/tags/TAG-mockingAStub mockstub

Update: Fixed a bug in the unit test where the customer’s id was being asserted and not the action’s id. That kinda misses the whole point.

My Son, The Italian

My 2-year-old son, William, is a true Italian.

Today he took a half-gallon container of olive oil from the kitchen counter and downed a few gulps. After being corrected by mom, he proceeded to ask for bread and vinegar (assume balsamic).

He has the ingredients right, but we need to work on preparation.

“Getting” IoC

Howard Lewis Ship has added an IoC Overview document to the Tapestry IoC project. It’s goal is an important one, helping developers “get” IoC.

For me, “getting” IoC was a big event. It happened to me in early 2004 when I was working on a workflow engine for a large back office application for a bank. A friend of mine told me I should check out HiveMind (the predecessor to Tapestry IoC). Using it, I found I was able to develop more sophisticated, more testable code with less grunt work. The dots between object oriented design and application assembly were connected elegantly.

The document mentions that style of code that works best when using an IoC container:

When thinking in terms of IoC, small is beautiful. What does that mean? It means small classes and small methods are easier to code than large ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods a thousand lines long, and no distinction between business logic and view logic. Everything mixed together into an untestable jumble.

At the other extreme is IoC: small objects, each with a specific purpose, collaborating with other small objects.

Using unit tests, in collaboration with tools such as EasyMock, you can have a code base that is easy to maintain, easy to extend, and easy to test. And by factoring out a lot of plumbing code, your code base will not only be easier to work with, it will be smaller.

The document ends with the concept that IoC does for object creation what garbage collection does for object destruction: takes it out of your hands and does it better (here is an older blog post on that same topic). I think the Guice project captures this concept the best when describing their @Inject annotation, calling it “the new new“.

A Simple Approach to Axis2

I recently started searching for a SOAP framework and took a look at Axis2. Actually, I looked at it twice. The first time I passed because the deployment model was too confusing. Only after evaluating the downsides of the other frameworks did I take a second look. I eventually went with it after I figured out how to get it to meet my two main requirements:

  1. A simple coding and deployment model: I didn’t something so complex that a wizard has to hide the complexity from me. I especially didn’t want a hot deployment of a special archive into a magic axis webapp. Just give me a simple configuration file to edit or some annotations for my service classes.
  2. IoC container integration. Instead of directly instantiating a service class and calling a method, I wanted Axis2 to invoke a method on one of my services defined in my IoC container (Spring, in this case).

I put together a sample project which demonstrates a simple approach to Axis2. The application exposes a single web service for retrieving products from a catalog. The service has two methods: getAll, and getForId.

Getting and Running the Project

The sample project can be found at http://bentomasini.com/svn/repos/demos/catalog/trunk. To try it out, checkout the source and start the application by doing the following. Maven2 is required.

svn co http://bentomasini.com/svn/repos/demos/catalog/trunk catalog
cd catalog
mvn jetty:run

Now open http://localhost:8080/catalog. From there you can open the WSDL and run a few operations using the quasi-RESTful Axis2 interface. To call the service using SOAP, or to generate clients for various SOAP frameworks, I recommend using soapUI. Just create a new WSDL project using the WSDL URL linked from the home page.

Java Code and Spring Configuration

The project’s service class, shown below, calls the injected dao and converts List<Product> to Product[]. SOAP frameworks choke on collections.

package com.bentomasini.catalog;

import com.bentomasini.catalog.Product;
import com.bentomasini.catalog.dao.ProductDao;

/**
*
* @author btomasini
* @since Jul 15, 2007
*
*/

public class ProductService {

    private ProductDao productDao;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public Product[] getAll() {
        return productDao.getAll().toArray(new Product[0]);
    }

    public Product getForId(Long id) {
        return productDao.getForId(id);
    }

}

The applicationContext.xml located in WEB-INF wires up the Spring bean and its dao:

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

  <bean id="productDao" class="com.bentomasini.catalog.dao.impl.ProductDaoImpl"/>

  <bean id="productService" class="com.bentomasini.catalog.ProductService">
    <property name="productDao" ref="productDao" />
  </bean>

</beans>

Axis2 Configuration and web.xml

The method I used to configure Axis2 is key to keeping the project simple. It also requires some background explanation. The Axis2 folks have a concept that developers should package their web services in a new type of archive, an aar, and deploy that aar into a canned Axis2 web application. This makes me scratch my head and go “huh?” I don’t think most developers want to do this. I know I don’t. I simply want to build a web application, specify some services, and package my application in one single application archive - a war.

The good news is that developers don’t have to create aar archive files. Taking a look at the aar deployment model, we see that these service archives are deployed into WEB-INF/services. Alternatively, service archives can be exploded into a directory by the same base name. So WEB-INF/services/ProjectService.aar can instead by deployed by exploding its contents into the directory WEB-INF/services/ProjectService. The magic file in the archive is META-INF/services.xml. It defines the services to be deployed by Axis2. This file can contain a single service definition, or multiple service definitions inside of a service-group element.

We can do away with all of this hoo-ha by having a single services.xml for our entire project. Just pick a generic name for the directory, say “WebService”. Now we can put a single file in our project to define services: WEB-INF/services/WebService/META-INF/services.xml. Just put all of your service definitions in there and enjoy the simplicity. Here is the services.xml file from the sample project:

<?xml version="1.0" encoding="UTF-8"?>
<serviceGroup>

  <service name="ProductService">
    <parameter name="ServiceObjectSupplier" locked="false">
      org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier
    </parameter>
    <parameter name="SpringBeanName" locked="false">productService</parameter>
    <operation name="getForId">
      <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
    </operation>
    <operation name="getAll">
      <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
    </operation>
    <excludeOperations>
      <operation>setProductDao</operation>
    </excludeOperations>
  </service>

  <!-- Add your second service here -->

</serviceGroup>

The service element configures our service for deployment and specifies a special ServiceObjectProvider which knows how to obtain the service from our Spring context. The name of the Spring bean is also provided. Each operation has an operation element and text marking it as an RPC method. In addition, our setProductDao method is excluded because it is only meant for use by our IoC container for dependency injection. Adding another operation or service is simply a cut-and-paste exercise.

The web.xml to load both Spring and Axis2:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>AxisServlet</servlet-name>
    <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>
</web-app>

That’s it!

Installing Emacs 22 on Ubuntu Feisty Fawn

Update: Emacs22 is now available via apt. Before trying this try sudo apt-get install emacs22. You will still need to edit your .emacs file as instructed in the last paragraph to handle Java annotations.

Emacs 22 is now released. I have installed on my Ubuntu Feisty Fawn system. The package is not yet available on the apt repositories, so this required building from source. Here are the steps I followed:

Install prerequisites as follows:
sudo apt-get install g++
sudo apt-get install libgtk2.0-dev

Download the source from http://ftp.gnu.org/pub/gnu/emacs/emacs-22.1.tar.gz.

After unpacking, run:
./configure --with-gtk --enable-font-backend --with-xft --with-freetype
make
sudo make install

Voila! The executable is now installed at: /usr/local/bin/emacs-22.1

The java-mode still does not handle annotations correctly. Getting around this requires adding the following to the ~/.emacs file. It simply treats annotations as comments:

(add-hook
 'java-mode-hook
 '(lambda () "Treat Java 1.5 @-style annotations as comments."
    (setq c-comment-start-regexp "(@|/(/|[*][*]?))")
    (modify-syntax-entry ?@ "< b" java-mode-syntax-table)))

Fully Qualified Artifact Names

There is a lot to like about Restlet, including even the the way they name their artifacts. You can check it out in their maven repository. Instead of just naming their jar restlet-1.0.1.jar, they name it with the full base package name: org.restlet-1.0.1.jar.  That name better represents the actual name of the module.  It also makes it easier to track down which class belongs to which jar, which can be helpful when you have to manually assemble a set of jars for a driver or other resource connector not in your main project.

I am going to adopt this convention for my projects from here on out, and hope other projects will as well.

Moving to Seattle

A week from now my family and I will be collecting our baggage at the Seattle Tacoma airport after a one way flight from Atlanta. That’s right, we are moving. This was decided back in October. Among the reasons is a strong desire to be closer to family. Seeing family now includes lots of time off work and some expensive plane tickets.

I am looking forward to living in Seattle. Some of my coworkers here think the rain is going to be too much to handle. I don’t think so. I plan to outdoors as much as possible, especially mountain biking. I think it will be a very positive change.

Getting ready to move has been crazy, especially with a newborn. We would have waited longer, but a great job opened up that I decided I should jump on. One of the challenges has been managing all of the tasks that have to be done, and by whom. It all started to feel like a hectic project that was falling behind. Oh, wait… that is exactly what it was!

That is when I realized I should treat the move like the project.  We setup a free personal Basecamp project to help us track the milestones and tasks. It has been great. It works especially well for us because we are both at our computers so much during the day. Now we have a handle on just how behind we actually are. :)

Ubuntu Supports Windows File Systems Automatically

My notebook dual boots Ubuntu and Windows.  Sharing files between the two systems has historically been an issue.

I just upgraded to version 7.04 - Feisty Fawn.  While opening a file in The Gimp, I noticed an extra hard drive listed in the dialog.  It was my Windows NTFS partition.  Sweet!  The file system mounts read only by default, but write support can be enabled.  More information can be found here

« Prev - Next »