Friday, March 18, 2011

Detecting Concurrency Problems using TestNG

With the emphasis on product quality, unit and integration testing is gaining widespread momemtum, and TestNG seems to have become the defacto standard for writing these tests. A great feature in TestNG - that is often missed in all the JUnit vs. TestNG comparisons on the web - is the ability to execute a test in parallel using multiple threads. This feature is pretty useful in detecting concurrency problems in the code. A developer could write a test at the Controller level that executes the Service and DAO (Data Access Object) code, and if this code contains any concurrency constructs for thread-safe access, then the TestNG threads will detect concurrency problems such as race conditions and deadlocks.

Using the TestNG framework, it is relatively easy to specify that a given test be executed in parallel. This can be done using additional parameters to the @Test annotation.

As an example, consider the following test:

@Test (threadPoolSize = 3, invocationCount = 9, timeOut = 1000)
public void myTest() {
// write your test here
}

The threadPoolSize determines the number of threads that are used to execute the tests, and the invocationCount determines the total number of times that the test is executed. The timeOut parameter - 1 second in the above example - guarantees that none of the threads will block on the others, in effect avoiding a deadlock. However, this is not something that a developer should try to avoid, because if there is a deadlock, it is better to detect it sooner that later. Therefore, in general, it is better of omit the timeOut parameter.

With the advent of these super-easy testing frameworks and the value-proposition that they bring, most developers are jumping on the unit/integration testing bandwagon. This is great for the software engineering field in general, as eventually some day bugs will not be considered as the norm in a software product.

Wednesday, February 16, 2011

Ant build under Eclipse - Error running javac.exe compiler

I ran into this problem twice, where the ant build script executes perfectly under the command prompt, but fails under Eclipse with the message - "Error running javac.exe compiler". It took me a while to figure out the problem, and it turns out that the problem arises from the javac task in ant. If the task contains an attribute fork="yes", then ant tries to spawn a new instance of javac to compile the source. Now if the referenced Java library in the project is a JRE, Ant can't find javac and therefore gives the above-mentioned error. If the parameter is changed to fork="no", then the build completes successfully, but a better solution is to include the JDK - and not the default JRE - as the referenced library for the project.

Tuesday, December 14, 2010

Concurrency - Optimistic vs. Pessimistic Approach

Whenever developers think of concurrency, the first thing that comes to their mind is semaphores and mutex that provide serial access to a critical section of code. Most languages provide an extensive API for thread synchronization and very often folks just start using the synchronization primitive without much thought into the what they are trying to accomplish. As an example, the most abused concurrency primitive is the "synchronized" keyword provided by Java, which is often put anywhere and everywhere that a developer feels that there is a possibility of concurrent access. "Synchronized" is a monitor, and as such, it doesn't require explicit lock and release statements, as a semaphore or mutex would. This is why perhaps people generally add the synchronized keyword to methods, whenever they feel that the method does something that needs protection from concurrent access. It is not uncommon to come across instances of deeply nested method calls, with each method having a synchronized keyword in the declaration. Synchronized implicitly obtains and releases a lock on the object every time the method with the modifier is called. This is a computationally intensive operation that makes the application slower than it needs to be. Now Java 5 provides some powerful concurrency primitives, but before jumping the bandwagon and starting to use those primitives all over the code, it is better to evaluate the concurrency needs of the application that is being built.

There are generally two approaches to handle concurrency in a software program, each with its pros and cons. An engineering team should consider and evaluate both approaches and decide to use either one, or both, based on the needs of the product they are building. The two approaches are:

Optimistic approach: In this approach, there are no semaphores or mutex to protect a critical section of code that handles the shared data. There is a master copy of the shared data, with each thread getting a local copy to work on. When a thread wishes to update its local copy of the data, the local copy is compared with the master copy to ascertain if the data has been modified since it was last read by the thread. If not, then the update is successful; however, if the data has indeed been modified, then a concurrent modification exception is thrown and the user is expected to re-apply the modifications on the new copy of the data. This approach is common in databases, and it is also used by Java for collections that are not thread-safe by default (HashMap, HashSet, ArrayList).

