Friday, June 14, 2013

One person's hack is another person's gem!

Most of us have probably heard the idiom: One man's trash is another man's treasure!

Even though I have heard this many times in life, I never realized how true this could be until a few weeks ago. I was attending a conference track, and the presenter, an Engineer working on a  great innovative product, was explaining the challenges the team faced while working on the product. During this presentation, the Engineer mentioned about a session timeout problem while using a very popular open-source product, and how a developer from the open-source product team helped out the Engineer by writing a JSP (Java Server Page) as a workaround for the session time-out problem. As the Engineer was describing how smart the solution proposed by the developer was, I couldn't help thinking why this solution couldn't be regarded as a hack. Having developed many Java enterprise applications myself, I just couldn't understand why a JSP was required to address the session time-out problem of two servers components interacting with each other. This is not to say that this solution is wrong, it's just that I wouldn't have solved it this way.

I have never believed in hacking myself out of a coding problem, however, there are companies and developers who believe in it and some even organize "hackathons" to celebrate their IPO launch. So now I understand that "One person's hack is another person's gem", just the way "One man's trash is another man's treasure". I guess as long as we enjoy what we build, hack or gem is just a matter of perception, and this is one of those things that makes the world go round.

Wednesday, January 9, 2013

Why is history so important?

When Einstein was asked "What is that one thing that should be taught in school?", he replied-- "History." Einstein didn't mean the history about a civilization, but the history of the subject that is being taught. If you are learning Physics, then you must learn about it's history, and understand how the field has evolved over time. As a graduate student at Santa Clara University, I remember a wise professor repeatedly iterating the same sentiment in a computational logic course. The professor kept reiterating--"History is important, it tells us why things are this way."

In my opinion, software engineers are notorious at ignoring the importance of history. I don't blame them, as I never had a subject that explained the software engineering evolution from a historical point-of-view. Just ask yourself--How many Java developers truly understand why it was created when another (dominant) object-oriented programming language (C++) was around? I bet that most universities and schools that teach the Java programming language never bother to explain what led to its existence. Java was created as a language for the web, and the main reason that it is such a success is because of it's "Write Once Run (or Debug) Anywhere" feature. The concept of having a Virtual Machine (VM) has really revolutionized programming; no wonder we now have many more languages that use the same concept.

In my opinion, to be a successful software engineer, it is important to understand the history of the technological evolutions. There are researchers--in academia and business--that understand this evolution, and they are the ones that are coming up with new technological advancements. Just something to think about then--people who understand history are the ones who have a place in it.

Thursday, September 20, 2012

GPU Computing

For a long time GPU processing has been synonymous with Graphics Processing Units, and the first thing that comes to mind when thinking about GPUs is computer games and the cool graphics. It is true that computer graphics has been a primary driver in the advent of these processors, but the GPU has now found other applications that benefit from the vast computing power provided by the GPUs. So in essence, GPU no longer implies the Graphics Processing Unit, but a General-Purpose Processing Unit. Compute-intensive applications in the field of Bioinformatics and Weather forecasting benefit from the tremendous number crunching capabilities provided by GPUs. This is not to imply that CPU or the Central Processing Unit is obsolete; in fact the CPU-GPU pair form a co-processor environment in which the CPU forwards all compute-intensive tasks to the GPU. GPU manufactures provide libraries that allow the programmer to indicate which part of the application logic should run on the GPU. The application binary then contains the appropriate instructions for the CPU to assign a certain task to the GPU for processing. The NVIDIA CUDA is one such library that is compatible with the NVIDIA GPUs.

A reasonable question to ask is: why have two different kinds of processors and why not just make one processor do everything? Both the CPU and GPU were designed with different objectives, so the CPU design makes it better for I/O tasks, whereas the GPU design makes it better for compute-intensive tasks. GPUs are gaining popularity not only in servers, but also in mobile devices. It is not surprising that the new iPad has a quad-core GPU and a dual-core CPU. With the increased emphasis on visualization and breadth-taking graphics, the GPU is expected to be the dominant, and perhaps the main processor, in a device.

Thursday, May 31, 2012

Engineer vs. Entreprenuer

What is the difference between an Engineer and an Entrepreneur? I can't speak about other engineering fields, however, in software engineering the difference is worth pondering over.

