2010 SpringOne 2GX Groovy/Grails Session Notes

October 24, 2010

The notes here are from 10000-ft view and some statements are merged from multiple sessions.

* Externalized configuration of  Config.groovy

grails.config.locations = [ "classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy"]
This way, you may remove production login/password from source control, along with  environment specific information from WAR.

* liquibase (www.liquibase.org) for database migration management.

* Securing JMX/VisualVM operations in production environment

* GORM may not completely shield you from Hibernate
http://blog.springsource.com/2010/06/23/gorm-gotchas-part-1/ lists some common issues

* Performance tuning (warning: avoid premature tuning)
- tools
Easiest one is to download tc-Server/Spring Insight and drop your war to see which operation is slow.
Other tools include Profile Plugin, Hibernate logging, p6Spy at server side, and Chrome speed tracer and Firefox ySlow at client side.
- fixes
Database queries tuning, Service/View tier Caching(springcache plugin), Async. calling, Http tier tuning, such as “static resource” plugin

* NOSQL development
NOSQL may provide better scalability and easier domain object mapping compared with RDBMS in some emerging data processing applications, but it is currently still in some sort of hype stage.  RDMS will remain to be the core persistence platform for long time to come. The NOSQL applicability is based on the application requirements of Consistency, Availability and Partition-tolerance. See http://bit.ly/cap-theorem-proof for details. It likely will take many more years for NOSQL to mature.
Grails currently provides Redis and GemFire NOSQL plugins and more are coming.

* Grails release updates in short and medium terms
- Groovy-1.8, Spring-3.1 and Hibernate-3.6 upgrade
- Agent-based reloading to improve performance
- Better static resource management
- NOSQL and RabbitMQ
- Rest client and server enhancement
- JQuery and Flex
- Gradle Build
- Spock and Jeb testing support

* Groovy programming language
- Compile time meta-programming via AST transformation. @Singleton and @Immutable etc annotations are classical examples.
- Run-time meta-programming via ExpandoMetaClass. myPerson.save() and Person.findByLastName(“Mylastname”) etc domain class persistent methods are typical examples.
- Performance has been improved greatly in the last few releases, but more are coming. Some audience still concerns the issue, such as bootstrap-startup time etc.
- Better modularization to allow customized and more efficient run-time deployment for different kinds of applications.

* Groovy concurrency
- At its core, java concurrency is the foundation, such as jetlang, jppf.org, gruple, gridgain, multiverse etc. IBM’s http://alphaworks.ibm.com/tech/contest remains the only thread testing tool to help improving thread safety.
- GPars is a new tool to help simplify Groovy/Java concurrent tasking implementation.

* Spock unit testing framework
Implemented mostly via Groovy compile-time meta-programming(AST transformation), it claims to be state-based, data-driven and behavior-based testing. It also supports extension for testing customization and enhancement.
However its core implementation is still based on jUnit spec and does not support parallel unit testing yet(It may come in the upcoming 1.0 release).

* Gradle build tool
It’s aim is to combine best features from both Ant(simplicity and control) and Maven(dependency management). It’s using closure syntax DSL for build scripting. For now the adoption is limited as the release is not 1.0 yet and lacks IDE support.

* Git repository
Single word: distributed repository management tool with core operation as add-commit-push. Its underlying tools allow better parallel development and changes/cloud-support management.

* AMQP/RabbitMQ
Protocol-based messaging tool to allow diversified clients interaction. RPC call via direct-exchange. No pre-determined content-type for messaging payload.
No embedded MQ yet for writing unit/functional tests. Clustering support for high-availability operation is in the works.

* Mobile development
- Server side using Spring-Mobile/REST Service
- Client side is all native code and no write-once-run-everywhere. Today is iPhone(you need a Mac) and tomorrow is Android, with Windows mobile 7 and Blackberry are wild-cards. Palm/WebOS may survive via tablet push by HP.
- PhoneGap and Appcelerator/Titanium are two major CSS/javascript based cross platform development tools, with native wrapper to deploy the app to target native device. It’s unclear on future direction how the cross-platform standard may playout.

Grails spring-security-core Usage Tips

September 6, 2010

There are a number of web app-layer authentication and authorization plug-ins for Grails.  These plug-ins provide essential functionalities for user log-in, access control, single sign-on etc.  Spring-security-core is the latest one built on top of  the powerful Java security framework Spring-Security-3.0(formerly Acegi security).  Spring-Security-3.0 provides supports for numerous authentication methods, such as OpenID, LDAP, JAAS etc. Here are a few common usage tips for this plug-in.

1. Implement your own authentication provider
Spring-Security-Core is still pretty new and may not provide you with a default authentication provider. But fortunately Spring-Security framework is interface based framework and you can easily implement the org.springframework.security.authentication.AuthenticationProvider interface for your own authentication protocal. Your code sketch may look like this:

