Shahzad Bhatti Welcome to my ramblings and rants!

January 25, 2009

Review of Clean Code

Filed under: Design — admin @ 8:54 pm

I just finished Clean Code: A Handbook of Agile Software Craftsmanship book, which is a compilation of patterns on writing clean/maintainable code and is written by uncle Bob and other folks from his consulting company Object Mentors including Tim Ottinger, Michael Feathers (author of Working Effectively with Legacy Code. This book is similar to Implementation Patterns by Kent Beck that I recently read on similar coding practices. Though, this book is a lot thicker with seventeen chapters, however there are plenty of pages filled with tedious listing of Java code.

The first chapter shares thoughts on good code from a number innovators and authors such as Kent Beck, Bjarne Stroustrup, Grady Booch, Dave Thomas, etc. They mention various attributes of good code such as easy to read, efficient, DRY, focused, literate, minimal, error handling and warn of bad code that leads to messy code or broken windows mentality.

The chapter 2 talks about golden advice of using intention-revealing names to improve the readability and following principle of least surprise. This chapter denounces use of hungarian notation or member prefix such as _ or m_.

The chapter 3 describes functions and methods and advises to use small, cohesive functions. It suggests using one level of abstraction to facilitate reading code from top to bottom. It also recommends using polymorphic methods as opposed to switch statement, if-else or functions that take flag/boolean arguments. The chapter discourages functions with side effects or the one that create temporal coupling. This chapter describes an aged old advice of command query separation, though it skips its roots from Bertrand Meyer’s design by contract. Finally, this chapter urges use of exceptions as opposed to error codes.

The chapter 4 describes writing good comments that focus on intent and dissuades against redundant and misleading comments.

The chapter 5 illustrates use of good formatting such as indentation, horizontal, vertical spacing, etc.

The chapter 6 describes use of objects and data structures. It encompasses advice on polymorphism, law of demeter, encapsulation, DTO/value objects, etc.

The chapter 7 discusses error handling. Again it encourages use of exceptions rather than return codes or error codes. It prohibits use of checked exceptions as it violates open/closed principle. It also discourages returning or passing null and recommends exceptions or empty collection instead of returning null.

The chapter 8 explains defining boundaries between components.

The chapter 9 describes advice on unit testing such as TDD, keeping tests clean, one assert per test, single concept per test, etc. Though, such advice should be taken with caution as one assert per test may not capture a unit of testing properly.

The chapter 10 is similar to chapter 6 and contains recommendations on writing classes such as encapsulation, classes should be small, single responsibility principle, cohesion, dependency inversion principle, etc.

The chapter 11 encompasses advice on building systems and managing complexity. It suggests dependency injection and use of factories. It also advocates use of AOP for managing cross cutting concerns.

The chapter 12 talks about emergent design, the concept I first heard from Andy Hunt. This chapter describes advice from Kent Beck: run all tests, refactoring, no duplication, express intents of the programmer and minimize the number of classes and methods. This chapter advocates use of template methods to remove duplication and command/visitor patterns to express design to other developers.

The chapter 13 discusses concurrency and suggests use of single-responsbility principle to keep concurrent code separate from other code, limiting scope of data, keeping threads independent, and use of immutable oobjects or copies of data. It recommends keeping critical section small. The chapter also holds advice on testing threaded code and suggests making threaded code plugable.

The chapter 14 shows an excercise on how to incrementally improve code.

The chapter 15 describes JUnit framework and walks reader through improving tests.

The chapter 16 walks reader through another refactor exercise.

The chapter 17 covers a number of smells, heuristics and anti-patterns. It deters use of poorly written comments, builds/tests that require more than one step. The chapter prohibits passing too many arguments to functions or use of output/flag arguments to functions. It encourages testing boundary conditions and respecting overridden safeties. It also proscribes writing code at wrong level of abstraction, i.e., exposing low-level logic through interface. The chapter also forbids exposing derivatives to base classes, having too much information in interface. Other smells include artificial coupling (sharing constants), feature envy (coupling formatting logic), flag arguments. This chapter also holds advice of Kent Beck about using explanatory (local/temporary) variables. The chapter recommends use of constants, structure over convention, encapsulate conditionals, avoiding temporal couplings, keeping functions at same level of abstraction and keeping configurable data at high levels. The chapter also contains Java specific is advice such as avoiding wildcards in imports, avoiding use of interface to inherit constants, etc. Finally, the chapter cautions against insufficient tests, use of coverage tool, testing boundary conditions, etc.

In conclusion, this book contains advice from wide range of authors on writing good maintainable code. As a coder with over 15 years of experience, I can attest that writing good code requires a lot of micro decisions and detailed attention to details and you generally have to continually improve and refactor your code for good design. Sometime it’s hard to maintain a good design when delivering features under tight deadlines so you may have to take shortcuts. Kent often talks about courage in XP and programmers needs to have courage to fight for writing maintainable code and take time to refactor existing code. Finally, I would caution against using these practices arbitrarily as another favorite rule of mine is that every practice or pattern depends on the situation. Unfortunately, there are lot of people in software industry including uncle bob who use these rules in draconian fashion such as always stressing on 100% test coverage or interfaces separate from implementation (DIP). Such advice may bring more money from consulting work or publication, but is disingenuous for practical use in real projects.

January 18, 2009

Tips from Implementation Patterns

Filed under: Computing — admin @ 10:05 pm

I read recently read Kent Beck’s Implementation Patterns book. The book contains a number of low-level programming techniques for improving design of a program. Kent Beck is grand master of programming and a great communicator. If there is one thing you can learn from this book is to communicate design effectively with the code. The book is fairly concise and consists of ten chapters and 130 pages. Following are some of my favorite tips from the book:

Values, Principles and Patterns

Due to his pioneering work in design patterns, Kent uses patterns to identify common programming techniques and similar to his extreme programming style for agile development he divides those techniques into values, principles and patterns. The values focus on high level goals such as communication, simplicity, flexibility. The principles focus on local consequences (minimize side-effect), DRY, keeping data/logic together, symmetry, decalartive (annotations), rate of change (Reuse/Release Equivalency Principle).

Class

The chapter 5 describes different ways of organizing the code using classes, interfaces, versioned interface, abstract class, value object, etc. Kent shows importance of dependency inversion principle of coding to interfaces. He provides trade-offs between interfaces and abstract class such as change in implementation and change of the interface itself. One of the hardest thing in real world is progression of interfaces with new behavior and Kent describes versioned interface for it. Kent also encourages use of value or immutable objects to make the program side-effect free as in functional languages. He bemoans procedural interfaces due to temporal depdency they impose. Inheritance is also most difficult to get right, so Kent gives a lot of advice on that to make sure subclasses follow Liskov Substition Principle. Kent describes discourages use of conditional logic and encourags delegation technique based on polymorphism. He also shows pluggable selector briefly to implement plugin like behavior. Finally, he discourages of use of library classes with static methods and encourages use of instance methods.

State

The chapter 6 describes patterns for state such as access, variables, parameters, initializations, etc. Unlike functional languages that don’t allow mutable state, imperative languages have to manage state that changes over time. Kent prefers indirect access to the state rather than direct especially when there is dependency between multiple pieces of data. Kent prefers keeping scope of variables local. This chapter also gives good advice on naming variables and parameters. Finally, this chapter describes techniques for eager and lazy initialization.

Behavior

The chapter 7 describes patterns for control flow, methods and exceptions. In object oriented languages messages are fundamental mechanism for controlling workflow and communicating with the objects. Kent also describes technique for double dispatch (similar to visitor pattern) that provides polymorphic behavior but at the cost of additional coding and maintenance overhead. Other topics include providing guards, naming method and exception handling.

Methods

The chapter 8 describes how to divide logic into methods. The chapter describes composed method for calling other methods. It encourages use of symmetry and having same level of abstraction for called methods. Kent also shows use of Method object or Function object that mimics functional style of programming. This chapter also describes conversion methods, factory methods, getter/setter methods and advice of returning copy from the methods instead of internal references.

Collections

The chapter 9 describes collections such as arrays, lists, sets, map.

Evolving Framework

This chapter describes how to evolve frameworks without breaking the applications. Kent borrows a lot of his experience from JUnit framework and Eclipse (his buddy Eric Gamma). One of interestic topic is how to use objects and the chapter provides three styles including instantiation, configuration and implmentation. Kent shows how implementation technique allow clients to implement a framework interface and extend behavior. Kent also describes trade-offs of extending interfaces and using specialized interfaces as used by AWT (LayoutManager2). The chapter also offers advice on use of internal classes by clients and how they can be instantiated using constructors, factories, etc.

Conclusion

This book shows a lot of techniques and patterns that most experienced programmers knowingly or unknowningly use on daily basis. Nevertheless, it helps to review these techniques and some trade-offs for them. Though, I wish the book gave a lot more examples and described antipatterns as I often found most of the topics a bit dull.

January 15, 2009

Tips from Effective Java, 2nd edition

Filed under: Java — admin @ 1:56 pm

I have been using Java since ’95 and I just reread Effective Java Second Edition by by Joshua Bloch, it is must have reference book for any Java programmer. It consists of over 75 guidelines for writing better code in Java or any other object oriented language for that better. I describe some of my favorite tips from the book:

Factories/Builders

Though, this book does not cover design patterns in general but encourages use of factories instead of constructors in certain cases. I also use this advice in cases when I have a lot of constructors and it is difficult to tell which constructor should be used. The factory methods also allows instantiating and returning subclass types. Though, the downside is that factory methods look like other static methods so it may not be obvious. I also use builders when I need to create a class with a lot of parameters and some of those parameters are optional. I often use following interface to build objects:

 public interface Builder<T> {
     public T build();
 }
 

Use enum for defining Singleton

As Java does not offer language level construct for defining Singletons (as opposed to Scala), defining Singleton can be difficult. The general rule I follow is to make the constructor private and define a static method for getting instance. However, there are still gotchas of preserving Singletons especially upon deserialization. Joshua recommends using enum because it automatically takes care of those edge cases.

Avoid finalize

Since, Java borrowed much of its syntax from C++, it created finalize method for a sort of desctructor. It is often misunderstood by new Java developers because it’s not a destructor. Also, it may not be called by the Java at all. Joshua recommends using try/finally block for any kind of resource allocation/release. I think closures in Java 7 may also help in this regard.

Generics

There are tons of gotchas with using generics in Java. One of my favorite tip to reduce amount of code is to define helper methods is to type inferencing, e.g.

   public static <K,V> Map<K, V> newMap() {
         return new HashMap<K, V>();
   }
 

One of confusing part of generics is when to use extend vs super, the book gives easy acronym PECS (producer extend consumer super) for remembering it. For example, following code shows a method that adds items to a collection:

   void popall(Collection<? super E> d) {
     d.add(pop());
   }
   void pushAll(Iterable<? extends E> src) {
      for (E e : src)
         push(e);
   }
 
 

Functional Programming

Though, Java is not a functional language, but Joshua offers some tips on creating functors or function objects, e.g.

         interface UnaryFunction<T> {
            public T apply(T arg);
         }
 

Now this interface can be implemented for various operations and give a flavor of functional programming. Again, closures in Java 7 would help in this regard.

EnumSet and EnumMap

I have rarely used EnumSet and EnumMap in practice, but the book offers useful tips for using those instead of bit masking and manipulation.

Threading

Though, I like Java Concurrency in Practice for concurrency and threading related topics. But the book offers good tips such as using immutable classes and use of synchronization features of Java for writing thread-safe applications. One of my favorite tip is to use double check idiom, I learned that when Java initially came out and synchronization was somewhat expensive. However, I stopped using it due to some of concerns in Java memory model. Java 1.5 has fixed the Java memory model so we can use it again by declaring the shared field as volatile and doing something like:

   volatile FieldHolder fh;
   ...
   void foo() {
     FieldHolder ref = fh;
     if (ref == null) {
         synchronized (this) {
             ref = fh;
             if (ref == null) {
                fh = ref = compute();
             }
         }
     }
   }
 

Another tip is to use lazy init holder pattern for initializing static field lazily that requires some synchronization, e.g.

 class MyClass {
     static class FieldHolder {
         static Field field = compute();
     }
     static Field get() {
         return FieldHolder.field;
     }
     static synchronized Field compute() {
        ...
     }
 }
 

Other threading tips include use of Executors and classes from new Java concurrency library (java.util.concurency).

Cloning and Serialization

The short answer for cloning is not to use it and instead use constructors to copy objects. The serialization creates a lot of security problems and can be difficult when using inheritance.

Exceptions

Joshua also offers a lot of good advice for exceptions such as using exceptions with proper abstraction level. Though, he still suggests use of checked exceptions for recoverable errors but my suggestion is to use RuntimeException for both application/non-recoverable exceptions and system/recoverable exceptions.

equals, hashCode, toString, Comparable

Writing equals method when inheritance is used can also be difficult and Joshua offers a lot of good advice on writing correct equals method. Another gotcha is to make sure hashCode matches semantics of equals method. Also, it good idea to implement Comparable interface so that it’s easy to use sorted collections.

Conclusion

I briefly wrote some of my favorite tips from the book, again it’s absolute desk reference book.

January 10, 2009

Launched beta version of Deal Red Hot or Not! website and facebook app.

Filed under: Computing — admin @ 10:27 pm

Over the holidays, I spent a little time on launching a new website Deal Red Hot or Not! to share tips on savings and great deals. I spent few hours today to finish facebook version of the site . Though, the site still need more work, but give it a try and send me your feedback.

December 29, 2008

Leaving the industry (IT)

Filed under: Computing — admin @ 1:14 pm

I read an interesting reply by Joel Spolsky to a post on Thinking of leaving the industry (IT) by someone who is thinking about leaving software industry and going for a business degree. Joel reply can be summed up to following points:

  • great programmers are not effected by the economic downturn.
  • pay is great with starting salary of $75,000 and most earn six figures salary.
  • programmers are treated better than people from other occupation.
  • most programmers would do programming even if they don’t get paid.

I have been programming for over twenty one years and love programming. For long time, the way I distinguished between great programmers and average programmers was passion and one way to see the passion is to ask them of their side projects. Though, I agree with first and last point and second point is a stretch, but I disagree with the third point. I have worked at ten or more companies as an employee and consultant and like answer to every programming design question: “it depends,” the treatment of programmers also varies.

I have spoken on this topic earlier [ 1 , 2 , 3]. I have found most IT places to be sweatshops, for example, in most companies Taylorism rules and programmers are treated like another dumb workers and managers are responsible for whipping them to get the work done. In fact, death march projects are norm in most places, where managers think setting impossible deadline will motivate people to put a lot of hours and finish the project earlier. Given, that there isn’t any overtime compensation in our industry, there is a little problem with such mentality. Such attitude is common in not only average companies but at top companies like Microsoft and Google where you get your so called 20% time for personal projects after you spend 60+ hours on actual project. Though, computers have added convenience to our life with a 7×24 culture, the cost of such culture is being oncall, which can curtail your social life significantly. Finally, offshoring has also effected job market and though most offshore people can’t compete with local great programmers and I will take 4-5 local great programmers over 100 offshore programmers any day, but it provides a very attractive alternative against average programmers.

So, despite higher salary, I think most programmers (great) work much harder than most other professionals and it can be a stressful job when you continuously have to work with impossible deadlines. Though, during dot com boom I saw plenty of store clerks and script kiddies making six figures in IT but they are long gone. These days, you cannot survive IT industry unless you are a top notch. And if you are not then, you’d better off move to management, which is the trend I have seen in most companies. In conclusion, I agree with the last point of Joel and the only way to survive in IT is passion.

November 22, 2008

Implementing Actor-based message passing using Object-oriented methods

Filed under: Computing — admin @ 11:01 am

I wrote about use of actor based programming for parallel and concurrent programming previously [ 1 , 2 ], where an actor keeps its own thread of execution with a mailbox. Actors communicates to other actors by sending messages that are delivered to its mailbox. In this model, the message passing takes literal form rather than method invocation. I studied Actor based parallel computing in my post graduate research on parallel and distributed field. I learned message passing systems such as Actors, MPI, MPL were much more scalable than shared memory. This describes popularity of languages like Erlang and Scala that has adopted Actor model to tackle concurrency (object-oriented nature in Erlang). According to Ralph Johnson concurrent Erlang is object oriented. Alan Kay has also argued that message passing is more important than objects in object-oriented programming and regrets that he chose the term “object-oriented” instead of “message-passing”. Even Joe Armstrong, who generally dislikes object oriented programming admits similarity between object-oriented programming and Erlang’s message passing.

However, despite effectiveness of message passing in new era of concurrency, I find that pure message passing is a bit intimidating to an average programmer. In this blog, I will show how an object-oriented methods can be used to abstract actor-based message passing. The primary benefit of message passing alongside with immutability is its support of concurrency so the following example will demonstrate use of message passing in multiple threads. Let’s suppose, we are designing a simple chat service to send and receive messages and the message looks like following:

package actor;

public class ChatMessage {
    public final String fromUser;
    public final String toUser;
    public final String message;

    public ChatMessage(String fromUser, String toUser, String message) {
        this.fromUser = fromUser;
        this.toUser = toUser;
        this.message = message;
    }
}

Following is an interface for the chat service:

package actor;

import java.util.Collection;

public interface ChatService {
    /**
     * sends a message to another user * @param message - message object
     */
    @Asynchronous
    public void sendMessage(ChatMessage message);

    /**
     * retrieves messages that were sent to the user. * @param user - target user who received the messages * @return - collection of messages
     */
    public Collection<ChatMessage> getMessages(String user);

    /**
     * remove all messages
     */
    @Asynchronous
    public void clear();

    /**
     * return number of messages
     */
    public long countMessages();

    /**
     * @throws IllegalArgumentException
     */
    public void raiseError() throws IllegalArgumentException;
}

Note that above interface uses “@Asynchronous” annotation for “sendMessage” and “clear” methods. One of the benefit of message-passing is that you can optionally send asynchronous messages. So I defined an annotation to declare a particular method as asynchronous, e.g.

package actor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Asynchronous {
}
Following code implements the chat service in non-thread-safe fashion:
package actor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Simple non-thread-safe implementation of ChatService
 */
public class ChatServiceImpl implements ChatService {
    private long count;
    private Map<String, Collection<ChatMessage>> messagesByUsers;

    public ChatServiceImpl() {
        messagesByUsers = new HashMap<String, Collection<ChatMessage>>();
    }

    /**
     * sends a message to another user * @param message - message object
     */
    public void sendMessage(ChatMessage message) {
        getMessages(message.toUser).add(message);
        count++;
    }

    /**
     * retrieves messages that were sent to the user. * @param user - target user who received the messages * @return - collection of messages
     */
    public Collection<ChatMessage> getMessages(String user) {
        Collection<ChatMessage> messages = messagesByUsers.get(user);
        if (messages == null) {
            messages = new ArrayList<ChatMessage>();
            messagesByUsers.put(user, messages);
        }
        return messages;
    }

    /**
     * remove all messages
     */
    public void clear() {
        messagesByUsers.clear();
    }

    /**
     * return number of messages
     */
    public long countMessages() {
        return count;
    }

    /**
     * @throws IllegalArgumentException
     */
    public void raiseError() throws IllegalArgumentException {
        throw new IllegalArgumentException();
    }
}

Note that above code cannot be used in multi-threading environment. If we were building thread-safe service using Java, we would have to add synchronization or locking such as:

package actor;

import java.util.Collection;

/**
 * Simple thread-safe implementation of ChatService
 */
public class SafeChatServiceImpl implements ChatService {
    private ChatService delegate;

    public SafeChatServiceImpl(ChatService delegate) {
        this.delegate = delegate;
    }

    /**
     * sends a message to another user * @param message - message object
     */
    public synchronized void sendMessage(ChatMessage message) {
        delegate.sendMessage(message);
    }

    /**
     * retrieves messages that were sent to the user. * @param user - target user who received the messages * @return - collection of messages
     */
    public synchronized Collection<ChatMessage> getMessages(String user) {
        return delegate.getMessages(user);
    }

    /**
     * remove all messages
     */
    public synchronized void clear() {
        delegate.clear();
    }

    /**
     * return number of messages
     */
    public synchronized long countMessages() {
        return delegate.countMessages();
    }

    /**
     * @throws IllegalArgumentException
     */
    public synchronized void raiseError() throws IllegalArgumentException {
        delegate.raiseError();
    }
}
Above code demonstrates use of composition to convert a non-thread-safe class into a thread-safe class.

Now the meat of this library is following factory class that converts any Java object into an actor:

package actor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Factory class to convert any POJO class into Actor.
 */
public class ActorFactory {
    private static final int MAIL_BOX_SIZE = 100;

    private static class MethodRequest {
        private final Object object;
        private final Method method;
        private final Object[] args;
        private final BlockingQueue<MethodResponse> replyQueue;

        private MethodRequest(Object object, Method method, Object[] args, BlockingQueue<MethodResponse> replyQueue) {
            this.object = object;
            this.method = method;
            this.args = args;
            this.replyQueue = replyQueue;
        }
    }

    private static class MethodResponse {
        private Object response;
        private Exception exception;

        private MethodResponse(Object response) {
            this.response = response;
        }

        private MethodResponse(Exception exception) {
            this.exception = exception;
        }

        Object getResponse() throws Exception {
            if (exception != null) throw exception;
            return response;
        }
    }

    private static class ActorThread extends Thread {
        private volatile boolean shutdown;
        private BlockingQueue<MethodRequest> queue;

        private ActorThread(BlockingQueue<MethodRequest> queue) {
            this.queue = queue;
            setDaemon(true);
        }

        public void run() {
            while (!shutdown) {
                try {
                    MethodRequest request = queue.take();
                    try {
                        Object response = request.method.invoke(request.object, request.args);
                        if (request.replyQueue != null) {
                            request.replyQueue.put(new MethodResponse(response));
                        }
                    } catch (InvocationTargetException e) {
                        if (request.replyQueue != null) {
                            request.replyQueue.put(new MethodResponse((Exception) e.getCause()));
                        } else {
                            e.printStackTrace();
                        }
                    } catch (Exception e) {
                        if (request.replyQueue != null) {
                            request.replyQueue.put(new MethodResponse(e));
                        } else {
                            e.printStackTrace();
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupted();
                }
            }
        }
    }

    public static Object create(final Class ifaceClass, final Object object) {
        final BlockingQueue<MethodRequest> queue = new ArrayBlockingQueue<MethodRequest>(MAIL_BOX_SIZE);
        new ActorThread(queue).start();
        final InvocationHandler handler = new InvocationHandler() {
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                if (method.isAnnotationPresent(Asynchronous.class)) {
                    queue.put(new MethodRequest(object, method, args, null));
                    return null;
                } else {
                    final BlockingQueue<MethodResponse> replyQueue = new ArrayBlockingQueue<MethodResponse>(1);
                    queue.put(new MethodRequest(object, method, args, replyQueue));
                    return replyQueue.take().getResponse();
                }
            }
        };
        return ifaceClass.cast(Proxy.newProxyInstance(ifaceClass.getClassLoader(), new Class<?>[]{ifaceClass}, handler));
    }

    public static Object createWithoutActor(final Class ifaceClass, final Object object) {
        final InvocationHandler handler = new InvocationHandler() {
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                Object response = method.invoke(object, args);
                return response;
            }
        };
        return ifaceClass.cast(Proxy.newProxyInstance(ifaceClass.getClassLoader(), new Class<?>[]{ifaceClass}, handler));
    }
}
The ActoryFactory uses reflection and proxy features of Java. The client code creates an actor by invoking
public static Object create(final Class ifaceClass, final Object object) {
  ...
}

ChatService service = (ChatService) ActorFactory.create(ChatService.class, new ChatServiceImpl());
      
The create method instantiates a blocking queue that serves as mailbox for the actor and then starts a thread. The create method then instantiates InvocationHandler that intercepts all methods. Finally, the proxy object is returned to the client. When the client invokes any method it is intercepted by the proxy, which then sends the message to the mailbox of the actor. The proxy also checks if the method i defined as asynchronous then it does not wait for the reply. The thread simply waits until there is a message in the mailbox. The message for the actor is defined in MethodRequest that encapsulates reflection information to invoke a method. The actor thread invokes the method using reflection and puts back reply in the queue supplied by the proxy. The proxy waits for the reply and then sends back the reply back to the client. As an actor serves one request at a time, there is no need for locking or synchronization.

Following code demonstrate client test code:

package actor;

import junit.framework.*;

import java.util.Collection;

public class ActorTest extends TestCase {
    private static ChatService service;
    private static final int NUM_THREADS = 100;
    private static final int NUM_MESSAGES = 100;

    protected void setUp() throws Exception {
        super.setUp();
    }

    public void testSendGetMessages() throws Exception {
        for (int i = 0; i < NUM_MESSAGES; i++) {
            final String suffix = Thread.currentThread().getName() + "--" + i;
            ChatMessage janeToAdamMessage = new ChatMessage("jane" + suffix, "adam" + suffix, "hi there" + suffix);
            service.sendMessage(janeToAdamMessage);
            ChatMessage adamToJaneMessage = new ChatMessage("adam" + suffix, "jane" + suffix, "hi there too" + suffix);
            service.sendMessage(adamToJaneMessage);
            Collection<ChatMessage> janeMessages = service.getMessages("jane" + suffix);
            assertEquals(1, janeMessages.size());
            assertEquals("hi there too" + suffix, janeMessages.iterator().next().message);
            Collection<ChatMessage> adamMessages = service.getMessages("adam" + suffix);
            assertEquals(1, adamMessages.size());
            assertEquals("hi there" + suffix, adamMessages.iterator().next().message);
        }
    }

    public void testError() throws Exception {
        try {
            service.raiseError();
            fail("should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException e) {
        }
    }

    public static Test suite() {
        TestSuite suite = new TestSuite(ActorTest.class);
        return suite;
    }

    private static void runTestsWith(ChatService svc, String logMessage) throws InterruptedException {
        service = svc;
        long started = System.currentTimeMillis();
        Thread[] threads = new Thread[NUM_THREADS];
        for (int i = 0; i < NUM_THREADS; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                    junit.textui.TestRunner.run(suite());
                }
            });
            threads[i].start();
        }
        for (int i = 0; i < NUM_THREADS; i++) {
            threads[i].join();
        }
        assertEquals(NUM_THREADS * NUM_MESSAGES * 2, service.countMessages());
        long elapsed = System.currentTimeMillis() - started;
        System.out.println("Completed " + logMessage + " in " + elapsed + " millis");
    }

    public static void main(String[] args) throws Exception {
        runTestsWith(new SafeChatServiceImpl(new ChatServiceImpl()), "thread-safe direct");
        runTestsWith((ChatService) ActorFactory.create(ChatService.class, new ChatServiceImpl()), "Actor model");
        runTestsWith((ChatService) ActorFactory.createWithoutActor(ChatService.class, new SafeChatServiceImpl(new ChatServiceImpl())), "thread-safe reflection");
    }
}
Above class demonstrates a variety of way you can instantiate service class, e.g. by simply invoking the constructor, using reflection and using actors. Note that you cannot simply run non-thread-safe implementation because it would produce incorrect results. For each type of service, the test creates 100 threads that try to send and receive messages. By the end of each test, 200,000 messages are sent and retrieved. Following are runtimes for the service invocation:
 Completed thread-safe direct in 286 millis
 Completed Actor model in 1412 millis
 Completed thread-safe reflection in 693 millis