Pros:
  1. Due to the absence of semaphores and mutex, the application exhibits better performance and scalability.
  2. The modifications of the first thread that performs the update are persisted, whereas the other threads are informed of the change in data and requested to repeat the update on the modified data.
Cons:
  1. User may need to perform the modifications again, if another thread updates the data after it was read by the user thread. This may cause frustration in a multi-user heavy-transaction environment.

Pessimistic approach: This approach requires the use of a semaphore, mutex or monitor to ensure serial access to a critical section in code. In this approach, a single copy of the data is maintained and serial access is provided to threads requesting access to this data. When a given thread enters the critical section, no other thread is allowed to access this data until the thread exits the critical section.

Pros:
  1. Suitable for situations where there is no shared data, however, serial access need to be provided to a shared resource, such as a socket.
Cons:
  1. If the semaphore or mutex is not released properly, it leads to a memory leak. This degrades the application performance over time.
  2. Another problem with semaphores and mutex is the possibility of a deadlock, which occurs when a circular dependency is introduced between two threads, each requesting a lock on a resource that is currently held by the other.
  3. Since serial access is provided to concurrently executing threads that wish to update shared data, the changes made by the last thread are persisted, whereas the other threads are unaware of what happened to their modifications.
A given application may use either one, or both, of the above-mentioned approaches. For shared data access among multiple threads, it is preferable to use the optimistic approach, whereas, for shared resource access (socket etc.), it is generally better to use the pessimistic approach.


Monday, November 29, 2010

Software Engineering - Art or Science?

I have been pondering over this question for a while now. In my opinion, Software Engineering is both an Art and a Science, as aspects from both the fields are relevant in designing a software product. I guess the association to science is easier to understand, as there is direct relevance to the scientific method, which in simple form consists of the following steps:
  • Formulate the hypothesis.
  • Conduct the experiment, collect the results and verify if the hypothesis is correct.
  • If desirable results are not obtained, make changes to certain parameters, and repeat.
This is how we test our software too:
  • Formulate what a program is intended to do.
  • Run the program, collect the results and check if it matches the expectations.
  • If not, tweak the program code or input, and repeat.
While the association of software engineering to the scientific side may be a bit obvious, it is the artistic elements that are difficult to relate to. An obvious question is - what is artistic about lines of program code or instructions that are always difficult to read and comprehend? In my opinion, the artistic elements of software engineering are more in the design of the program than in the actual code itself, however, that is not to say that good code doesn't have any artistic elements.

A program that considers the following design elements is generally considered more artistic than one that doesn't.
  • Consider a component-based design that follows the high-cohesion-low-coupling paradigm, with a well defined API that specifies the component contract.
  • While designing classes, consider the responsibility of each class and ensure that a class doesn't do too much or too little.
  • Follow a general naming convention for components and classes. A good guideline for the MVC (Model-View-Controller) architectural style is to have classes with the names such as - xxxxView, xxxController, xxxManager. Classes that are a part of a component that offers a service could be named as xxxService; as an example - DatabaseService, LoggingService etc.
  • Consider using design patterns when possible, as they offer a consistent - and often familiar - solution to a known problem.
  • Have a long-term view while designing the components and classes. Remember, a good artist paints what she sees, whereas a great one paints from her imagination, what no one else sees.
There certainly are artistic elements to be considered while implementing the code too, some of which are:
  • Follow the same structure while laying out the source code. Always have a comment block for every class and method.
  • Avoid methods that are too long. A general guideline is to have methods that generally fit within a screen length for the new high-resolution monitors.
  • While doing defensive null checks, consider having return statements when the object is null, instead of having deeply nested "if" statement that contain logic when the object is not null.
  • Consider using a static analysis tool, so that consistent coding guidelines and good coding practices are enforced throughout the code.
While doing all the above may not make your program work any better than it currently does, it would certainly improve the readability and maintainability of the code, enabling others to understand it and extend it. And, if others can understand and relate to your work, then there is definitely something artistic about it.

