Thursday, September 29, 2011

Different flavors of mocking with Groovy

If you don't use Groovy in your Java projects, you definitely should consider to start using it. There are many areas where Groovy would be very useful, but one I would like to talk a bit today is testing with mocking. There are a bunch of awesome frameworks to do mocking with Java (Mockito, powermock, EasyMock, ...) but Groovy allows you to do it out of the box, using built-in classes and language constructs.

Let's assume we have third-party service implementation to mock. If service was designed well, it implements some kind of interface (or interfaces) so clients could call different methods using interface contracts.
package com.example;

import java.util.Collection;

public interface SimpleService {
	Collection< String > getServiceProviders();
	Collection< String > getServiceProviders( final String regex );
}
The simplest and beautiful test case will look like this:
package com.example

import org.junit.Test

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetServiceProvidersByPattern() {
		// Create implementation from a map, method name : implementation (closure)
		def simpleService = [
			getServiceProviders : { String regex -> [ "Provider 1", "Provider 2" ] }  
		] as SimpleService
	
		assertEquals( [ "Provider 1", "Provider 2" ], 
			simpleService.getServiceProviders( "Provider*" ) )
	}
}
Awesome and easy! Let's consider another use case: service has implementation only, no interfaces. Could we mock and it as well? Yes!
package com.example;

public class SimpleServiceImpl {
	public Collection< String > getServiceProviders() {
		return null;
	}

	public Collection< String > getServiceProviders( final String regex ) {
		return null;
	}
}
The test case is a bit more verbose because of using Groovy mocking framework. You can also specify how many calls you expect as well as call sequences.
package com.example

import groovy.mock.interceptor.MockFor

import org.junit.Test

import com.example.impl.SimpleServiceImpl

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetServiceProviders() {
		def context = new MockFor( SimpleServiceImpl )
		
		context.demand.with {
			getServiceProviders() { -> [ "Provider 1", "Provider 2" ] }
		}
	
		context.use {
			def simpleService = new SimpleServiceImpl()
			
			assertEquals( [ "Provider 1", "Provider 2" ],
				simpleService.getServiceProviders() )
		}
	}
}
Cool and easy! The obvious question is, what about mocking static methods? You will love Groovy after that (as I do). Let's complicate our service a bit with static method.
package com.example;

public class SimpleServiceImpl {
	public static Collection< String > getDefaultServiceProviders() {
		return null;
	}
    
	// Other methods here
}
So the test case for mocking this static method is no more than one line of code (thanks to Groovy meta-programming capabilities):
package com.example

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetDefaultServiceProviders() {
		SimpleServiceImpl.metaClass.'static'.getDefaultServiceProviders = 
			{ -> [ "Provider 1", "Provider 2" ] } 
	
		assertEquals( [ "Provider 1", "Provider 2" ],
			SimpleServiceImpl.getDefaultServiceProviders() )		
	}
}
And that's it!

Sunday, August 7, 2011

Exploiting MongoDB together with Spring Data project: advanced concepts

In previous post we had started discussion about MongoDB and Spring Data projects. In this post I would like to show some advanced features (which could be available in next Spring Data milestone or release as part of core functionality).

First of all, let us extend our MongoService with a method that counts documents in collection which match specific query.
package com.example.mongodb;

import java.util.Arrays;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.document.mongodb.CollectionCallback;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.document.mongodb.query.Criteria;
import org.springframework.data.document.mongodb.query.Index;
import org.springframework.data.document.mongodb.query.Index.Duplicates;
import org.springframework.data.document.mongodb.query.Order;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;

@Service
public class MongoService {
    public long countDocuments( final String collection, final Query query ) {  
        return template.executeCommand( 
            "{ " +
                "\"count\" : \"" + collection + "\"," +
                "\"query\" : " + query.getQueryObject().toString() + 
            " }"  ).getLong( "n" );
    }
}
The approach for this particular functionality is to call native MongoDB command count passing the query as a parameter. The returning structure contains number of documents in n property.

