More than 10 years of experience in Enterprise Applications development, and Project Management (since June 2001). Specialties: Enterprise Applications, J2EE, J2SE, Spring Framework, Spring Security, Spring Webflow, JPA and JDBC, JMX, JAXB, JUnit; XML, XSLT and XSL-FO; HTML/CSS, Javascript, JSON, jQuery/jQuery UI; RDBMS (Oracle, SQL Server, MySQL), PL/SQL; UML; Mobile Applications, mostly in Objective-C targeted iPhone/iPad Michal is a DZone MVB and is not an employee of DZone and has posted 12 posts at DZone. You can read more from them at their website. View Full User Profile

Enforcing Coding Discipline With FindBugs

03.20.2012
| 4935 views |
  • submit to reddit

Suppose that group of developers work in parallel on parts of a big project. Some developers are working on the service implementation, while others are working on code using this service. Both groups agreed on a service API, and started working separately, with the API assumptions in mind.

Do you think this story will have happy ending? Well, ... - maybe :) There are tools which can help achieve this. One of these tools is FindBugs, supported with JSR-305 (annotations for software defect detection).

Let's take a look at the service API contract:

package com.blogspot.vardlokkur.services;

import java.util.List;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import com.blogspot.vardlokkur.entities.domain.Employer;

/**
 * Defines the API contract for the employer service.
 *
 * @author Warlock
 * @since 1.0
 */
public interface EmployerService {

    /**
     * @param identifier the employer's identifier
     * @return the employer having specified {@code identifier}, {@code null} if not found
     */
    @CheckForNull Employer withId(@Nonnull Long identifier);

    /**
     * @param specification defines which employers should be returned
     * @return the list of employers matching specification
     */
    @Nonnull List<Employer> thatAre(@Nonnull Specification specification);

}

As you see there are annotations like @Nonnull or @CheckForNull added to the service method signatures. The purpose of their usage is to define the requirements for the method parameters (ex. identifier parameter cannot be null), and the expectations for the values returned by methods (ex. service method result can be null and you should check it in your code).

So what? - you may ask - should I check them in the code by myself or trust the co-workers that they will use the guidelines defined by those annotations? Of course not :) - trust no one, use the tools which will verify the API assumptions, like FindBugs.

Suppose that we have following service API usage:

package com.blogspot.vardlokkur.test;

import org.junit.Before;
import org.junit.Test;

import com.blogspot.vardlokkur.services.EmployerService;
import com.blogspot.vardlokkur.services.impl.DefaultEmployerService;

/**
 * Employer service test.
 *
 * @author Warlock
 * @since 1.0
 */
public class EmployerServiceTest {

    private EmployerService employers;

    @Before
    public void before() {
        employers = new DefaultEmployerService();
    }

    @Test
    public void test01() {
        Long identifier = null;
        employers.withId(identifier);
    }

    @Test
    public void test02() {
        employers.withId(Long.valueOf(1L)).getBusinessName();
    }

    @Test
    public void test03() {
        employers.thatAre(null);
    }
}

Let's try to verify the code against the service API assumptions:


FindBugs will analyze your code, and switch to the FindBugs perspective showing potential problems:

Null passed for nonnull parameter
Possible null pointer dereference


Similar way, guys writing the service code may verify their work against defined API assumptions, for ex. if you run FindBugs for the very early version of service implementation:

package com.blogspot.vardlokkur.services.impl;

import java.util.List;

import com.blogspot.vardlokkur.entities.domain.Employer;
import com.blogspot.vardlokkur.services.EmployerService;
import com.blogspot.vardlokkur.services.Specification;

/**
 * Default implementation of {@link EmployerService}.
 *
 * @author Warlock
 * @since 1.0
 */
public class DefaultEmployerService implements EmployerService {

    /**
     * {@inheritDoc}
     */
    public Employer withId(Long identifier) {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public List<Employer> thatAre(Specification specification) {
        return null;
    }

}

The following error will be found:


As you see, nothing can hide from the FindBugs and his ally - JSR-305 ;)

A few more reference links:

 

 

Published at DZone with permission of Michal Jastak, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

dieter von holten replied on Wed, 2012/03/21 - 7:35am

what is teh current state of JSR 305 ? checked their website and last activity was 2006, thet status is 'inactive'.

anything going on with that?

 

Anuj Mehta replied on Thu, 2012/03/22 - 2:00am

I have written an article on FindBugs -  http://anuj-mehta.blogspot.in/2011/07/findbugs.html

Adding it for reference 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.