Wednesday, September 29, 2010

REST vs. SOAP

There is a lot of information on the web pertaining to REST; however, there is nothing relevant that compares REST to SOAP. This post contains a brief introduction to REST, and provides a REST vs. SOAP comparison. The reader is expected to have some familiarity with SOAP.

REST(Representational State Transfer) is an architectural style for networked applications, which is based on the Ph.D. dissertation of Roy Fieldings. REST introduces a different paradigm for web services, which are traditionally thought of as a RPC-based services, using a SOAP+WSDL combination. Web services written using the REST style adhere to the Resource Oriented Architecture (ROA) paradigm, a term given to a set of rules for designing such services. Typically, a user of a web application progresses through a series of pages or URLs, resulting in the state being transferred from one traversed resource to the next. REST attempts to formalize this model using four important concepts - resources, their names, their representations and the links between the resources. All RESTful services are judged by four important properties – addressability, statelessness, connectedness and the uniform interface.

REST architectural rules are also called “constraints”. Unconstrained architecture allows method calls, RPC and other messages that are understood by a specific component or module (client or server) involved in the interaction. REST eliminates ad-hoc messages and radically shifts the focus of API development towards defining pieces of information that can be retrieved and manipulated. The motivation for REST was to create an architectural model for how the web should work, such that it would serve as the guiding framework for the web protocol standards. REST prescribes the use of standards such as HTTP, URI and XML.

REST objects are called “resources”, with the information in resources being called “state”. This information has to be encoded to include it in a message, this encoding are called “representation”. Method invocations transfer state in representations. The following is a list of the HTTP methods and their implied meaning in REST:

· GET to an identifier means, give me your information.

· PUT to an identifier means, replace your information with the new one provided.

· POST adds new information.

· DELETE removes the information.

Resources are identified by URIs and manipulated through their representation. HTTP is a compliant RESTful protocol; however, it is possible to apply REST concepts to other protocols and systems. The statelessness property of REST ensures that any resource can be served by any server, thereby making REST solutions highly scalable. REST services may be described using WSDL or WRDL (Web Resource Description Language). The following are the characteristics of a REST-based system:

· Client-Server: A pull-based interaction style.

· Stateless: Request from client to server must contain all the information necessary.

· Cache: To improve network efficiency, responses must be capable of being labeled as cacheable or non-cacheable.

· Uniform interface: All resources are accessed via the generic HTTP methods.

· Named Resources: Every resource in a RESTful service is appropriately named.

· Interconnected resource representation: Enables a client to progress from one state to another.

A logical question is: how is REST different from SOAP? SOAP offers a RPC-oriented paradigm, where the participating components are interacting in a closed environment, using a proprietary API. REST offers a solution based on commonly used web standards and offers a more open solution, where even unknown clients can connect to a server component and use its capabilities using standard HTTP requests / responses. In addition to this basic difference in the two approaches, the following are some additional differences between these two paradigms.

· Security: A proxy server can look at the REST request and determine the resource being requested, based on which the request may be allowed or denied. Whereas for the SOAP message, the resource is identified inside the envelope, which is not accessible, unless the SOAP message is written using RDF (Resource Description Framework) or DAML (DARPA Agent Markup Language). Therefore, for a SOAP-based web service, security is generally built into the proprietary API.

· State Transitions: Each resource representation received by the client causes it to transition to the next state. The decision about which link to navigate is either hard-coded in the client or determined dynamically using XLINK (xlink:role). In a SOAP network, state transitions are always hard-coded in the client.

· Caching: Network communication has always been a bottleneck, and therefore the HTTP headers can contain a request to cache data. SOAP is always a HTTP POST and since the SOAP URI is directed to the server and not the resource, no caching is possible with SOAP. However, since REST uses the generic HTTP interface, it is possible for intermediate proxies to cache the results from a RESTful service call, in an effort to achieve a better performance.

· Evolving the Web (Semantic Web): It is envisioned that eventually the web will be accessed by people and computers alike, each being capable of intelligently processing the data returned by services on the web. In this vision of the Semantic Web, every resource has a unique URI and is accessible using standard HTTP methods. SOAP is not consistent with the Semantic Web vision, whereas REST is completely aligned with it.