Or, in more code-friendly way:
import org.springframework.dao.DataAccessException;
import org.springframework.data.document.mongodb.CollectionCallback;

import com.mongodb.DBCollection;
import com.mongodb.MongoException;

public long countDocuments( final String collection, final Query query ) {  
    return template.execute( collection,
        new CollectionCallback< Long >() {
            @Override
            public Long doInCollection( DBCollection collection ) 
                    throws MongoException, DataAccessException {
                return collection.count( q.getQueryObject() ) );
            }
        }
    );
}

Next useful feature is bulk inserts. Please note, that in current version of MongoDB 1.8.1, when there is a duplicate inside the collection of inserting documents, bulk insert stops on first duplicate and returns so all other documents won't be inserted. Be aware of such behavior. Before moving to code snippet, let me introduce simple class SimpleDocument which we will be persisting to MongoDB:
package com.example.mongodb;

import org.springframework.data.document.mongodb.mapping.Document;

@Document( collection = "documents" )
public class SimpleDocument {
    private String id;
    private String name;
    private String content;
 
    public SimpleDocument() { 
    }
 
    public SimpleDocument( final String id, final String name ) {
        this.id = id;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
Following method inserts all documents as single bulk update:
public void insert( final Collection< SimpleDocument > documents ) {  
    template.insert( documents, SimpleDocument.class );     
}
Another very cool and useful feature to explore is MongoDB's upserts (more about this here http://www.mongodb.org/display/DOCS/Updating): if document matching specific criteria exists, it will be updated, otherwise - new document will be inserted into collection. Here is a code snipped with demonstrates it by following use case: if SimpleDocument with such name exists, it will be updated, otherwise new document will be added to collection:
@Autowired private MongoConverter converter;

public void insertOrUpdate( final SimpleDocument document ) {
    final BasicDBObject dbDoc = new BasicDBObject();
    converter.write( document, dbDoc );
  
    template.execute( SimpleDocument.class, 
        new CollectionCallback< Object >() {
            public Object doInCollection( DBCollection collection ) 
                    throws MongoException, DataAccessException {
                collection.update( 
                    new Query()
                        .addCriteria( new Criteria( "name" ).is( document.getName() ) )
                        .getQueryObject(), 
                    dbDoc,  
                    true, 
                    false 
                );
     
                return null;
            }
        }
    );
}
Please notice usage of converter bean which helps to convert Java class to MongoDB's DBObject.

The last one I would like to show is findAndModify operation which does several things as one atomic sequence:
- find document matching criteria
- perform update
- return updated document (or old one, depending on what are your needs)
public void findAndModify( final Query query, final Update update ) {
    return template.execute( SimpleDocument.class,
        new CollectionCallback< SimpleDocument >() {
            @Override
            public SimpleDocument doInCollection( DBCollection collection ) 
                    throws MongoException, DataAccessException {
                return converter.read( SimpleDocument.class,       
                    collection.findAndModify( 
                        query.getQueryObject(), 
                        null,
                        null,
                        false,
                        update.getUpdateObject(),
                        true,
                        false
                    ) 
                );
            }
        }			
    );
}



For now, those are all interesting use cases I encountered. Honestly, I am very excited about MongoDB and strongly recommend it if it fits your application.

Wednesday, July 27, 2011

Exploiting MongoDB together with Spring Data project: basic concepts

All of us are observing the explosion of NoSql solutions these days. I get used to RDBMS but those are not a solution for all kind of challenges you might have. In my recent experience I got a chance to work with MongoDB - document database. In this post I intent to cover some basics (and some advanced features in next post) of using MongoDB together with Spring Data project. Before we start, small disclaimer: at the moment Spring Data is still in milestone phase so some classes / interfaces may change.

Before we start, please download and run MongoDB for your operating system. It's very simple so I won't spend time on this and let's start with simple POM file for our project:

    4.0.0

    mongodb
    com.example.spring
    0.0.1-SNAPSHOT
    jar

    
        UTF-8
        3.0.5.RELEASE
    

    
        
            org.springframework.data
            spring-data-mongodb
            1.0.0.M3
        

        
            log4j
            log4j
            1.2.16
        

        
            org.mongodb
            mongo-java-driver
            2.5.3
        

        
            org.springframework
            spring-core
            ${spring.version}
        

        
            org.springframework
            spring-context
            ${spring.version}
        
    

    
        
            springsource-milestone
            Spring Framework Milestone Repository
            http://maven.springframework.org/milestone
        
    

There are two key dependencies here:
- MongoDB java driver
- Spring Data for MongoDB

There are few ways to define MongoDB inside your Spring application context. Let me show a bit verbose but more flexible one:


    
    
  
    
 
    
        <constructor-arg index="0" ref="mongo" />
        <constructor-arg index="1" value="elements-db"/>
    

        
      

    
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        <constructor-arg name="mappingContext" ref="mappingContext" />         
     

    
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
        <constructor-arg name="mongoConverter" ref="converter" />        
        <property name="writeResultChecking" value="EXCEPTION" />
        <property name="writeConcern" value="NORMAL"/>
    
 
    
        
    

The role of each bean here:
  • mongo defines connection to MongoDB database (we rely on default settings, port 27027)
  • converter is used to convert Java classes to/from MongoDB's DBObject (== JSON)
  • mongoTemplate exposes operations we can do over MongoDB

So, we are ready to go!
Here are few code snippets to start with:
package com.example.mongodb;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.document.mongodb.CollectionCallback;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.query.Index;
import org.springframework.data.document.mongodb.query.Index.Duplicates;
import org.springframework.data.document.mongodb.query.Order;
import org.springframework.stereotype.Service;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;

@Service
public class MongoService  {
    @Autowired private MongoOperations template;

    public void createCollection( final String name ) {
        template.createCollection( name  );
    }

    public void dropCollection( final String name ) {
        template.dropCollection( name  );
    }

    public void insert( final Object object, final String collection ) {
        template.insert( object, collection );
    }
   
    public void createIndex( final String name, final String collection ) {
        template.ensureIndex( 
            new Index()
                .on( name, Order.DESCENDING )
                .unique( Duplicates.DROP ), 
            collection  
        );
    }
 
    // Remove / save / ... operations here
}
That's it with basics. Next post will cover advanced features: using bulk inserts, update or insert operation and executing MongoDB commands. :)

Saturday, June 11, 2011

Using JSR 330 annotations with Spring Framework

No doubts Spring Framework had (and still has) a great influence on JSR 330: Dependency Injection for Java. For a long time Spring Framework has a pretty rich set of Java annotations in order to push dependency injection to superior levels. But ... most of such annotations are Spring-specific (like @Autowired, @Component, etc.). So ... the question is: does Spring Framework support JSR 330: Dependency Injection for Java? And the answer is: yes, it does, starting from version 3.

So let me show by example how to use Spring Framework together with JSR 330: Dependency Injection for Java. First, we need to reference JSR 330 annotations, f.e. from atinjet project. As always, I'm using Apache Maven 2/3 so here is my POM file:

  4.0.0

  com.example
  cdi-spring
  0.0.1-SNAPSHOT
  jar

  
    UTF-8
 3.0.5.RELEASE
  

  
    
      javax.inject
      javax.inject
      1
    
        
    
      org.springframework
      spring-context
      ${spring.version}
    
  
  
  
    
      nexus.xwiki.org
      http://nexus.xwiki.org/nexus/content/repositories/externals/
    
  

Pretty simple, the only thing we need to do is to have JSR 330 annotations in classpath. That's it. Here is my simple Spring context XML (applicationContext.xml):



    
    
 

I just asked Spring to do all job for me. Let me declare two simple beans, OneBean and AnotherBean, and inject one bean into another. So here is OneBean.java:
package com.spring.cdi;

import javax.inject.Named;

@Named
public class OneBean {
 public void doWork() {
  System.out.println( "Work is done" );
 }
}
And here is AnotherBean.java:
package com.spring.cdi;

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class AnotherBean {
 @Inject private OneBean oneBean;
 
 public void doWork() {
  oneBean.doWork();
 }
}
As you can see, there are no any Spring specific imports. Let me declare some Starter class which will host main() function (Starter.java):
package com.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.cdi.AnotherBean;

public class Starter {
 public static void main( String[] args ) {
  ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" );
  AnotherBean bean = context.getBean( AnotherBean.class );
  bean.doWork();
 }
}
It just loads Spring application context from classpath, asks it for AnotherBean class and call the doWork() method on it (which delegates call to injected OneBean bean). Here is my log when I am running Starter class (please notice that Spring detected JSR 330 annotations and properly handled them):
Jun 11, 2011 1:08:03 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2626d4f1: startup date [Sat Jun 11 13:08:03 EDT 2011]; root of context hierarchy
Jun 11, 2011 1:08:03 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
Jun 11, 2011 1:08:03 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Jun 11, 2011 1:08:04 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Jun 11, 2011 1:08:04 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4979935d: defining beans [anotherBean,oneBean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
Work is done
So those beans could be easily used without modifications by any Java framework which supports JSR 330 (f.e., JBoss Weld). Cool stuff.

Saturday, May 14, 2011

Watch your Spring webapp: Hibernate and log4j over JMX

I have been actively using Java Management Extensions (JMX), particularly within web applications, in order to monitor application internals and sometimes tune some parameters at runtime. There are few very useful tools supplied as part of JDK, JConsole and JVisualVM, which allow to connect to your application via JMX and manipulate with exposed managed beans.

I am going to leave apart basic JMX concepts and concentrate on interesting use cases:
- exposing log4j over JMX (which allows to change LOG LEVEL at runtime)
- exposing Hibernate statistics over JMX

In order to simplify a bit all routines with exposing managed beans I will use Spring Framework which has awesome JMX support driven by annotations. Let's have our first Spring context snippet: exposing log4j over JMX.




    

    
    
        
        
        
    
 
    
        
    
 
    
        
    
 
    
    

    
    
    


That's how it look like inside JVisualVM with VisualVM-MBeans plugin installed (please notice that root's logger LOG LEVEL (priority) could be changed from WARN to any, let say, DEBUG, at runtime and have effect immediately):
Let's add Hibernate to JMX view! In order to do that I will create very simple Hibernate configuration using Spring context XML file (I will repeat configuration for JMX-related beans but it's exactly the same as in previous example):



    

    
    
        
        
        
    
 
    
        
    
 
    
        
    
 
    
    

    
    
        
  
        
            
        
    
        
            