public class MyAuthenticationProvider implements AuthenticationProvider {
……
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Your custom authentication integration code goes here
}

public boolean supports(Class<? extends Object> authentication)  {
……
}
}

The Authentication object can be viewed as a simple security token to hold information about your log-in status, user name/password, user information(UserDetailsService)etc, sort of like a building access badge. You need to refer to SpringSource reference doc on more about Authentication details.

Once you implement the provider interface, place it in Grails conf/spring/resource.xml with a bean name such as myAuthenticationProvider, and then activate the provider in Grails config.groovy with one line:
grails.plugins.springsecurity.providerNames = ['myAuthenticationProvider']

Now, you are done with your own custom authentication integration and ready to use the log-in form and other security service in your application. Spring-Security-Core comes with most features you need at HTML form, service and GSP tag level for security integration and deployment.

Since Spring-Security web authentication is servlet filter based, it always automatically prefix your app-context-path in the process. So be careful when configure the application related URL properties. For example, when login failed, you want to redirect the user back to the log-in page wherever it is. The proper relative url should be the one w/o context path:
${request.forwardURI.substring(request.contextPath.length())} Notice here we do not use http referer as it may not work with some older browser.

2. Session Fixation Prevention
Spring-Security-Core by default automatically migrates your existing session into the new session upon successful authentication. This prevents sessionId based attack.
Another added benefit is that it will integrate smoothly with your current session-based application, such as shopping-cart, Spring Webflow etc. User can log-in at any point of the session flow.  But notice log-out will wipe out the security session along with your application session data as well. So you may need a warning message for end-user to logout during middle of your application session flow. If some session data must be processed before logout, you can implement a logout handler and register it at config.groovy.

3. Password management
Another common feature is managing expired, locked and or temporary password etc. Many applications have slightly different way to use it. Spring-Security-Core has four methods defined on UserDetailsService( a component in the above Authentication object)
- isAccountNonExpired()
- isAccountNonLocked()
- isCredentialsNonExpired()
- isEnabled()

You can implement any of these methods to suit your application needs to manage invalid password and redirect user to a proper error handling page when the exception happens.

Spring-Security-Core is a feature rich security plug-in that can satisfy most of you application authentication and authorization needs with easy-to-use interface for extending/customization. The underlying Spring Security-3.0 is also very powerful and you are assured most of your application security requirement can be met.

References

1. grails-spring-security-core/

2. http://static.springsource.org/spring-security/site/

Using Apache Commons JEXL for Java Object Validation

March 14, 2010

Apache Commons JEXL is a simple generic  expression language that can be used for dynamic scripting. Among many possible applications, we apply it for dynamic Java object validation.

Object validation is rather common in many applications and there are numerous ways to do it. But via JEXL, you can put validation rules in a configuration file or database table and JEXL can load them up at runtime to validate a given object.  Here is an example on how to do it.

1. A Simple Validation Problem
Assuming a Person class with four attributes: SSN, firstName, lastName and birthYear. It has two different validation rules per different environment:
(1) Rule 1:  SSN != null and birthYear < 1990 when a Person object is processed in Bonus-prize-draw component.
(2) Rule 2: firstName != null  and lastName != null when a Person object is processed in Guest-book sign-up component.

The Person class:

public class Person {
  private String ssn;
  private String firstName;
  private String lastName;
  private Integer birthYear;

  public Person(String ssn, String firstName, String lastName,Integer birthYear) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName;
    this.birthYear = birthYear;
  }
  public String getSsn() {
    return ssn;
  }
  public String getFirstName() {
    return firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public Integer getBirthYear() {
    return birthYear;
  }
}

Then an instance of Person class called p is subjected to two validation rules defined above. We can denote above rules as four expression-syntax Strings :
“p.ssn != null”, “p.birthYear < 1990″, “p.firstName != null”, and “lastName != null”

2. The Validation Class
First we define a base abstract class called JexlObjectValidator

import java.util.List;
public abstract class JexlObjectValidator {
 // A list of JEXL expressions
 protected List<String> jexlExprRules;

 public JexlObjectValidator() {
 }
 public JexlObjectValidator(List<String> jexlExprRules) {
 super();
 this.jexlExprRules = jexlExprRules;
 }
 /**
 *
 * JEXL expression based general object validation.
 * See latest JEXL details at http://commons.apache.org/jexl/
 *
 * @param o
 * @return Return null if no error found.
 *         Otherwise first error of the JEXL expression validation rules.
 */
 public abstract ValidationError validate(Object o) ;
}

In this class the “List<String> jexlExprRules” attribute holds a list of String-based validation rules. The ValidationError validate(Object o) method validates
a given object based the specified jexlExprRules.
The ValidationError class simply holds the detailed message if the object is not valid. It may look like this:

