Thursday, August 27, 2009

Java EE and Cloud Computing

I would like to share this interesting article on Java EE and Cloud Computing.

Monday, August 10, 2009

JUnit 4.0

Junit 4.0 is very different from its previous versions. I present the features followed by examples.


JUnit 4.0 features:

  • Uses annotations and makes life very easy.
  • Test Class DOES NOT have to extend TestCase.
  • Need to manually do "import static org.junit.Assert.*" to get all the methods like AssertFalse and AssertTrue as the Test class does not extend TestCase.
  • All methods that needed to be tested should be decorated with @org.junit.Test annotation and you can use any method name.
  • @Test notatation takes an expected parameter which can be used to specify the exception the method should throw.eg: @Test(expected=IndexOutOfBoundsException.class) The test fails if the expected exception is not thrown.
  • To not test a particular method , decorate it with the annotation @org.junit.Ignore
  • Can specify a timeout for a method, if the method runs for a longer time, it fails. eg: @Test(timeout=1)- AssertEquals can test arrays, so we don't need to iterate over contents of array.
  • Can use annotations to specify test fixtures.
  • There are 2 Class level fixtures: @BeforeClass and @AfterClass. These are run only once before or after the tests in the class are run. Note: Can create multiple @BeforeClass fixtures though the order of running them cannot be currently
    specified.
  • There are 2 Method level fixtures: @Before and @After. These are run before or after running every test (method) in the class.
  • Can use annotations to specify test suites.
    @RunWith(Suite.class)
    @Suite.SuiteClasses( { <YourTestClass1>.class,[<YourTestClass2>.class] })
    public class <SuiteName> {
    }
  • Introduces a new runner called Parameterized. It allows the same tests to be run with different data. One of the examples below shows how to run Parameterized test. To enable this do the following:
    • Have the annotation @RunWith(value = Parameterized.class) for the Test Class
    • Have a public static method that returns a Collection for data. Each element of the collection must be an Array of the various paramters used for the test.
    • Provide a public constructor for the test class that uses the parameters.

Examples:

Java code on which the tests have to be run


import java.util.HashMap;
import java.util.Map;

public class SimpleExample {

private Map<Integer, Employee> emp;

public SimpleExample() {
emp = new HashMap<Integer, Employee>();
}

public void addEmployee(String name, int id) {
Employee e = new Employee(name,id);
emp.put(id, e);
}

public String getEmployeeName(int id) throws EmployeeException{
if (!emp.containsKey(id)) {
throw new EmployeeException("No Employee with the id " + id);
}
return emp.get(id).getEmpName();
}

public int getNumberofEmployees(){
return emp.size();
}


}

class Employee {
private String empName;
private int empID;

Employee(String name, int id) {
empName = name;
empID = id;
}

public String getEmpName() {
return empName;
}

public int getEmpID() {
return empID;
}
}

public class EmployeeException extends Exception {

private static final long serialVersionUID = 1L;

EmployeeException(String ex) {
super(ex);
}

}


Example 1: JUnit 4.0 test cases for the above class


import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class SimpleExampleJUnitTest {

private static SimpleExample se;
private static final String NAME1 = "foo";
private static final String NAME2 = "bar";

@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass: run only once");
se = new SimpleExample();
se.addEmployee(NAME1, 1);
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass: run only once");
se = null;
}

@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void addEmployeetTest() {
se.addEmployee(NAME2, 2);
assertEquals(se.getNumberofEmployees(),2);
}

@Test
public void getExisitingEmployeeNameTest()
throws EmployeeException {
assertEquals(se.getEmployeeName(1),NAME1);
}

@Test(expected=EmployeeException.class)
public void getNonExisitngEmployeeNameTest() throws EmployeeException {
se.getEmployeeName(10);
}

@Ignore
public void getAllEmployeesTest() {
//Not yet implemented.
}
}


Example 2: Parameterized JUnit 4.0 test case


import static org.junit.Assert.*;

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

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(value = Parameterized.class)
public class SimpleExampleParameterizedJUnitTest {

private SimpleExample se;
private String name;
private int id;

public SimpleExampleParameterizedJUnitTest(String name,int id) {
this.name = name;
this.id = id;
}

@SuppressWarnings("unchecked")
@Parameters
public static Collection data() {
Object[][] data = new Object[][] {
{ "foo", 1}, {"bar",2},{"foobar",3}};
return Arrays.asList(data);
}

@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass: run only once");
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass: run only once");
}

@Before
public void setUp() throws Exception {
System.out.println("setUp: run before every test");
se = new SimpleExample();
}

@After
public void tearDown() throws Exception {
System.out.println("teatDown: run after every test");
se = null;
}

@Test
public void addEmployeetTest() {
se.addEmployee(name,id);
assertEquals(se.getNumberofEmployees(),1);
}

@Test
public void getExisitingEmployeeNameTest()
throws EmployeeException {
se.addEmployee(name,id);
assertEquals(se.getEmployeeName(id),name);
}

@Test(expected=EmployeeException.class)
public void getNonExisitngEmployeeNameTest() throws EmployeeException {
se.getEmployeeName(id+1);
}

@Ignore
public void getAllEmployeesTest() {
//Not yet implemented.
}
}