                org.hibernate.dialect.HSQLDialect
                true
            
        
    
 
    
  
    
        
      

       
    
        
    


And now we see this picture (please notice very important Hibernate property in order to see some real data here hibernate.generate_statistics = true):

Cool, simple and very useful, isn't it? :)

Tuesday, May 10, 2011

Testing untestable: JUnit + Mockito + Spring Test against static instances

This post is about my recent experience with the projects I thought don't exists anymore nowadays. Unreadable code base, chaotic design, any minor change breaks everything and, for sure, no tests. Worth mentioning deployment is nightmare. How this projects are supposed to evolve? I have no idea ... but we need to make fixes and changes. So ... what should we do? Write tests first!

That's not about how to write tests, but about techniques which allows to overcome some very bad coding practices in case you are not allowed to modify code base (as my team was put in such restrictions).

Let's start with such a pearl: private static initialized members (we will skip the thread safety aspects and concentrate on instance member only).
package org.example;

public class SomeStaticUtil {
    private static SomeStaticUtil instance = SomeStaticUtil.getInstance();
 
    public static SomeStaticUtil getInstance() {
        if( instance == null ) {
            instance = new SomeStaticUtil();
        }
  
        return instance;
    }
}
So how to substitute SomeStaticUtil with different implementation suitable for testing scenarios (aka mocks)? Remember, you are not allowed to modify the code (I would love to). There are few ways to do that:
- Excellent PowerMock framework. Didn't fit this project because bytecode manipulations crashed JVM.
- Magnificent AspectJ framework. Didn't fit this project because of complex aspects and necessary runtime weaving.
- Old and well-known reflection :-)