public class ValidationError {
 private String errCode;
 private String errMsgs;

 public ValidationError(String errCode, String errMsgs) {
 super();
 this.errCode = errCode;
 this.errMsgs = errMsgs;
 }

 public String getErrCode() {
 return errCode;
 }
 public String getErrMsgs() {
 return errMsgs;
 }
}

Now we are ready to implement the validator for a person object.

import java.util.List;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
public class PersonObjectValidator extends JexlObjectValidator {
 public PersonObjectValidator(List<String> jexlExprRules) {
 super(jexlExprRules);
 }

 public ValidationError validate(Object o) {
 Person person = (Person)o;

 JexlEngine jexl = new JexlEngine();
 JexlContext context = new MapContext();
 context.set("p", person);
 for (String expr : jexlExprRules ) {
 Expression e = jexl.createExpression( expr );
 Boolean isValid = (Boolean)e.evaluate(context);
 if (!isValid) {
 // Whoops, invalid object
 return new ValidationError("personErr", e.getExpression());
 }
 }        
 // OMG, an valid object!
 return null;    
}

}

In the validate(Object o) method, we first cast it to Person type and then initialize a JexlContext called “context”. Then we place the “person” object into the context with a name “p”.
We then iterate through rule list “jexlExprRules” to evaluate each expression rule against the given object “person” stored in the context. If any rule fails, we stop and return the ValidationError object with failure message(highlighted in above bold text). Otherwise return null for a valid object.

From the above sample code, you can see Jexl in the works  in these three simple validation steps:
(1) Use the JexlEngine object to create a Jexl Expression based a Jexl-syntax expression String
(2) Use the JexlContext object to hold an object to be validated(It holds more than one object in real-word applications)
(3) Use the jexl Expression created in step (1) to evaluate against the object stored in the context

You might wonder why the above expression’s evaluate(context) method call result can be cast to a Boolean object. The reason is the expression we defined earlier such as p.ssn != null always returns a boolean value. JEXL expression can return any object based on the expression defined by your application – it could be an Integer or a specific domain object etc.
Please refer to http://commons.apache.org/jexl/index.html for more details.

3. The Validation Process
The following unit test mocks the scenarios we defined in section 1(A Simple Validation Problem) – in which the same person object  is valid in Bonus-prize-draw application component while invalid in Guest-book sign-up component.

package sandbox.util;

import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
public class PersonObjectValidatorTest extends TestCase {
 private List<String> rule1;
 private List<String> rule2;
 private Person p;

 protected void setUp() {
 // Rule 1
 rule1 = new ArrayList<String>();
 rule1.add("p.ssn != null");
 rule1.add("p.birthYear < 1990");    
 // Rule 2
 rule2 = new ArrayList<String>();
 rule2.add("p.firstName != null");
 rule2.add("p.lastName != null");    
 // Person object to be validated
 p = new Person("123-45-1234","John", null, 1980);

 }
 // The person object is valid in one run-time application case
 public void testValidPersonObjectInBonusPrizeDrawComponent() {    
 PersonObjectValidator validator = new PersonObjectValidator(rule1);
 ValidationError err = validator.validate(p);
 assertNull(err);
 }
 // The same person object is invalid in another run-time application case
 public void testInValidPersonObjectInGuestbookSignupComponent() {
 PersonObjectValidator validator = new PersonObjectValidator(rule2);
 ValidationError err = validator.validate(p);
 assertNotNull(err); // The lastName is null to cause the person object being invalid
 }
}

Notice JEXL uses Java Reflection API extensively and above “p.firstName != null” rule is actually invoked as “p.getFirstName() != null”. In real-world application, your expression can contain any method call on the object.

4. Conclusion

The example here is extremely simple to just demo the dynamic object validation. In above unit test code, you can see the validation rule is specified as List<String> and you can load them from a configuration file/DB table in your application. This way you can re-configure rules dynamically per your application needs.

The above sample code uses apache-commons-jexl-2.0 and can be downloaded at http://commons.apache.org/jexl/index.html. Or if using Maven project build, the dependency entry is

<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-jexl</artifactId>
 <version>2.0</version>
</dependency>

A Simple String Cipher in Java 6

March 6, 2010

For regular simple application, Java Cryptography seems always complicated. But for Java 6, AES is included. Here is a simple cipher to encrypt a text string into another string which can be used safely in web environment with proper url encoding included.

package sandbox.util;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
 * A simple text cipher to encrypt/decrypt a string.
 */
public class SimpleStringCipher {
 private static byte[] linebreak = {}; // Remove Base64 encoder default linebreak
 private static String secret = "tvnw63ufg9gh5392"; // secret key length must be 16
 private static SecretKey key;
 private static Cipher cipher;
 private static Base64 coder;