Tuesday, July 28, 2009

Getting references to outer classes

Sometimes it is necessary to get references to the outer classes of an inner class. From within the inner class it is pretty straightforward to obtain the reference to the outer class. Just precede the keyword this with the outer class name. Here is a simple example:

public class OuterThis {
private String me = "OuterThis";
public class Inner1 {
private String me = "Inner1";
public class Inner2{
public void getEnclosingClasses() {
System.out.println(Inner1.this.me);
System.out.println(OuterThis.this.me);
}
}
}

public static void main(String[] args) {
OuterThis.Inner1.Inner2 in2 = new OuterThis().new Inner1().new Inner2();
in2.getEnclosingClasses();
}

}


You can also get the outer class reference through reflection. The this reference is encoded as this$n where n is an int specifying the level of the class. In the example above, this$0 is the outer class "OuterThis" while this$1 refers to "Inner1". So in the code above just do the following to get the enclosing class "Inner1" through reflection in the method getEnclosingClasses().
Inner1 in1 = (Inner1)getClass().getDeclaredField("this$1").get(this);

Reflection to obtain the outer class reference is usually used when you are outside the inner class. The following example illustrates it.

import java.util.ArrayList;

public class ExposeThis {
private String exposeThis = "Just Expose This";

public static void main(String[] args) throws
IllegalArgumentException, SecurityException, NoSuchFieldException,
IllegalAccessException {
Client cl = new Client();
new ExposeThis().registerMe(cl);
cl.printThis();
}

public void registerMe(Client client) {
client.addListener(new ClientListener(){});
}

public String toString() {
return exposeThis;
}

}

interface ClientListener {
}

class Client {
private ArrayList<ClientListener> clients = new ArrayList<ClientListener>();

public void addListener(ClientListener cl) {
clients.add(cl);
}

public void printThis() throws
NoSuchFieldException, IllegalArgumentException,
SecurityException, IllegalAccessException{
for (ClientListener cl: clients) {
//Get handle to OuterClass this by reflection
ExposeThis et =
(ExposeThis)cl.getClass().getDeclaredField("this$0").get(cl);
System.out.println(et);
}
}
}





Note:
Since it is possible to obtain references to enclosing classes by getting a handle to the inner class, one has to be very careful while working with inner classes.

Wednesday, July 22, 2009

Checked collections

The generics mechanism provides compile-time type checking. So generic collections are mostly type-safe. I did not say they will "always" be safe because it is possible to add wrong types into generic collections using unchecked casts. For instance mixing generic and non-generic code results in unchecked casts. The compiler will issue warnings when there are unchecked casts but the compilation does not fail. Also at runtime, when a wrong type is added to the parameterized collection no ClassCastException is thrown because the runtime has no knowledge of type parameters due to type erasure. So now, the wrong type is happily added to the collection. The problem of wrong type in the collection does not get discovered until much later. And when the problem is discovered, the runtime exception makes it quite impossible to discover the source of the problem i.e. where exactly the unsafe type got added. Here is a simple example followed by the runtime exception that the program throws when it runs.

import java.util.ArrayList;
import java.util.Collection;

public class UnsafeCollectionOperation {

public static void unsafeAdd(Collection c) {
c.add(new Integer(1));
}

public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("One");
c.add("Two");
unsafeAdd(c);
for (String s: c) {
System.out.println(s);
}

}

}




Here is what happens at runtime:
One
Two

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer
at UnsafeCollectionOperation.main(UnsafeCollectionOperation.java:17)


As you see from the exception above, the runtime exception does not offer any information on where exactly the unsafe type was added. My code is so small, so we can easily deduce where we went wrong, but when we deal with a lot of code, this task becomes very cumbersome. One way to deal with this problem is to use checked collection(see java.util.Collections). Checked collections are dynamically type safe views of collections. They perform a runtime type check every time an element is inserted into the collection. Any attempt to insert a wrong type will immediately result in ClassCastException. So we know exactly where we went wrong. Here is an example:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

public class CheckedCollection {

public static void safeAdd(Collection c) {
c.add("three");
}

public static void unsafeAdd(Collection c) {
c.add(new Integer(1));
}

public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("One");
c.add("Two");
Collection<String> checkedCollection =
Collections.checkedCollection(c, String.class);
safeAdd(checkedCollection);
unsafeAdd(checkedCollection);
for (String s: checkedCollection) {
System.out.println(s);
}

}

}



Running the program produces:
Exception in thread "main" java.lang.ClassCastException: Attempt to insert class java.lang.Integer element into collection with element type class java.lang.String
at java.util.Collections$CheckedCollection.typeCheck(Collections.java:2206)
at java.util.Collections$CheckedCollection.add(Collections.java:2247)
at CheckedCollection.unSafeAdd(CheckedCollection.java:14)
at CheckedCollection.main(CheckedCollection.java:23)


From the exception above we know exactly where we went wrong.
Couple of note worthy points are:
- When a checked collection view is created using an existing collection, it will NOT discover incorrectly typed elements, if they already exist in the collection prior to creating the view.
- After creating the checked collection view, if any access happens through the original collection and not through the checked collection, it cannot ensure type safety.
- There is a performance overhead of a runtime type check every time an element is inserted into the collection.