Wednesday, April 22, 2009

Using field level access for hibernate entities

Hibernate allows you to configure the access mechanism for attributes in the entity object. It can access the attributes directly or through the accessors. The field or property access type is decided by hibernate based on the location of @Id or @EmbeddedId.

@Entity
public class Item {
@Id
public String id;
public long itemNumber;
}

@Entity
public class FoodItem {
private String id;
private long foodId;

@Id
public String getId(){
return id;
}
public long getFoodId(){
return foodId;
}
}

In the above code, Item class uses field access and FoodItem class uses property access.

Using property access mechanism allows classes to hide the internal data structure from the external world and it enables class to perform validations while setting the value or while accessing it. It is useful when we want to perform some calculation before returning the result or setting the value.

However, mostly we end up directly accessing the variable from the getter and setter methods. In that case, property access is overkill. It makes us write lot of getter - setters which are not used anywhere else in the code. It also exposes setters if when we don't want anyone to set the value of fields like 'id'. We can mark the accessors private or protected and avoid this problem, but we will still have the code.

IMHO, while creating the entity, we should start with field level access. Doing so will reduce the unnecessary code which is used only by hibernate. We should keep the fields private and provide accessor methods only when required. So our entity object will be modeled by the needs of the application and not by the hibernate. In future, if we need to validate or manipulate the values set on the object (which mostly won't happen), we can then switch to property access, but we shouldn't start with it.

Adding static @BeforeClass method in the test class

I was looking at a integration test in project that takes 10 seconds to execute. Its a integration test in a for a class that connects to the FTP server and performs some operations. The test uses a in-memory mock ftp server. The issue is that it starts, initializes the mock file system for every test and then stops the server after each test. The initialization code is written as a part of @Before method and server is stopped in @After method. The fact that the server was getting started and closed for every test was the reason why test was so slow. I want to start and initialize it only once for the all the tests my my class. The way to achieve this is to use @BeforeClass annotation. The method marked with @BeforeClass runs only once for all the test. The corresponding tear down method is @AfterClass. By using @BeforeClass instead of @Before and with some other changes, I was able to reduce the time required to run the test to 3 seconds.

However, using @BeforeClass instead of @Before may make tests dependent on each other and on the order of execution. As all the tests will use the same objects, changes made by one test will be affecting others. So @BeforeClass method should be used to initialize objects which are not modified by the tests. The methods should be used to setup the environment for the test and not for creating the objects that will be directly consumed by the tests.

@BeforeClass (and @AfterClass) method has to be static, which means all the variables that are accessed in this method has to be maked as static. This puts up restrictions on the ways in which @BeforeClass can be used, but this makes it explicit that the @BeforeClass method should be used to set only the environment for the test and objects under test itself.

Tuesday, April 7, 2009

Improved modularity with Superpackages in Java7

JSR 294 talks about introducing improved modularity support with Superpackages.
Right now modularity is supported at various levels in Java language. Modularity provides encapsulation and information hiding at various levels. Method encapsulates certain program logic and local variables. Class encapsulates instance variables and methods and a package provides a module to group related classes. All these modules helps us to understand and change the system locally, within the module space without worrying about its effect outside the module.

However, the modularity supported by packages is inefficient in some cases. The problem is that packages supports hierarchy, file system also stores classes in the hierarchy, but the accessing member of the package is not hierarchical. There is no special relationship between packages and their children or parents. We create packages like com.domain and com.domain.validators. Clearly, there is some kind of hierarchical relationship between the classes in two packages. You may want to access some classes or methods of com.domain from com.domain.validators package, but you don't want to expose them to the whole world by making them public. The scenario is very well explained by Neal Grafter at http://www.infoq.com/interviews/gafter-closures-language-features-optional-typing. Currently, there is no way to achieve this directly.

We can use default member access so that it becomes public within the same package, but stays inaccessible to the outside world. Classes in the subpackages also can not access it. So we end up putting classes in the same package as we want to access members with the default access. This leads to packages with large number of classes, the classes which should ideally go in the sub packages.

The other option is to make the members public. Doing this may expose unwanted API. We will end up relying on the official documentation of the API and prays that no one comes to know about the class and invoke its 'public' method. The issue is public is too public.

We need a module entity that is bigger than a package but narrower than public. The solution is to introduce one more level of modularity called Superpackages. Superpackages contains classes from one or more packages or superpackages. Its a new construct which is put into super-package.java file and compiled by the Java compiler. The types can be exposed to the outside world by exporting them. Only the exported types are visible outside the superpackage. Public types that are not exported can not be accessed outside of superpackage.
e.g. A superpackage which encapsulates types in com.domain and com.domain.validators is defined as -

superpackage domain {
// member packages
member package com.domain;
member package com.domain.validators;

// exported types
export com.domain.*;
}

Here, only classes from com.domain package is visible outside superpackage, classes from com.domain.validators are not.Note that Java classes doesn't specify the superpackage they belongs to. It is specified in the super-package.java file only.
Superpackages can encapsulate other superpackages as well. Only the public types in exported superpackage will be accessible from outside.

Superpackages is coming up with Java 7 and going to be an effective mechanism for information hiding in Java.