 static {
 try {
     key = new SecretKeySpec(secret.getBytes(), "AES");
     cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "SunJCE");
     coder = new Base64(32,linebreak,true);
 } catch (Throwable t) {
     t.printStackTrace();
 }
 }

 public static synchronized String encrypt(String plainText) throws Exception {
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherText = cipher.doFinal(plainText.getBytes());
        return  new String(coder.encode(cipherText));
 }

 public static synchronized String decrypt(String codedText) throws Exception {
        byte[] encypted = coder.decode(codedText.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decrypted = cipher.doFinal(encypted);  
        return new String(decrypted);
 }

}

A few notes about this code:

1. Encryption for simple and fast text encryption with Java 6 built-in AES implementation and Apache commons-codec-1.4 for text encoding.
2. The “secret” key is hard-coded in the source per your application compilation. You may expose it to configuration when needed.
3.” new Base64(32,linebreak,true)” construct  is used to provide proper url encoding and remove default linebreak. The encrypted text is safe to be used in browser window.

Here is the unit test to demo the usage:

public class SimpleStringCipherTest extends TestCase {

   public void testBasicEncrption() throws Exception {
                String plainText = "2010 starts new decade.";
                String encrypted = SimpleStringCipher.encrypt(plainText);
                assertTrue(!plainText.equals(encrypted));

                String decrypted = SimpleStringCipher.decrypt(encrypted);
                assertEquals(plainText, decrypted);
   }

}

Java Tip: Deploy WAR to multiple Tomcat-6.x Nodes/Environments with Cargo Maven-plugin

October 25, 2009

In JEE/Tomcat-6.x web development, if you use Maven you can easily deploy your build to local host via “mvn tomcat:redeploy” with these two simple changes:
(1). In Tomcat context.xml,  disable jar locking by adding extra attributes(in bold text) to <Context> tag:
<Context path=”/<your-webapp-path>”
reloadable=”true”
antiJARLocking=”true”

antiResourceLocking=”true”
>
(2).   Set tomcat manager user/password as default “admin” and empty string “”