So what we can do here? Let's us exploit two excellent and very powerful test scaffolding frameworks: Mockito and Spring Test. Here is what we can do:
package org.example;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.test.util.ReflectionTestUtils;

public class SomeStaticUtilTestCase {
    private SomeStaticUtil someStaticUtil;
 
    @Before
    public void setUp() {
        someStaticUtil = Mockito.mock( SomeStaticUtil.class );
        ReflectionTestUtils.setField( someStaticUtil, "instance", someStaticUtil );
    }
 
    @Test
    public void someTest() {
        // ... some tests
    }
}
Very simple but powerful: replace private static member instance with mock implementation. Cool.

Saturday, April 2, 2011

Force your beans validation using JSR 303 and Hibernate Validator 4.1.0

In my list of most loved features JSR 303 is somewhere among top ones. Not only because it's extremely useful, but also because it has simple design and extensibility. Hibernate project actively uses validation techniques for a long time as part of Hibernate Validator subproject, recently with JSR 303 implementation support.

Today I would like to share some basic uses cases of JSR 303 annotations and programmatic validation support. Let us start with first one.

1. Assume you are expecting Person object to be passed to you business logic layer, just typical Java bean with few properties.
package org.example;

public class Person {
    private String firstName;
    private String lastName;
    
    public void setFirstName( String firstName ) {
        this.firstName = firstName;
    }
 