A smart engineer builds a great product to solve a technical problem, gifts the product away to the open-source community for the greater good, gets recognition in the technical community for the effort, and then goes back to being a salaried employee at a company.

A smart entrepreneur on the other hand, hires smart engineers to build a product to solve a consumer problem by using the technological advancements made by the open-source community, gets recognition among the masses, either sells the company or takes it public, becoming a millionaire or possibly a billionaire in the process.

Case in point - Doug Cutting developed Hadoop, a great distributed computing framework, gifted it to the open-source community, gained respect in the technical community, and went back to being a salaried employee. Whereas, Mark Zuckerberg built facebook by using Hadoop to gain massive scalability and reliability, gained world-wide recognition by building the largest social network, and became a billionaire after facebook went public.

Moral of the story: Become an Engineer, but think like an Entrepreneur!

Wednesday, May 16, 2012

The iConic Entrepreneur: Steve Jobs

People who love Apple products have grown to admire Steve Jobs as a great visionary and entrepreneur. Those who are intrigued by Steve's life and his numerous contributions should definitely read his book: "Steve Jobs" by Walter Isaacson. Steve Jobs did not have the perfect life, and perhaps this is why he strived to achieve perfection in his work by making products that are simple and intuitive. Steve was one of the rare individuals who understood that engineering is not just a science, it is an art as well. So, what makes Steve Jobs such a great entrepreneur? The first thing that comes to mind when we think of great entrepreneurs is that they are "great visionaries". However, having a vision is not everything, execution and timing are just as important. I read Bill Gates's book - "The Road Ahead" - in the nineties. In the book, Gates predicts that the web would evolve into an Information Superhighway and it would be accessible by a small device that is the size of our wallet. This wallet-sized device would cater to all our computing and communication needs. Even with Gates' vision, Microsoft never came up with such a product. It was Apple that launched the iPhone, which does what Gates had predicted. Where Apple succeeded - when Microsoft failed - was in the execution and timing. Under Steve's leadership, Apple executed flawlessly to deliver such a great product. With the IT world gravitating towards Cloud Computing (and SaaS), the timing could not be better. So in a grand scheme of things, execution and timing go hand-in-hand with a great vision. Steve Jobs had all three: great vision, execution and timing. This is why Steve Jobs is the iConic entrepreneur of our generation.


Friday, April 6, 2012

1c for the code, 99c for where you put it!

All engineers have probably heard this popular story at some point in their life: An engineer is called to fix a complicated machine, which the engineer fixes in minimal time by just replacing a screw. The engineer presents an exorbitant bill for the service, and when questioned by the customer, explains that the cost of the screw is only 1% of the bill, and the remaining 99% is for replacing the "right" screw.

It occurred to me that this story applies pretty well to the software engineering field. In the software engineering world, if I had a dollar to spend on a line of code, I would put 1c on the actual code itself, and the remaining 99c on the location of the code. Why would I do that? After all, as long as the code is working, does it really matter where it exists? The truth is that code added to the correct method, class and component makes a significant difference in the readability and maintainability of the code. Correct design ensures that the code is placed in the correct location, so the moral of the story is - to get the biggest bang for your buck, focus on the correct design and not on just getting the code to work. Remember, in a world with 9 billion people, there are probably millions who can write working code, but only a selected few who can design it correctly.

Wednesday, March 7, 2012

Enterprise vs. Cloud Computing

I recently found myself in a discussion where I was trying to differentiate between web computing and cloud computing. I was trying to make a point that these days all web-based products are claiming to be cloud-enabled. Anyhow, I later realized that I was making a wrong comparison. The web is in fact just a medium for product delivery; the comparison should have ideally been between "Enterprise Computing" and "Cloud Computing". In an era where "Cloud" has become the buzz word, most people are touting their web-enabled enterprise products to be cloud-enabled.

Enterprise and Cloud computing are two different things, the only thing common is perhaps that both are  web-enabled, which means that they can be accessed via the browser using an internet connection. However, there are many differences in these two technologies, and some of them are highlighted below.

1. Single-tenant vs. Multi-tenant: Enterprise solutions are generally single-tenant, which means that each customer or enterprise has its own deployment. Cloud solutions are multi-tenant, where the same deployment supports multiple domains (customers or enterprises).