But Cargo maven-plugin(http://cargo.codehaus.org/Maven2+plugin) is more powerful to deploy your build to QA/Production environments easily.

1. Set up your default deployment target as dev environment

In your POM.xml, add these entries with bold text indicating your environment related values :

<!– default cargo deployment target –>
<cargo.manager.url>http://<your_dev_server>:<dev_host_port>/manager</cargo.manager.url>
<cargo.username>dev_username</cargo.username>
<cargo.password>dev_password</cargo.password>

<!– Cargo-Plugin: Hot deploy to remote tomcat6x running instance –>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat6x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.tomcat.manager.url>${cargo.manager.url}</cargo.tomcat.manager.url>
<cargo.remote.username>${cargo.username}</cargo.remote.username>
<cargo.remote.password>${cargo.password}</cargo.remote.password>
</properties>
</configuration>
<deployer>
<type>remote</type>
<deployables>
<deployable>
<groupId>***your group id***</your></groupId>
<artifactId>***your_build_id***</artifactId>
<type>war</type>
<properties>
<context>***your_context****</context>
</properties>
</deployable>
</deployables>
</deployer>
</configuration>

</plugin>

Run “mvn clean build” and “mvn cargo:redeploy” to verify that your build can be deployed to dev box without problem.

2. Assume we have one QA and one production tomcat-6.x instances. Simple add these two profile entries to your POM.xml:

<!–  QA env deployment target –>
<profile>
<id>qa1</id>

<properties>
<cargo.manager.url>http://<qa1_host>:<qa1_port>/manager</cargo.manager.url>
<cargo.username>qa1_username</cargo.username>
<cargo.password>qa1_password</cargo.password>
</properties>
</profile>
<!–  Production  env deployment target –>
<profile>
<id>prod1</id>

<properties>
<cargo.manager.url>http://<prod1_host>:<prod1_port>/manager</cargo.manager.url>
<cargo.username><prod1_user></cargo.username>
<cargo.password><prod1_password></cargo.password>
</properties>
</profile>

Now you can just run “mvn build”, then “mvn cargo:redeploy -Pqa1″ and “mvn cargo:redeploy -Pprod1″ to deploy your war file to tomcat-6x instances.  Of course in real application, you have multiple instances in each environment and you can simply add “qa2″, “prod2″ etc entries in your POM.xml(if necessary, place production entries in  maven setting.xml to protect passwords)

Note, in tomcat hot deployment, you may run into JDK’s PermGen out of memory error after hot deployment.  So you should restart tomcat instances after deployment run. More details can be found at http://wiki.apache.org/tomcat/OutOfMemory

Java Tip: Using Open Source Selenium-Grid-1.x for Quick Performance Testing

October 25, 2009

When conducting performance testing of multi-step interactive web applications such as registration, shopping etc, not many open source solutions are available. Grinder(http://grinder.sourceforge.net/) is the primary choice, however it is not simple to use.  Selenium is well-known for its ease to use record-and-replay feature, but it is primarily for unit/functional testing.

Thoughtworks recently put out a new tool called Selennium-Grid(http://selenium-grid.seleniumhq.org/) to speed up integration tests. However  it can also be used for a quick developer-driven performance testing.  Here are the brief steps to do it:

1. Development Setup
- Install Java6, latest Eclipse-3.x and latest Selenium IDE/RC/Grid
- Download latest TestNG-5.X(for parallel unit tests run)
- Install TestNG Eclipse-3.x plug-in(Start/Stop tests from your IDE)

2. Create  Java Performance Test Code
The performance testing will be carried out in the form of running multiple unit tests’ test methods in concurrent mode.

2.1 Use Selenium IDE to record your typical multi-step application user case for a given user and save it as Java code, and then refine this Java code as a base unit test class(make sure it is thread-safe). The code skeleton may look like this:

public abstract class SeleniumPerfTestBaseCase
{

public static final String TIMEOUT = “120000″; // testing run timeout
// @para User class is a value object to contain test parameters for a single User, such as ID, username, password etc
protected void testMultiStepApplicationByOneUser(User user ) throws Exception {

// Your recorded test case code goes here

//Some Thread.sleep() calls may be needed to adjust user think time

}

}

2.2 Implement a test case with multiple users. Each user corresponding to a method call. The code skeloten may look like this:

import static com.thoughtworks.selenium.grid.tools.ThreadSafeSeleniumSessionStorage.closeSeleniumSession;
import static com.thoughtworks.selenium.grid.tools.ThreadSafeSeleniumSessionStorage.startSeleniumSession;
import org.testng.annotations.Test;

public class ConcurrentUserLoadTest extends SeleniumPerfTestBaseCase  {
// Testing env parameters, such as
private String seleniumGridHost = “my_selenium_grid_host”;
private int seleniumGridHostPort = xxxx;
private String browser = “*firefox”;
private String testingTargetWebSite = “http://blah-blah-blah/”;

// User 1 test
User user1 = new User( “username1″, “passwd1″, “myemail1@gmail.com”, “checkout”);
@Test(groups = {“demo”, “firefox”, “default”}, description = “test my shopping”)
public void testUser1() throws Throwable {
try {
startSeleniumSession(seleniumGridHost, seleniumGridHostPort, browser, testingTargetWebSite);
testMultiStepApplicationByOneUser(user1);
} finally {
closeSeleniumSession();
}
}

…….. Repeat above code for X number of users, say we test 50 users here

// User 50 test
User user50 = new User( “username50″, “passwd50″, “myemail50@gmail.com”, “checkout”);
@Test(groups = {“demo”, “firefox”, “default”}, description = “test my shopping”)
public void testUser50() throws Throwable {
try {
startSeleniumSession(seleniumGridHost, seleniumGridHostPort, browser, testingTargetWebSite);
testMultiStepApplicationByOneUser(user50);
} finally {
closeSeleniumSession();
}
}

}

2.3 Finally in your testng cfg file, specify your test class,  parallel for methods and thread count for your performance test

<!DOCTYPE suite SYSTEM “http://testng.org/testng-1.0.dtd”>
<suite name=”my-webapp” parallel=”methods” thread-count=”25“>
<test verbose=”2″ name=”PeakUserLoadTest” annotations=”JDK”>
<classes>
<class name=”ConcurrentUserLoadTest“/>
</classes>
</test>
</suite>
Notice we set thread count as “25″ here which means above 50 test methods will be finished in 2 iterations where each thread runs two test methods sequentially. You can adjust these parameters however you want to suit your test needs

3. Testing environment  setup
3.1 Base on your performance testing goal, make available a number of PCs. Install Selenium-Grid on one of them and rest with Selenium RC along with Firefox. The PCs with Selenium RC are the ones to actually generate the testing traffic by firing up Firefox browsers to complete a user test case.
3.2 Start up SeleniumGrid and SeleniumRC on all PCs and follow Selenium web site instructions on how to do it. Once it is done, check SeleniumGrid console page and verify that all the RC clients are available for testing.

4. Running the Test
Last step is easy, just fire up your test case in Eclipse IDE  and watch firefox browsers pop-up all over the screens. Record your client and server site test results.

You may need to several test runs to iron out some wrinkles.
-  You may need to adjust user think time in your base test class when running in parallel
- Sometimes one PC may be less powerful and can not handle the traffic, you need to add more PCs or reduce thread count
- Sometimes SeleniumGrid and its RC clients may be out of sync and you need to restart them all over again. This is a bit annoying and future Selenium releases sure will improve its reliability.
- SeleniumGrid does not have Maven dep entry, and you need to install manually if Maven is used.

5. Final comments
- Performance testing definition may be very broad. The above quick test is for a peak traffic run. You also can easily modify the code to add some loops to mimic long running user traffic and  see if you have slow memory leak etc
- The Selenium Testing tools triggers real browser run during the testing and system resource overhead is high and hence this approach is not suitable for large-scale performance testing.  In our experience each PC roughly can handle 10 parallel users at a time, but again it is totally depends on how powerful your PC is.

Quick Scan of Free(mostly) Testing Tools

May 19, 2009

Today I spent a few hours Googling over some free testing tools and here are the list I came up – which are relatively active ones based on the release date.  I am no expert in testing tools and posted here just as sort of bookmarks for possible future reference.

Database Tier Testing Tools

1. AnyDbTest from http://www.anydbtest.com/: DBA/DB developers tool in which test case is written in XML. $1245.00 for 10 lic#
2. DbFit from http://gojko.net/fitnesse/dbfit/: FIT/FitNesse tests for DBA/DB developer. Free
3. DBUnit from http://www.dbunit.org/: Export real data to XML file as controlled dataset for unit test runs. Free
4. ndbunit from http://code.google.com/p/ndbunit/: .Net’s DBUnit
5. Quest Code Tester from http://unittest.inside.quest.com/index.jspa: PL/SQL testing tool. Commercial Ware/Fee?
6. SQLUnit from http://sqlunit.sourceforge.net/: A junit extension to test stored procedure easily via XML test case scripting.

Another one is tsqlunit from http://tsqlunit.sourceforge.net/index.html. Free
7. If you are using Spring, you may use spring-mock.jar to test against either DBUnit or a real database. The nice feature of it is that it rolls back transaction automatically after test run and hence will not change the state of a real database. Free
8. If you are using Google AppEngine/Java edition, it provides a local test persistence impl to present a clean DB in junit setUp() for your subsequent unit test runs. Free
Google AppEngine/Java is using google’s own OO database(Big Table) and annotation of an entity class is the only thing needed to persist the data – no more ORM mapping to deal with which is quite nice and simple. See http://code.google.com/appengine/docs/java/howto/unittesting.html

General Unit Testing Tools
9.  junit from http://junit.org/. Most popular. Free
10. nunit from http://nunit.org. Free
11. jExample from http://scg.unibe.ch/research/jexample/. It uses producer/consumer model for mocking and seems unique. Free
12. JDave from http://www.jdave.org/ for behavior driven development among few others. Free
13. GroboUtils from http://groboutils.sourceforge.net/. It supports both code-coverage and multi-thread tests which is not very common among xUnit like tools. Free
14. testNG from  tehttp://testng.org/doc/ which provides more advanced features. Free
15. csUnit from http://www.csunit.org/ it works with most .NET/Vista/XPsp3 platforms and compatible with NUnit/VS2008(i.e.MSTest). It also supports searching test cases.
16. Mb.Unit from http://www.mbunit.com/ More feature rich testing tool which is running on the more general open source .NET platform http://www.gallio.org/. Free
17  testDriven.NET from http://www.testdriven.net/
18  specter from http://specter.sourceforge.net/ which integrates with NUnit. It is using Boo static-typed language(http://boo.codehaus.org/) for test case scripting. Free
19. Pex from http://research.microsoft.com/en-us/projects/Pex/ It allows whitebox testing automation via Parameterized Unit Testing.

Container Testing Tools
20. Cactus from http://jakarta.apache.org/cactus/. In-container testing and integrated with Cargo(http://cargo.codehaus.org/) andHttpUnit, so config files tests are covered. Free
21. Mockrunner from http://mockrunner.sourceforge.net/ does not run real container and hence is simple, but cfg files may not be covered as API is used in the test cases. Free
22. UncleBob shows primitive ways to test jsp http://blog.objectmentor.com/articles/category/testing-guis via apache Jasper & HtmlUnit. This can avoid some fragile tests that break when the format of a page changes(such as Selenium, Mercury :) )

WebService Testing Tools
23. soapUI from http://www.soapui.org/. Most popular web service testing tool and supports load testing as well. Free
24. TestMaker from http://www.pushtotest.com/ and written in Jython. So it is extremely powerful to write test cases not just for web service, but for almost everything – HTTP, POP3, JDBC etc
but it also triggers higher learning curve as well. Free
25. WebInject from http://www.webinject.org/ It is a simple and light testing tool. Free

RIA/Flex Testing Tools
26. FlexUnit from http://opensource.adobe.com/wiki/display/flexunit/FlexUnit(used to be http://code.google.com/p/as3flexunitlib/). Most popular one for Flex2&3. Ant build and HTML output format. Free
27. Reflex Unit from http://code.google.com/p/reflex-unit/. Using Reflection to specify target test methods and also allow async tests running in parallel. Multiple output formats. Free
28. fluint from http://code.google.com/p/fluint/ Support Async UI action testing and cairngorm command/controller testing. ant build and XML output format. Free.

Integration/Acceptance Testing Tools
29. fitnesse http://fitnesse.org/ general acceptance tool. Free
30. concordion from http://www.concordion.org/ documentation driven testing. Free
31. texttest from http://texttest.carmen.se/ which plain text is the focus of high level test cases for non-tech people. Free
32. jbehave from http://jbehave.org/. Similar to item 12. for BDD testing.
33. Selenium from http://seleniumhq.org/ for web tier testing. Free.
ThoughtWorks also provides commercial ware Twist – http://studios.thoughtworks.com/twist-agile-test-automation

34. FlexMonkey from http://code.google.com/p/flexmonkey/ for Flex2&3 integration tests.
35. FunFx from http://funfx.rubyforge.org/ It is Ruby based functional testing tool for FLEX.

Code Coverage Tools
36. NCover from http://www.ncover.com/ code coverage tool for C#, .NET. Commercial Ware.
37. PartCover from http://sourceforge.net/projects/partcover/ for .Net, but it is free.
38. cobertura from http://cobertura.sourceforge.net/ for Java unit test coverage. Free.
39. codecover from http://codecover.org/ for Java unit test coverage. It supports more detailed coverage analysis such as correlation analysis. Free
40. EMMA from http://emma.sourceforge.net/ for Java code coverage with test case filtering support
41. Clover from http://www.atlassian.com/software/clover/ for Java code coverage. Commercial ware, but free for open source project only.

Mocking Tools
42. typemock from http://www.typemock.com It supports most framework such as WCF, Sharepoint, LINQ, Silerlight. Commercial ware.
43. jmockit from https://jmockit.dev.java.net/ It is for writing unit or integration tests via non-reflection based approach.Free
44. Easymock from http://www.easymock.org/ Java proxy-based mock object. Free.
45. jmock from http://www.jmock.org/ More popular java mock framework. Free
46. Rhino Mock from http://ayende.com/projects/rhino-mocks.aspx for .Net unit test mocking. Free

Adobe AIR Tip: Avoid File Drag-and-Drop Side Effect with DataGrid

May 8, 2009

In AIR application, if you enable drag-and-drop capability say for a file, be careful with dropEnabled=”true” attribute in a DataGrid control inside your application. If you have both turned on, the top-level drag-and-drop may not work smoothly.  The sample code here shows the issue:

<?xml version=”1.0″ encoding=”utf-8″?>

<mx:WindowedApplication xmlns:mx=”http://www.adobe.com/2006/mxml”
creationComplete=”init()” layout=”vertical”>

<mx:Script>
<![CDATA[
import mx.managers.DragManager;

import mx.collections.ArrayCollection;
[Bindable]
private var myData:ArrayCollection;

private function init():void
{
addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, dragEnter);
addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDropHandler);
}
private function dragEnter(event:NativeDragEvent):void
{
DragManager.acceptDragDrop(this);
}
private function onDropHandler(event:NativeDragEvent):void
{
trace(“Handle dropped file…”);
}

]]>
</mx:Script>

<mx:Label text=”Control 1″/>

<mx:DataGrid id=”myGrid” dropEnabled=”true”/>

<mx:Label text=”Control 2″/>

</mx:WindowedApplication>

In above code, the init() enables application level drag-and-drop,  and at same time, the “myGrid” DataGrid has attribute dropEnabled=”true” .  When you drag-and-drop a file to the application, it may not work 100% of the time, particularly when your application has many controls.

In summary, you should avoid above case in which two-level drag-and-drop are enabled.


Handling Large Collection Data – Hibernate Pagination, ScrollableResults and Native SQL

April 24, 2009

In Hibernate it is common to fetch a collection of data like this:

List l = session.createQuery(“select * from … “).list()

However this solution may not scale well if the query returns large amount of data(such as in a batch job etc):

-  Consuming a lot of memory

-  Possible slow speed as large data being moved and processed between middleware and database

Here we discuss a number of options to improve the performance of handling large data set.

(1). Hibernate Pagination

The idea here is to divide the large result set into a number of pages and fetch only one page at a time.  You need to specify the start position and the page size in the query parameter. If not in original query yet, you also need to add an “order by” clause to ensure the result data set is sorted and kept in a consistent view of data between pages.

The code itself is very simple:

Query q = session.createQuery(select * from ... order by ...");
q.setFirstResult(startPosition);
q.setMaxResults(pageSize); List l = q.list();

This solution resolves the memory issue nicely and works with most major databases via different dialects offered by Hiberante. For instance in a search-like application, this works well as an user may click through different search result pages.

However if an application does need to process all the result set data this approach may significantly increase query execution time as previously a single query becomes a large number of queries. For example, if the original query returns 100k rows and the page size is 100, the total queries to be run in the pagination would be 1000. The “order by” clause may also impact the query time as well. You also need to figure out total number of pages in which another query “select count(*) from … ” is added.

(2) Hibernate ScrollableResults

This approach loops through the entire results set in a stream fashion, thus will not incur significant slow-down in query execution time.

      Query q = session.createQuery("select * from ...");
      ScrollableResults results = q.scroll();
       while (results.next() )
       {
         Long id = results.getLong(0); ...
      }
      results.close();

Moreover if session cache is enabled, you need to add explicit code to clear the session cache, such as a code snippet here to clear cache every 100 rows:

 readCount++;
if ( readCount % 100 == 0) {
session.flush();
session.clear();
}

Hibernate has different level of caching and be careful about it. If session cache is not cleared periodically and the results set data is large, you will soon get out-of-memory error.

This approach has some drawbacks as well: business logic may be moved to dao tier; the connection remains open during entire operation; some databases may not support this feature(need to check the related jdbc driver)


(3) Native SQL

If operation speed is a major issue and none of above solutions is fast enough, you may consider to move the entire operation to database side via native jdbc and/or stored procedure. This approach can leverage database specific features to improve performance, and may also reduce unnecessary data transportation between middleware and database. In some real applications, we have some very I/O intensive operations and execution time is reduced significantly(3~5 times) via direct jdbc sql.

However this approach makes your application database specific and actual performance improvement will be based on application’s specific behaviors. It also moves the cpu and I/O load to database server and all needs to be considered before hand.

Summary

When dealing with large data, we list three solutions to improve performance.


Solution Memory usage Speed Portablity across databases Simplicity
Hibernate pagination Bound Slow Most Simplest
Hibernate ScrollableResults Conditional bound (explicit clear session cache needed) Fair Somewhat(depends on driver) More work(biz logic moved to dao tier)
Nativce SQL/Stored Procedure Bound Fast No Most amount of work

Each solution has its advantages and disadvantages. Based on each application’s specific requirements, you may choose a proper solution here.

     

Integrate Fluint Testing with Apache Ant in Adobe AIR Application build

April 24, 2009

In my last post “Using Apache Ant to Compile, Test and Package Adobe AIR Application” we discussed how to do ant build with flexunit. In this post we replace flexunit with fluint for unit/integration tests. The main benifit of fluint is that it allows you to do sequenece tests – simulating an user’s click sequence in a Flex application. It is a white-box testing as FlexMonkey is a black-box testing tool.

You first need to go to fluint home http://code.google.com/p/fluint/ to download the package and follow the instructions to install the AIR test runner.

Here are the steps after you have fluint installed:

Step 1: fluint uses module to control the tests insteadof WindowedApplication in flexunit.The sample module here is called MyAIRUnitTestsModule.mxml which may look like this in which MyTestSuite class contains all your individual tests:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Module xmlns:mx=”http://www.adobe.com/2006/mxml” implements=”net.digitalprimates.fluint.modules.ITestSuiteModule”>
<mx:Script>
<![CDATA[
import test.com.mycompany.test.MyTestSuite;

public function getTestSuites() : Array
{
var suiteArray : Array = new Array();
suiteArray.push( new MyTestSuite()() );
return suiteArray;
}
]]>
</mx:Script>
</mx:Module>

Step 2: In build.xml’s unittestcompile target, replace flexunit lib with fluint:

<arg line=”-library-path+=’${basedir}/libs/fluint-1.1.0.swc’”/>

Step 3: In build.xml, replace unittest target with:

<target name=”unittest” depends=”unittestcompile”>
<delete dir=”${reports.dir}” />
<mkdir dir=”${reports.dir}”/>

<!– Run the tests –>

<taskdef name=”fluint”
classname=”net.digitalprimates.ant.tasks.fluint.Fluint”
/>
<fluint
debug=”true”
headless=”true”
failonerror=”true”
workingDir=”${APP_ROOT_DIR}”
testRunner=”C:\Program Files\FluintAIRTestRunner\FluintAIRTestRunner.exe”
outputDir=”${reports.dir}”>

<fileset dir=”${UNITTEST_OUTPUT}”>
<include name=”MyAIRUnitTestsModule.swf”/>
</fileset>
</fluint>

</target>

unit test results are stored in the directory specified in above outputDir switch.

testRunner switch indicates its location(win xp path in this example)

Quick summary

- fluint allows white-box integration tests against Flex UI components in addition to normal unit tests

- fluint uses Module for AIR unit tests

- fluint uses its own FluintAirTestRunner.exe(itself is an AIR application, so AIR runtime is required) to the tests.


Follow

Get every new post delivered to your Inbox.