    public String getFirstName() {
        return firstName;
    }

    public void setLastName( String lastName ) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }   
}
Further, let us assume that according to business logic firstName and lastName properties are required. There are many ways to enforce such kind of constraints but we will use JSR 303 bean validation and Hibernate Validator.
package org.example;

import org.hibernate.validator.constraints.NotBlank;

public class Person {
    @NotBlank private String firstName;
    @NotBlank private String lastName;
    
    ...  
}
The question arises who will actually perform validation? The most straightforward solution is to do it using utility class.
package org.example;

import java.util.HashSet;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;

public class ValidatorUtil {
    private final ValidatorFactory factory;
 
    public ValidatorUtil() {
        factory = Validation.buildDefaultValidatorFactory();
    }
  
    public< T > void validate( final T instance ) {  
        final Validator validator = factory.getValidator();
  
        final Set< ConstraintViolation< T > > violations = validator
            .validate( instance, Default.class );

        if( !violations.isEmpty() ) {
            final Set< ConstraintViolation< ? > > constraints = 
                new HashSet< ConstraintViolation< ? > >( violations.size() );

            for ( final ConstraintViolation< ? > violation: violations ) {
                constraints.add( violation );
            }
   
            throw new ConstraintViolationException( constraints );
        }
    }
}
Having such a class validation is easy:
final Person person = new Person();
new ValidatorUtil().validate( person );
ConstraintViolationException exception will be thrown in case of any validation errors. Let us move on to more complicated examples.

2. Assume you are expecting Department object to be passed to you business logic containing at least one (valid!) person. Let me skip the details and present the final solution here.
package org.example;

import java.util.Collection;

import javax.validation.Valid;

import org.hibernate.validator.constraints.NotEmpty;

public class Department {
    @NotEmpty @Valid private Collection< Person > persons;

    public void setPersons( Collection< Person > persons ) {
        this.persons = persons;
    }

    public Collection< Person > getPersons() {
        return persons;
    }
}
The validation above ensures that Department contains at least one Person instance and each Person's instance is itself valid.

There are just a lot of other use case out there which Hibernate Validator is able to handle out of the box: @Min, @Man, @Email, @Url, @Range, @Length, @Pattern, ... This post is just a starting point ...