2. Scalability: Enterprise products are expected to scale from 10s to perhaps 1000s of users, whereas Cloud solutions need to scale to millions of users. So whereas an Enterprise platform may be scaled vertically by beefing up the server hardware, Cloud platforms generally rely on horizontal scalability by increasing the number of processing nodes in the cluster.

3. Performance: In an Enterprise platform, performance may be improved by having  multiple processing threads; however, cloud platforms improve performance by processing on multiple nodes in parallel. Therefore, Cloud platforms require a distributed processing and coordination framework, such as Hadoop.

4. Virtualization: Enterprise products generally use dedicated resources - servers, storage devices etc. Cloud-enabled products, on the other hand, use virtualization to share hardware resources.

5. Access Control: In an Enterprise platform, access controls pertains only to user access control, whereas in Cloud platforms, access control also applies to the resources shared between the multiple tenants.

I am sure that there are other differences between Enterprise and Cloud computing, so this is certainly not a comprehensive list. The objective is primarily to get the product architects thinking in the right direction. I hope you found it useful.






Wednesday, January 18, 2012

Singleton Pattern - The Correct Usage

The singleton pattern is perhaps the most widely (mis)used pattern. Developers who program in object-oriented languages use the singleton pattern whenever they think of a service or manager class. I have seen a lot of projects use singletons even when the singleton class never encapsulates any private data that needs to be handled for multiple instantiations. Usage of the singleton pattern - with a private constructor and a getInstance() method - ensures that only a single instance of a class exists and all threads use the single instance. A database manager class that maintains a local data cache is an ideal candidate for a singleton, as we wouldn't want to maintain multiple local caches; the singleton cache should be loaded once and preserved in memory for faster access. Operations on this cache should also be thread-safe. If a class does not hold and control access to private data, then simple object instantiation makes perfect sense.

Another common mistake with the singleton pattern implementation is doing the object instantiation in the getInstance() method by making it thread-safe and having a check to see if the object is already instantiated. Given below is the implementation logic in Java. The method getInstance() is made thread-safe by using the synchronized keyword. This approach degrades the application performance as a lock is obtained on the object every time a thread calls the getInstance() method.


MySingleton mySingleton = null;


public synchronized MySingleton getInstance() {
  if (mySingleton == null) {
    mySingleton = new MySingleton();
  }
  return mySingleton
}


A better alternative is to instantiate the singleton object at the time of declaration. In this case, the ClassLoader instantiates the singleton when it comes across its reference, well before any thread is active in the application. Since the getInstance() is no longer synchronized, this offers better performance.



MySingleton mySingleton = new MySingleton();  // Object instantiated during declaration


// No need to synchronize method
public MySingleton getInstance() {
  return mySingleton
}


The concurrency-optimized implementation of the Singleton pattern is explained in many Java Concurrency books, but hopefully now you won't have to read the whole book to learn this neat trick.


Tuesday, June 21, 2011

Using Database Constraints

For many developers, a relational database is just a simple data store. They really don't believe is having any constraints in the database, and prefer to implement all checks-and-bounds in the application logic. This is really a recipe for disaster, and in this post, I will look at some key database constraints that should always be set for an application.
  1. Foreign Key: A relational database is called "relational" for a reason - the term signifies the ability to relate tables (and data) with foreign key constraints. A foreign key constraint avoids data integrity problems and prevents programming errors. Having foreign keys is essential for parent-child and other association relationships. A commonly quoted example is the "Purchase Order" and "Line Item" data, where the purchase order id is the foreign key in the line item table. Not having the foreign key relationship between these tables allows for the possibility of having an incorrect purchase order id in the line item table. This value may be inserted mistakenly by the application code or perhaps manually from the SQL prompt, which in turn results in unpredictable errors in the application and perhaps defensive code to check if the purchase order id is correct before performing further processing. It is much easier to avoid these problems by having proper foreign key constraints in the database.
  2. Not Null Constraint: This is another commonly overlooked problem. Even with limited domain knowledge, it is not too difficult to ascertain which columns can never be null and enforce this in the database by adding a "not null" constraint on the column. Again, the avoids the need to have defensive code all over the place that checks if the variable - that stores the data from this column - is not null before using it for further processing.
  3. Unique Constraint: Unique constraints can be placed on a single column, or on a group of columns. To create an unique constraint on a set of columns, it is required to create an index on them and set the index as unique. Without the unique index, it is common for application code to query the database to check if certain key data is already present before inserting a new record with the data. As an example, if the user id in the user table needs to be unique, then it is better to enforce this with a constraint, instead of querying the database to see if the user id is already exists. Attempting to insert with the duplicate user id results in an exception, which can be caught and the user can be requested to select a different user id. There is a significant performance benefit of using the constraint approach, instead of the using the query to check for duplicates.
  4. Using ENUM: Most programming languages support the enum datatype, and now most databases also support enum. Before enums, if a column could have a fixed set of values, then the solution was generally to have integer (or char) constants denote the various values. As an example, if the user account could be 'active' or 'disable', then the 'state' column would generally have integers (0 and 1) to denote the different states, or perhaps characters 'A' or 'D' for the same purpose. With enums, it is possible to enumerate all the values that a column might store, and use the same names in the code so that data comparison becomes easier.