· Generic Interface: Using REST, access to every resource is made using HTTP GET, POST, PUT and DELETE. With SOAP, the application needs to define its own proprietary methods.

· Interoperability: With interoperability, the key is standardization. Web has standardized on certain things, such as URI for address and naming, HTTP for generic resource interface and HTML/XML/GIF/JPEG for resource representation. REST uses these standards, whereas SOAP depends on customizations. SOAP clumping of resources behind a single URI is contrary to the vision for the web. SOAP is best utilized for closed systems, where all participants are known beforehand.

Wednesday, September 8, 2010

FindBugs Warning - Exception is caught when exception is not thrown

Performing static analysis of a Java code-base on a regular basis is an extremely useful exercise, and I have found FindBugs to be an extremely useful and worthy tool. One particular warning raised by FindBugs - exception is caught, when exception is not thrown - may appear to be a false positive at first, however, the tool basically recommends catching specific exception types, instead of having a "catch all" exception clause that catches the base Exception class.

The reason for this is pretty simple - catching the base Exception class will also catch the RuntimeException, which is a child class of Exception. This will mask potential programming mistakes. As a result of having a catch clause with the base Exception class, I have seen instances of NullPointerException - a child of RuntimeException - being caught and logged on numerous occasions. This potentially masks problems in the code, when an object instance was null, although it wasn't supposed to be so. If the object is null in only certain circumstances, then there is a distinct possibility that catching the base Exception will cause this problem to slip by in the development environment and fail in a production set-up at a customer site.

Catching specific exceptions and handling them appropriately - and perhaps differently - also makes for a better error-handling approach. Overall, it improves the readability of the code, where others are able to better understand and extend the exception handling mechanism.

Not long ago there was a trend among Java programmers to use the "*" notation while importing packages - e.g. java.util.*, instead of explicitly importing the classes required. This trend seems to have disappeared, and I hope that the trend of catching the base Exception class also cedes to the approach of explicitly catching the specific exceptions.

Monday, July 19, 2010

Optimizing Power Consumption

I recently reviewed an interesting paper, titled - Optimizing Power Consumption in Large Scale Storage Systems. Even though I was impressed by the lucid presentation of the problem and the quality of the proposed solution, the true significance of the work dawned upon me only after I watched Al Gore's movie - The Inconvenient Truth. Yes, three years after the movie won the Academy award for best documentary, I finally borrowed it from the library and watched it at home with my family.

Anyhow, the many objective of this post is to highlight some interesting aspects of the paper on optimizing power consumption. The paper highlights the reality of present time, where huge data centers have become a way of life. These data centers contain thousands of servers for storage, which in turn results in higher electric bills and searing heat. Hard disks account for a significant portion of the energy consumption and in a data center many hard disks are not accessed at a given time. The paper explains the three existing disk management solutions - Hardware-based solutions, Disk Management solutions and Caching solutions - that attempt to conserve power by powering down hard drives that are not being used. The paper outlines the limitations of these existing solutions, as not being able to predict well on which disks to power down, and then presents a fourth option - File-system solution, where the Log-structured File System (LFS) directs all writes to the log head. This leads to a perfect prediction mechanism as the disk being written to is known in advance and other disks may be powered down or operated in low-power mode.

LFS was initially motivated by the desire to optimize latency of write-accesses. To eliminate seek time, LFS replaces write operations by append, and the secondary storage is treated as a large append-only log, where writes go to the log head. Reads don't avoid the seek latency, however, the assumption is that with a good caching technique, there would be limited reads that need to access the secondary storage.

The paper finds a new fit for an old idea - using LFS to optimize the power consumption in a data center. Even though the idea sounds impressive at a conceptual level, there is still more work - related to the efficacy of log cleaning approach - that needs to be done before this idea turns into a viable solution. Overall this was an interesting read, with the significance of the work being exemplified by the wonderful movie - An Inconvenient Truth.