As expected, using builtin synchronization yields the fastest response, reflection adds some overhead and finally actor based communication adds considerable more overhead. One of the feature of Erlang is its support of seamless networking support. Using an abstraction layer as above can easily be enhanced to start an actor on remote machine. Though, in that case the service will only exist on the remote server. As threads in Java are natives and map to light-weight process, they are much more heavy weight than process in Erlang, which only consumes 300 bytes per process. I have found that native threads are more suitable for CPU-bound processing and green or user-based threads suit well for IO-bound processing. In the end, biggest gain of above design from programmer’s perspective is that the client code looks exactly like any other object oriented and unlike Erlang you get real type safety in message passing. Another big advantage is use of polymorphism, above technique uses dependency inversion principle to interface and implementation separate, thus actual implementation can be changed as needed.

You can download all code from here

November 5, 2008

Ten things I hate about Enhydra Shark

Filed under: Computing — admin @ 12:17 pm

I am trying to use Enhydra Shark at work for implementing a workflow system, but I have been finding a lot of issues with it. Here are ten things that I found absolutely aweful about the Enhydra Shark:

  1. All methods throw Exception as part of the signature instead of specific exceptions.
  2. It uses constants instead of enums.
  3. Many classes use public fields and underscore as part of the name, e.g.
                      public final class AppParameter {
                                     public String the_actual_name = null;
     

    it reminds me of a quote ‘You can write FORTRAN in any language”.

  4. Every single Shark method requires transactions and many of the methods open and close several transactions per method, e.g. real code from another group using Shark:
                userTxn = getUserTransaction();
                userTxn.setTransactionTimeout(600);
                userTxn.begin();
                                                                                                  
                 // Connect to the shark process repository
                 SharkConnection connection = shark.getSharkConnection();
                 connection.attachToHandle(executor.getSharkSessionHandle());
     
                 WfProcess process = loadProcess(connection, userTxn);
                 userTxn.commit();
     
                 userTxn.begin();
                 WfActivity activity = loadActivity(shark, userTxn, connection);
                 userTxn.commit();
                                                                                                  
                 userTxn.setTransactionTimeout(600);
                 userTxn.begin();
                 WMSessionHandle toolAgentSession = toolAgent.connect(connectionInfo);
                 toolAgent.invokeApplication(session, toolAgentSession.getId(),
                             appInfo, toolInfo, null, processInstanceId, assignmentId,
                             parameters, appMode);
                 connection.disconnect();
                 userTxn.commit();
     

    Worst, some of the methods require both local and XA transactions.

  5. It uses its own connection factory so I can’t use apache commons or other connection pool. It defines connection properties in several files, which don’t work as expected, e.g. some parameters are used for upper bound and other for lower bound.
  6. It uses its own transaction factory so I can’t use declarative transactions using annotations or Spring. It is just not designed to work with any other framework.
  7. It requires each JVM to connect with a unique engine name and another team had to generate that name on startup.
  8. Its community does not answer questions (I never got response of my questions) and last activity on the mailing list was 10 months old.
  9. It does not use latest XPDL 2.0, which has been released a few years ago.
  10. Due to explicit connection management and transaction management several times per method, other groups using Shark found a lot of problems with multi-threading, scalability and reliability.

I like the frameworks or languages that follow “principle of least surprise”, on the other hand Shark follows “principle of voodoo magic” to get things working. In the end, I have not completely given up on Shark engine, but I have very low expectations.

October 25, 2008

My gripes about REST services

Filed under: REST — admin @ 11:17 am

I love REST style services because of their simplicity and ease of testing. I have discussed benefits of REST earlier. I have used a number of distributed technologies over seventeen years such as LU6.2 (CICS) for mainframes, BSD Sockets, RPC, CORBA, RMI, JINI, Messaging Middlewares, SOAP, etc. In most of those technologies, you had to use special libraries to interact with the server. I worked in some organizations where I saw real dependency hell or jar hell, where I had to import dozens of client jars from different groups to talk to those services. REST, on the other hand only relies on HTTP (and security) libraries.

I first wrote XML over HTTP style service in late 90s before I knew about the REST term. At the time, I worked as a consultant for government DOTs and built CORBA based system to provide traffic data to media agencies. However, people were scraping our website for the data so I built an XML over HTTP service to download the data with some credentials. I think a lot of people used simplicity of HTTP to build similar services. And many of them didn’t understand REST as put forth by Roy Fielding. Over past few years, a lot of people are promoting real style of REST such as Sam Ruby, Stefan Tilkov, Steve Vinosky and Roy Fielding himself. At the same time, they are chastising people who diverge from their vision.

I have tried building REST style services over last few years and recently I have started building new services that will be used for entire organization. As, these services will need to support large number of transactions, performance and scalability are critical. Also, these services need to support batch of requests. In my older blog, I discussed commandments for writing service and wrote about importance of batch requests for scalability. That requirement changes a few things, for example instead of taking advantage of request parameters in HTTP, I had to use XML for input request and had to use XML for response. Though, this style is suitable for POST or PUT where you are expecting to read request as a file but is unnatural for GET types.

Another tenet of REST style services is resource. In this style, you interact with the service similar to how users interact with a web site, i.e., you click on links to go to another page, which returns more links and so on. However, this style in service adds network communication. For example, in one of the service for workflow I had to return active tasks for a particular workflow. In true REST style, I would have to return a hyperlink for each task instead of contents of task and the client would have to ask server for task content by hitting the resource for the task. As, you might guess this adds significant network latency so I am being practical instead of purest and as a result, I am returning task contents. Also, the service allows you to pass requests for multiple workflows and returns a single response for all workflows.

I used similar style when using messaging middlewares that allowed serving batches of requests in a single message. I found messaging middlewares offered more flexible options, e.g. you can design an aggregator service that waits for a few seconds for incoming requests and then puts them in a single request to another service that serve them. These kind of batch services are integral for building scalable systems. I have discussed some of these limitations in earlier blog, especially its lack of push based architecture. Though there are some workaround for push such as long-lived HTTP connection that are difficult to use behind firewall, comet style or reverse Ajax based communication, which is limited and more recently reverse http, which is too new to apply in real applications. Perhaps, messaging standards like XMPP can fill this gap.

I find that IT industry is largely driven by a single minded attitude where every new technology, language or process is adopted by bandwagon of people who just repeat each other’s words without understanding. For example, I have seen similar attitude from agile folks, folks from object oriented programming, aspect oriented programming, metaprogramming or dynamic programming, design patterns, etc. In the end, I believe you have to be practical instead of purest and as always answer to every question in IT is “it depends”, i.e., there is no single universal solution.

October 22, 2008

Developing REST based services using JSR 311

Filed under: Java — admin @ 1:28 pm

Recently, I had to write a few services using REST style in Java. Though I have developed such services in past either using Java Servlet APIs, but I wanted to find something better. I had found writing REST style services in Ruby on Rails a breeze and I wanted something as testable and easy to configure. I found a new JSR 311 that does exactly that. Similar to EJB 3.0 and Servlet 3.0 trend, it allows you to write REST services using annotations. I found an open source project that implements JSR 311 and just released 1.0. I found most of the documentation was Maven and Glassfish driven and I wanted to simply try on Tomcat and Ant so here is how I did it:

Download and Install

First, download following jar libraries (you can see that I am using jars from maven repository because Jersey’s wiki was missing jars or pointing to old version):

Developing

My application used models to describe business object, DAOs for database access and I didn’t want to pollute my business objects with REST annotations so I created two new packages for resources and services. Here is a simple example that follows this separation of concerns:

Business Objects (Model)

The model simply consists of a contact class that stores contact information for a person.

 
 package rest;
 
 public class Contact {
     private final String name;
     private final String email;
     private final String address;
 
     public Contact(final String name, final String email, final String address) {
         this.name = name;
         this.email = email;
         this.address = address;
     }
 
 
     public String getName() {
         return name;
     }
 
     public String getEmail() {
         return email;
     }
 
     public String getAddress() {
         return address;
     }
 }
 

Data Access Layer

The data access layer simply uses a hashmap for storing and accessing these contacts, e.g.

 
 package rest;
 
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
 public class ContactDao {
     private static Map repository = new HashMap();
 
     public boolean save(Contact c) {
         boolean created = repository.get(c.getName()) != null;
         repository.put(c.getName(), c);
         return created;
     }
 
     public boolean delete(String name) {
         return repository.remove(name) != null;
     }
 
     public Contact get(String name) {
         return repository.get(name);
     }
 
     public Collection getAll() {
         return repository.values();
     }
 }
 
 

Resources

For resources, I defined ContactResource that adds XML annotations to convert Contact into XML and ContactsResponse for returning complete XML response, e.g.

 
 package rest;
 import javax.ws.rs.core.UriInfo;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
                                                                                                                                                       
 
 @XmlAccessorType(XmlAccessType.PROPERTY)
 @XmlRootElement(name = "Contact")
 public class ContactResource {
     private UriInfo uriInfo;
     private Contact contact;
 
     public ContactResource(final UriInfo uriInfo, final String name, final String email, final String address) {
         this.uriInfo = uriInfo;
         this.contact = new Contact(name, email, address);
     }
 
 
     public ContactResource(final Contact contact) {
         this.contact = contact;
     }
 
 
     ContactResource() {
     }
 
 
     public JSONObject toJson() throws JSONException {
         return new JSONObject()
             .put("name", contact.getName())
             .put("email", contact.getEmail())
             .put("address",contact.getAddress());
     }
 
     @XmlElement(name = "Name")
     public String getName() {
         return contact.getName();
     }
 
     @XmlElement(name = "Email")
     public String getEmail() {
         return contact.getEmail();
     }
 
     @XmlElement(name = "Address")
     public String getAddress() {
         return contact.getAddress();
     }
 }
 
 
 

 
 package rest;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 
 
 @XmlAccessorType(XmlAccessType.PROPERTY)
 @XmlRootElement(name = "ContactsResponse")
 public class ContactsResponse {
     private String uri;
     private String status;
     private Collection contacts;
 
     public ContactsResponse(String uri, String status, Collection contacts) {
         this.uri = uri;
         this.status = status;
         this.contacts = new ArrayList();
         for (Contact contact : contacts) {
             this.contacts.add(new ContactResource(contact));
         }
     }
 
     public ContactsResponse(String uri, String status, Contact contact) {
         this(uri, status, contact == null ? new ArrayList() : Collections.singleton(contact));
     }
 
     ContactsResponse() {
     }
 
     @XmlElement(name = "Uri")
     public String getUri() {
         return uri;
     }
     public void setUri(String uri) {
         this.uri = uri;
     }
     @XmlElement(name = "Status")
     public String getStatus() {
         return status;
     }
     public void setStatus(String status) {
         this.status = status;
     }
 
     @XmlElement(name = "Contacts")
     public Collection getContactResources() {
         return contacts;
     }
     public void setContactResources(Collection contacts) {
         this.contacts = contacts;
     }
 }
 
 

Service

Here is the meat of JSR 311 that defines annotations for the REST based web service, i.e.,

 
 package rest;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Collection;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.springframework.context.annotation.Scope;
 
 import com.sun.jersey.api.spring.Autowire;
 
 @Path("/contacts/")
 @Produces( { "application/json", "application/xml" })
 @Consumes( { "application/json", "application/xml" })
 @Scope("singleton")
 @Autowire
 public class ContactService {
     private final ContactDao contactDao;
     @Context UriInfo uriInfo;
     @Context Request request;
 
     public ContactService(ContactDao dao) {
         this.contactDao = dao;
     }
 
     public ContactService() {
         this(new ContactDao()); // this will be injected in real-app
     }
 
     /**
      * create contact
      */
     @PUT
     @Consumes("*/*")
     @Produces("application/xml")
     @Path("{name}")
     public Response createcontact(
             @PathParam("name") String name,
             @FormParam("email") String email,
             @FormParam("address") String address) {
         Contact contact = new Contact(name, email, address);
         final boolean newRecord = contactDao.save(contact);
         if (newRecord) {
             try {
                 URI uri = uriInfo != null ? uriInfo.getAbsolutePath()
                         : new URI("/contacts/");
                 return Response.created(uri).build();
             } catch (URISyntaxException e) {
                 throw new RuntimeException("Failed to create uri", e);
             }
         } else {
             return Response.noContent().build();
         }
     }
 
     /**
      * deletes contact 
      * 
      */
     @DELETE
     @Consumes("*/*")
     @Path("{name}")
     public Response deletecontact(@PathParam("name") String name) {
         boolean deleted = contactDao.delete(name);
         if (deleted) {
             return Response.ok().build();
         } else {
             return Response.status(404).build();
         }
     }
 
     /**
      * @return contact in XML format
      */
     @GET
     @Consumes({"text/xml", "application/xml"})
     @Produces("application/xml")
     @Path("{name}")
     public ContactsResponse getcontactByXml(
             @PathParam("name") String name) {
         Contact contact = contactDao.get(name);
         String uri = uriInfo != null ? uriInfo.getAbsolutePath().toString() : "/contacts/";
         return new ContactsResponse(uri, "success", contact);
     }
 
     /**
      * @return contact in JSON format
      */
     @GET
     @Consumes("application/json")
     @Produces("application/json")
     @Path("{name}")
     public JSONArray getcontactByJson(@PathParam("name") String name) throws JSONException {
         Contact contact = contactDao.get(name);
         JSONArray arr = new JSONArray();
         arr.put(new ContactResource(contact).toJson());
         return arr;
     }
 
     /**
      * @return all contacts in XML format
      */
     @GET
     @Consumes({"text/xml", "application/xml"})
     @Produces("application/xml")
     public ContactsResponse getAllByXml() {
         Collection contacts = contactDao.getAll();
         String uri = uriInfo != null ? uriInfo.getAbsolutePath().toString() : "/contacts/";
         return new ContactsResponse(uri, "success", contacts);
     }
 
     /**
      * @return contacts in JSON format
      */
     @GET
     @Consumes("application/json")
     @Produces("application/json")
     public JSONArray getAllByJson() throws JSONException {
         Collection contacts = contactDao.getAll();
         JSONArray arr = new JSONArray();
         for (Contact contact : contacts) {
             arr.put(new ContactResource(contact).toJson());
         }
         return arr;
     }
 }
 
 

A few things to note:

  • @Path defines the URI used for accessing the service
  • I am using @PUT to store contacts (as the user is creating new URI as opposed to @POST where the application uses same URI). Also, I don’t have any method for update (which uses PUT) as I already am using PUT and create method simply updates the contact if it already exist.
  • @PathParam is retrieved from the URI itself, e.g. /contacts/myname
  • @FormParam is retrieved from POST form submission
  • I can use the same URI and return different type of data based on Content-Type, e.g. when user sets it to application/xml or text/xml I return XML content and when user sets it to application/json I return JSON format.
  • To return list of contacts I skip the name and simply use /contacts/

Servlet Configuration

I added servlet to handle REST requests to web.xml, e.g.

     <servlet>
         <servlet-name>RestServlet</servlet-name>
         <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
         <init-param>
             <param-name>com.sun.jersey.config.feature.Redirect</param-name>
             <param-value>true</param-value>
         </init-param>
         <init-param>
             <param-name>com.sun.jersey.config.feature.ImplicitViewables</param-name>
             <param-value>true</param-value>
         </init-param>
         <init-param>
             <param-name>com.sun.jersey.config.property.packages</param-name>
             <param-value>rest</param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>
     <servlet-mapping>
         <servlet-name>RestServlet</servlet-name>
         <url-pattern>/svc/*</url-pattern>
     </servlet-mapping>
 

I used Spring to inject DAOs in real application but if you don’t need it then replace com.sun.jersey.spi.spring.container.servlet.SpringServlet with com.sun.jersey.spi.container.servlet.ServletContainer.

Also note that com.sun.jersey.config.property.packages defines package name of Java classes that defines service classes.

Deploying

I am assuming you already know how to package a war file and deploy it to application server such as Tomcat.

Testing it

Unit Testing it

A big advantage of JSR 311 is ease of test, e.g. here is a sample unit test:

 
 package rest;
 import javax.ws.rs.core.Response;
 
 import junit.framework.TestCase;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONObject;
 
 import com.sun.jersey.api.NotFoundException;
 
 public class ContactServiceTest extends TestCase {
     private ContactService service;
 
     @Override
     protected void setUp() throws Exception {
         service = new ContactService();
     }
 
     public void testCreateContactWithGetContactByXml() {
         final String name = "shahbhat";
         final String email = "shahbhat@myhost";
         final String address = "shahbhat address ";
 
         Response response = service.createContact(name, email, address);
         assertEquals(201, response.getStatus());
         assertNull(response.getEntity());
 
         // recreate the same mapping and it should return no content
         response = service.createContact(name, email, address);
         assertEquals(204, response.getStatus());
         assertNull(response.getEntity());
 
         ContactsResponse contactResponse = service.getContactByXml(name);
         assertEquals(1, contactResponse.getContactResources().size());
         ContactResource contactResource = contactResponse.getContactResources().iterator().next();
         assertEquals(name, contactResource.getName());
         assertEquals(email, contactResource.getEmail());
         assertEquals(address, contactResource.getAddress());
     }
 
     public void testCreateContactWithGetContactByJson() throws Exception {
         final String name = "shahbhat";
         final String email = "shahbhat@myhost";
         final String address = "shahbhat address ";
 
         Response response = service.createContact(name, email, address);
         assertEquals(201, response.getStatus());
         assertNull(response.getEntity());
 
         JSONArray jsonArray = service.getContactByJson(name);
         assertEquals(1, jsonArray.length());
         JSONObject json = jsonArray.getJSONObject(0);
         assertEquals(name, json.getString("name"));
         assertEquals(email, json.getString("email"));
         assertEquals(address, json.getString("address"));
     }
 
     public void testDeleteContact() {
         final String name = "shahbhat";
         final String email = "shahbhat@myhost";
         final String address = "shahbhat address ";
 
         Response response = service.createContact(name, email, address);
         assertEquals(201, response.getStatus());
         assertNull(response.getEntity());
 
         ContactsResponse contactResponse = service.getContactByXml(name);
         assertEquals(1, contactResponse.getContactResources().size());
         ContactResource contactResource = contactResponse.getContactResources().iterator().next();
         assertEquals(name, contactResource.getName());
         assertEquals(email, contactResource.getEmail());
         assertEquals(address, contactResource.getAddress());
 
         response = service.deleteContact(name);
         assertEquals(200, response.getStatus());
 
         contactResponse = service.getContactByXml(name);
         assertEquals(0, contactResponse.getContactResources().size());
 
         //
         response = service.deleteContact(name);
         assertEquals(404, response.getStatus());
 
     }
 
     public void testGetAllContactByXml() {
         service.createContact("shahbhat", "shahbhat email", "shahbhat address");
         service.createContact("bill", "bill email", "bill address");
 
         ContactsResponse contactResponse = service.getAllByXml();
         assertEquals(2, contactResponse.getContactResources().size());
         for (ContactResource contactResource : contactResponse.getContactResources()) {
             if ("shahbhat".equals(contactResource.getName())) {
                 assertEquals("shahbhat email", contactResource.getEmail());
                 assertEquals("shahbhat address", contactResource.getAddress());
             } else if ("bill".equals(contactResource.getName())) {
                 assertEquals("bill email", contactResource.getEmail());
                 assertEquals("bill address", contactResource.getAddress());
             } else {
                 fail("unknown contact " + contactResource);
             }
         }
 
         service.deleteContact("shahbhat");
         service.deleteContact("bill");
 
         contactResponse = service.getAllByXml();
         assertEquals(0, contactResponse.getContactResources().size());
     }
 
 
     public void testGetAllContactByJson() throws Exception {
         service.createContact("shahbhat", "shahbhat email", "shahbhat address");
         service.createContact("bill", "bill email", "bill address");
 
         JSONArray jsonArray = service.getAllByJson();
         assertEquals(2, jsonArray.length());
 
         for (int i=0; i<2; i++) {
             JSONObject json = jsonArray.getJSONObject(i);
             if ("shahbhat".equals(json.getString("name"))) {
                 assertEquals("shahbhat email", json.getString("email"));
                 assertEquals("shahbhat address", json.getString("address"));
             } else if ("bill".equals(json.getString("name"))) {
                 assertEquals("bill email", json.getString("email"));
                 assertEquals("bill address", json.getString("address"));
             } else {
                 fail("unknown contact " + json);
             }
         }
         service.deleteContact("shahbhat");
         service.deleteContact("bill");
 
         jsonArray = service.getAllByJson();
         assertEquals(0, jsonArray.length());
     }
 }
 

Functional Testing it

Once deploy, you can use curl to functionally test it (though there are other automated tools available as well), e.g

Creating Contact

 curl -X PUT -d "email=myemail&address=myaddress"  http://shahbhat.desktop:8080/svc/contacts/bhatti
 

It will create a contact and to retrieve it, use

 curl http://shahbhat.desktop:8080/svc/contacts/bhatti
 

It should return

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ContactsResponse><Contacts><Address>myaddress</Address><Email>myemail</Email><Name>bhatti</Name></Contacts><Status>success</Status><Uri>http://shahbhat.desktop:8080/svc/contacts/bhatti</Uri></ContactsResponse>
 

To get JSON format use

 curl --header "Content-Type: application/json" http://shahbhat.desktop:8080/svc/contacts/bhatti
 

and it should return

 [{"name":"bhatti","email":"myemail","address":"myaddress"}]
 

You can create another contact e.g.

 curl -d "email=billemail&address=billaddress"  http://shahbhat.desktop:8080/svc/contacts/bill
 

Now to get all contacts use

 curl http://shahbhat.desktop:8080/svc/contacts/
 

and it will return

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ContactsResponse><Contacts><Address>myaddress</Address><Email>myemail</Email><Name>bhatti</Name></Contacts><Contacts><Address>billaddress</Address><Email>billemail</Email><Name>bill</Name></Contacts><Status>success</Status><Uri>http://shahbhat.desktop:8080/svc/contacts/</Uri></ContactsResponse>
 

And to get JSON format use

 curl --header "Content-Type: application/json" http://shahbhat.desktop:8080/svc/contacts/
 

which will return

 [{"name":"bhatti","email":"myemail","address":"myaddress"},{"name":"bill","email":"billemail","address":"billaddress"}]
 

Conclusion

I found this approach is easily testable with standard unit test and easy to develop. Though, there are few glitches, e.g. @QueryParam only works with GET and if you are POSTing to something like /uri?x=yy then you won't see query parameters. But, overall I am happy with the outcome and will continue to use this framework.

October 18, 2008

Concurrency Constructs

Filed under: Computing — admin @ 11:43 am

With the proliferation of multi-cores, concurrency has been a hot topic for past few years. I described a few ways to tackle concurrency in my blog earlier this year. As I mentioned in my blog, this problem is nothing for scientific and research community. Also, many languages have had devised numerous constructs to tackle these abstractions and other languages are adding support for concurency. I will go over some of these abstractions here:

Processes

All modern operating systems support preemptive multitasking and processes have been simple way to add concurrency. For example, this technique is used by Apache web server that launches multiple processes and serve thousands of clients at a time. There are also a number of system primitives for inter-process communication such as shared memory, sockets, pipes and other forms of middlewares and peer to peer technology. This technique is specially suitable for many scripting languages that don’t have concurrency support such as Perl, Ruby, CPython, etc. Despite their scripting nature, these languages are highly productive. For example, much of Amazon’s retail website is built using Perl/Mason and uses multiple processes served by FastCGI for handling concurrent requests. Though, Ruby and Python support green threads, but are not designed for concurrency. For example, Global Interpreter Lock (GIL) in Python only allows one thread to execute at a time. Similarly, Ruby has Global VM lock that also allows one thread to execute at a time. These limitations have also effected kind of applications you can built. For example, one of criticism of Ruby on Rails framework has been its lack of concurrency. Though, there have been a number of solutions that tackle this problem by multi-processing such as clusters of mongrel, FastCGI, etc.

This model is also used by Fork/Join, Map/Reduce, Master-Slave and Leader/Follower style of parallel programming, where the master process creates work and distributes work to workers, who work on it. There are a plenty of libraries and frameworks available for this such as Globus, Hadoop, MPI/MPL, PVM and Fork/Join in Java 7.

Kernel Threads

Many languages support kernel threads that are mapped to lightweight processes (LWP) and scheduled by the operating systems. The operating system context switches between threads using time-slicing that give perception of concurrency. Posix compliant operating systems offer a number of solutions for inter-thread communication and synchronization such as mutex, semaphores, condition variables. Many languages offer support for high level synchronization such as concurrent library in Java.

Green Threads/Fibers

As opposed to native threads, green threads run in user space and scheduled by using yield to allow other thread/fiber to execute. As user threads or fibers rely on collaboration, they are easily subject to starvation. Some languages encapsulate blocking I/O with nonblocking I/O and automatically yield fiber when they make blocking call. Effective use of fibers can help applications scale more than multi-processing or multi-threading, which are generally limited by the system resources. For example, in a performance comparison between Apache and Yaws, where latter was built in Erlang that uses user processes was able to scale upto 80,000 concurrent connections whereas Apache died at around 4000 connections. Ruby 1.9 has just added support for fibers, which can be used to build streams, e.g.

 fib = Fiber.new do  
    x, y = 0, 1 
    loop do  
     Fiber.yield y 
     x,y = y,x+y 
    end 
   end 
   20.times { puts fib.resume } 
 

Streams

Streams are sort of iterators over infinite lists and often used in functional languages, though many imperative programming languages now support them to create infinite lists. You can find a number of examples of Strams in languages like Groovy, Scala, Haskell, etc. Python offers similar capability via generators that contain yield keyword, which causes compiler to suspend generator until next() method of generator is called. For example,

 def generate_ints(N):
     for i in range(N):
         yield i
 
 >>> gen = generate_ints(2)
 >>> gen.next()
 >>> gen.next()
 

Coroutines

Coroutines are similar user threads and unlike subroutines, they have multiple entry and exit points. They are often built using contiuations or generators. In C, setjmp and longjmp can be used to implement coroutine. Ruby 1.9 added support for fibers that are more accurately semi-coroutines [pp 167].

Continuation

Continuation work like saving game at a checkpoint and resuming it. Traditionaly goto were used to implement continuations, though a number of languages have native support for continuations such as Scheme, Smalltalk, Ruby (callcc), Scala, C (setjmp/longjmp), etc. Though, they are not without problems but Seaside web framework based on Smalltalk has shown innovative way to write web applications using continuation passing style.

Actor model

I was introduced to actor model in mid mid 90s when working on graduate and post-graduate work. An actor has its own thread of execution with a mailbox. It communicates to other actors by sending messages that are delivered to its mailbox. Erlang, a language designed for concurrency, is based on actor model and more recently Scala has adopted actor model as well. When I worked for high performance computing (HPC) area in 90s, I used SGI systems that were built using NUMA based shared memory and messaging passing systems/libraries such as MPI, MPL, etc. I found message passing systems were much more scalable than shared memory, so I believe this style of programming will have best chance of succeeding. Though, I admit I found converting algorithms into message passing style is not easy.

Reactive or Event driven style

In reactive or event driven style, systems communicate by sending or listening on events. It’s sort of flip-style of threading, instead of creating new thread for each new concurrent task, it uses a fixed number of threads that cooperate. It is more scalable than multi-threading (kernel) as native threads are limited by available resources and context switching is expensive. For example, event-driven Mongrel server is much more scalable than Mogrel server. A number of J2EE application servers such as Glassfish, Jetty and Tomcat 6 have adopted Grizzly framework that uses asynchronous I/O to implement reactive style servers.

Software Transactional Memory

It’s difficult to write correct program using shared memory and as it requires proper locking of shared data and special attention to thread starvation and deadlock issues. A number of languages like Clojure, Haskell and Fortress have added support for software transactional memory that provide implicit locking through transactions. I have not used this style of programming but it seems to make writing concurrent applications easy. Though, I believe scalability with shared memory may only help with systems upto a few cores or processors.

TupleSpace based model

In tuple space, processes communicate to each other by storing messages in tuple spaces. The tuple space provides simple APIs like get, put, read and eval. Where get/read are blocking operations to implement dataflow based application and eval creates a new process to execute a task and store result in the tuple space. I built a similar system called JavaNOW, though there are a number of open source and commercial frameworks availeble such as JavaSpaces, GigaSpaces, Blitz.

Declarative concurrency

I heard recently Anders Hejlsberg and Guy Steele talked about concurrency and Anders suggested declarative concurrency where the programmer indicates parts of the applications that can be run concurrently. In a way, it is similar to compiler based parallelism used in High performance Fortran or Parallel Fortran that used data flow analysis to create parallel applications.

In nutshell, I find that more and more languages are adding constructs and frameworks to address concurrency and we will have to get used to these constructs to write programs that are future proof.

« Newer PostsOlder Posts »

Powered by WordPress