While there may be other useful constraints, I generally find the above-mentioned ones most useful and find it difficult to comprehend how an application can do without them.

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.

Wednesday, June 9, 2010

Catching Java Exceptions

While running FindBugs - a static analysis tool - on a Java project, I encountered numerous instances of a warning - "Exception is caught when Exception is not thrown". Digging deeper into the problem made me realize that this warning results from a "catch all" exception block - catch(Exception e) - that is very commonly used by most Java developers to avoid handling checked exceptions explicitly.

The reason that FindBugs complains about this practice is that having a catch all block for some code - using catch(Exception e) - also catches RuntimeException, which is a child class of Exception; however, doing so could potentially mask serious errors in the program logic. As an example, having a catch(Exception e) block catches the NPE (NullPointerException), which is a child class of RuntimeException. The NPE exception indicates potential problem with the code, indicating that a defensive null check is missing before an attempt to dereference an object. This problem may go undetected for a while if a "catch all" block is used to catch all exceptions.

The only solution to this problem is to explicitly catch the "checked" exceptions that can be thrown by the executing code. Even though there is a base class for runtime exceptions, there is no such class for checked exceptions, so the developer needs to explicitly catch the different checked exceptions, which may seem like a pain, but would certainly be beneficial in the long run. An additional motivation - for catching all checked exceptions explicitly - is that the method may need to throw each exception explicitly to clearly indicate the problem to the caller, which facilitates better error handling and reporting.

Monday, January 11, 2010

Throttling the SwingWorker using an ExecutorService

The SwingWorker is a utility class that ships with Java 6. It allows a Swing application to perform lengthy background computation in a separate worker thread, in effect freeing the event dispatch thread to interact with the user. Even though the SwingWorker utility is an important addition to the Java SDK, it does increase the resource overhead of the application by creating two additional threads for processing the lengthy computation - one thread performs the actual background work, while the other waits for the background thread to finish and then updates the results on the UI. Since the event dispatch thread is free to accept user input, the user - in the absence of a prompt response - may invoke the same functionality repeatedly. This results in a large number of worker threads being instantiated, and for a J2EE application, this in turn results in an increase in the number of associated threads being spawned by the servlet container to process the client requests. The increased number of threads on the server-side typically results in server overload and performance degradation. Even though the SwingWorker utility provides a cancel() method to stop the execution of an existing worker thread, there is no way to cancel the execution of the server-side thread created by the servlet container. The solution to this problem is to throttle the SwingWorker utility by using the ExecutorService, which has been added in Java 5 to execute Runnables using a thread pool. A fixed sized thread pool ExecutorService allows only a certain number of SwingWorker threads to be active at anytime, with the new threads having to wait for the earlier ones to finish, before getting a chance to execute. The value of the thread pool size is specific to the application and is primarily dependent on how many SwingWorker threads are expected to be active at any given time.

The code sample given below depicts a typical Swing application that uses the SwingWorker utility to retrieve data from the server. The SwingWorker utility is parameterized to have any desired return type , which is returned from the doInBackground() method. The type is used to denote the intermediate results that are used by the publish() and process() methods to depict - if required - the progress to the user. The doInBackgound() method is executed by the background worker thread that performs the lengthy computation. A second thread blocks at the get() call in the done() method and the event dispatch thread continues to perform user interaction. Finally, once the lengthy background computation is complete, the get() method returns the result of the doInBackground() method, which is then used by the second waiting thread to update the results on the Swing UI.

As explained above, once a SwingWorker thread is submitted for execution, it may be subsequently cancelled by invoking the cancel() method on the SwingWorker instance created. However, it is not possible to cancel the server-side thread that is spawned by the servlet container to process the client request. To avoid this problem, it is advisable to throttle the number of threads being created by using an ExecutorService with a fix thread pool of a certain size. Therefore, instead of calling the execute() method on the SwingWorker instance, the SwingWorker instance - which is a Runnable - is submitted to an implementation of the ExecutorService.

// Create a background worker thread

SwingWorker swingWorker =

new SwingWorker, Void>() {

// This method executes on the background worker thread

@Override

protected doInBackground() throws Exception {

compute result;

return result;

}

// This method executes on the UI thread

@Override

protected void done() {

result = get();

}

};

// Submit to the executor

SwingWorkerExecutor.getInstance().execute(swingWorker);

Given below is a very simple implementation of the SwingWorkerExecutor that creates an ExecutorService with a fixed thread pool size set as 3, which allows only three worker threads to be active at any given time. New Runnable instances of SwingWorker wait in the queue and are selected for execution only when a previous instance has completed execution. This strategy effectively avoids the spawning of numerous threads of the server, and therefore, prevents any possible performance degradation.

public class SwingWorkerExecutor {

private static final int MAX_WORKER_THREAD = 3;

private static final SwingWorkerExecutor executor = new SwingWorkerExecutor();

// Thread pool for worker thread execution

private ExecutorService workerThreadPool = Executors.newFixedThreadPool(MAX_WORKER_THREAD);

/**

* Private constructor required for the singleton pattern.

*/

private SwingWorkerExecutor() {

}

/**

* Returns the singleton instance.

* @return SwingWorkerExecutor - Singleton.

*/

public static SwingWorkerExecutor getInstance() {

return executor;

}

/**

* Adds the SwingWorker to the thread pool for execution.

* @param worker - The SwingWorker thread to execute.

*/

public void execute(SwingWorker worker) {

workerThreadPool.submit(worker);

}

}

Monday, August 17, 2009

Comparing Java Runtime Analysis (or Profiling) Tools

Runtime analysis is a practice aimed at understanding software component behavior by using data collected during the execution of the component. The analysis provides an understanding of the following aspects of the application execution environment:
  • Execution paths and code coverage.
  • Memory utilization and memory leaks.
  • Execution performance and performance bottlenecks.
  • Thread analysis and related concurrency issues.
Enterprise Java applications that are designed to run on modern multi-core processors typically benefit from the use of a Java runtime analysis tool, as it provides information on memory leaks, performance bottlenecks and even concurrency issues such as deadlocks.

Recently at work, I got the opportunity to evaluate the leading Java profiling tools. An initial review of the leading tools in this arena resulted in the following list - JProfiler, YourKit Java Profiler, Java Visual VM, DevPartner Java Edition, Rational Purify, JProbe and OptimizeIt. A preliminary investigation shortlisted the candidates to JProfiler, YourKit Java Profiler and Java Visual VM. Both JProfiler and YourKit Profiler are leading award-winning tools and I was basically looking to compare them with the Java Visual VM, a free tool available with JDK 6.0 Update 7 (Windows). The other tools were rejected for various reasons - the DevPartner for Java product kept crashing, Rational didn't have a standalone Java edition, OptimizeIt only worked well with JBuilder, and finally, based on reviews posted on the web, JProbe was considered somewhat inferior to JProfiler and YourKit Profiler.

The three selected candidates (JProfiler 5.2.2, YourKit Java Profiler 8.0.13 and Java Visual VM 1.6.0_14 were compared against the following evaluation criteria:
  • License Cost: While Visual VM is free, both JProfiler and YourKit Profiler are commercial tools that provide an option to purchase both standalone (node-locked) licenses and floating licenses. The license cost for both these products is more-or-less in the same range.
  • Ease-of-use: This was an important consideration as the profiling tool should be intuitive to use, with the results being presented in an easily understandable format. All the tools faired equally in this category.
  • Performance (CPU) Profiling: CPU profiling helps to identify hotspots (or method) that result in higher CPU usage. All the three tools provide comprehensive analysis, however, YourKit and JProfiler have better presentation options that display the data using call graphs and trees.
  • Memory Utilization: This form of analysis presents information regarding the memory usage. The three tools under consideration provide a view which lists all the objects and their associated memory consumption. Again, the presentation of JProfiler and YourKit is slightly better than Visual VM.
  • Thread Analysis: Provides a view of the threads running in the VM. All the tools under consideration provide very good thread analysis capabilties and also detect concurrency issues such as deadlocks.
  • Code Coverage: This criteria was also under consideration; however, it was deemed less important in comparison with the other criteria.None of the tools being evaluated provided code coverage analysis.
  • Remote Profiling: This is the ability to perform the runtime analysis from a remote machine. JProfiler and YourKit provide all the features that are available for local analysis; however, Visual VM only provides a limited set of features for remote analysis.
  • IDE Integration: All three tools integrate well with Eclipse and other major Java IDEs.
  • Supported Platforms: The three tools selected support all the major version of the common operating systems - Windows, Linux, Mac OS X and Solaris.

Based on the comparative analysis, it was clear that both JProfiler and YourKit were slightly superior products with some great profiling features. While Visual VM may not have all the features provided by the other two products, it is extremely intuitive and provides all the basic features that are desired from a runtime analysis tool. It is also important to note that since Visual VM is extensible via a plug-in architecture (just like Eclipse), it is poised for growth and contributions from the open-source community will eventually make it a compelling product, possibly at par (or even better) that JProfiler and YourKit.

Therefore, we decided to use Java Visual VM, as it satisfies our current needs and there is already some contribution from the development community in the form of some really useful plug-ins.

Monday, August 3, 2009

Comparison of Java source code analysis tools

Recently at work, I got the opportunity to evaluate some leading static source code analysis tools for Java. The intent was that a good source code analysis tool would help to improve the quality of the product by detecting problems in the code, well before the QA folks get it.

At expected, there are a plethora of tools in the market - some that are commercially available, whereas others that are provided free with the open-source initiative. I selected Coverity Prevent for Java, one of the leading commercially available tools, in part due to the existing relationship that my present employer has with Coverity. I also decided to pick two leading tools, FindBugs and PMD, from the open-source arena, as they seem to be the most popular tools in use. The selected tools were used to analyze the same Java codebase on a Windows 2008 Server machine with 1.5 GB allocated to the analysis.

Comparing source code analysis tools from different vendors is not a typical apple-to-apple comparison. Each tool has its own inherent strengths and does better than the other in certain areas. Anyhow, following an evaluation methodology that has always worked very well for me, I evaluated these three candidates again the following criteria:
  • License Cost: An important consideration in any evaluation. Being a commercial product, Coverity Prevent has as associated license cost, whereas the other two are basically free.
  • Quality of the Analysis: Obviously concurrency and resource ultilization issues are deemed more important that ununsed method / variables. This was a difficult comparison to make, as all the three tools reported a wide spectrum of problems. In general, however, I found the Coverity Prevent and FindBugs analysis to be better than PMD.
  • Speed of the Analysis: Since the objective is to integrate the analysis with the nightly build, a short analysis time is preferred. While Coverity Prevent took hours to analyze the codebase, both FindBugs and PMD were done in minutes.
  • Eclipse Integration: Having an Eclipse plugin is essential to report defects during day-to-day development. Fortunately, the three tools selected provide one.
  • Rule Customization / Extension: The ability to customize the existing rulesets and add new ones was considered a desirable feature. While all three provided the option to add / drop certain rulesets from the anaysis, only FindBugs and PMD allowed the user to create new customized rulesets.
  • Defect Reporting: This considered the ability of the tools to report the defects in the most intuitive and convenient manner. Coverity Prevent has a great web-based defect manager that allows the user to remotely look at the defects, review the associated source code and act on them. FindBugs has a GUI option that displays the defects and provides associated source markups, however, PMD doesn't provide the source markups and it is only available as a command-line program. All three tools provided an option to export the defects in different output formats (html, xml).
Based on the evaluation criteria given above, we selected FindBugs, which is in line with the wisdom of the web - "If you have never used a source code analysis tool before, try a free one first and see if that works for you". Typically, projects use multiple open-source code analysis tools and I found a lot of references to projects that have used both FindBugs and PMD.

We are now looking for a Java runtime analysis tool and I am doing an evaluation for that. I hope to post the results of that as well.