Monday, January 2, 2012

Hibernate Entity Generation Using Ant

Why would someone like to generate the sources from ant if its very easily generated through the IDE. The answer is simple: In a development environment different developers will use different versions of eclipse which will result in slightly different entities being generated. To provide the consistency across the team its better to have a ant or maven to generate the sources rather than rely on ide tools configuration.

Its very simple to generate the sources from ant's build.xml.

lets go through step by step


Build.xml is the file that the Ant uses to build the project. It has different tasks which we can use to perform different actions like compile, making jars, making wars, deployment etc. We will be using build.xml to generate sources. Hibernate tools comes with a predefined task which is org.hibernate.tool.ant.HibernateToolTask which is present in hibernate tools jar. We will be using this task to generate the sources.

1 Write a hibernate configuration file (a xml file.) which provides with all the details which the hibernate will require to connect to database. Hibernate will require
Username: username of the database
Password: password of the database
Schema: The name of the schema of the database
Driver: The driver to the database. For oracle its oracle.jdbc.OracleDriver
Connection Url: The connection url with portnumber, protocol and hostname.
Dialect: The dialect. For oracle 10 with hibernate its org.hibernate.dialect.Oracle10gDialect

At the end it will look like below.
oracle.jdbc.OracleDriver
development

username
password
org.hibernate.dialect.Oracle10gDialect


2 Write a reveng file which is an xml file which says which table metadata to be taken and converted to source.
For example:



3 Create a strategy class for the generation of classes. This strategy class will define the template for the source file generated. We will define this file to customize our class generation. We use HibernateCustomStrategy for our strategy. By default Hibernate tools provides with its own implementation.
4 Create a build.xml with the target. The class name mentions which class to be evoked when running this task. We will be using the predefined class HibernateToolTask which is present in the hibernate-tools.jar. Class path ref is the reference to the class path. For example
Create a path element. This element says that all the jar files in the lib directory will be part of this path.








We will refer this path element in the classpathref like below.






in ant task to generate the xml mapping files and uncomment to generate the DAOs.
11 To run this build.xml you can choose to use command line or through an IDE.
11.1 To run from the command line go to the directory of the build file. Use ant to run the build.xml. Note: You should have ANT_HOME set in your environment variable.
11.2 To run from Eclipse. Change the view to ant view. And double click on the targetname.
12 Check in the for the generated source.

A simple Test Framework with example

It’s a very common requirement to have a testing framework of its own for an application to provide a capability that’s common to all the unit classes. Say, if you are building test classes to test the Rest based webservices you would like to have a framework that provides the capability to provide the creation of request in the form of URLs. The response can be either xml or json and we can provide our own implementation to validate the response that’s come in, so that for each unit test of services we don’t have to write a code in each test class to validate the response. I am suggesting a simple framework that provides the backbone for such a framework implementation. It’s not specific to a particular architecture but can be modified to use it for any architecture that user wants.

I am suggesting a kind of driver class to run all the tests. The driver class will be responsible to provide specific behaviors to the whole test application. Suppose you want to add the facility of creating the url ,as described in the above example for the rest based webservice, of the resource. You need to add that method or operation in this driver class.

Coming on to Driver class.

Our driver class is that of TestCase. It has two abstract methods ;
protected abstract void executeTest() throws Exception;
protected abstract void checkActualResults() throws Exception;
which will be extended by every TestCase to have the specific behavior of the application. The other class will be that of AllTests which uses the junit test suites to run all the tests.

I am giving the code for the TestCase and AllTest below.

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


public abstract class TestCase {

private String testName = "";

protected Map testConditions = new HashMap();
private Map expectedResults = new HashMap();
private Map actualResults = new HashMap();

public TestCase() {
}


public boolean isTestPass() throws Exception {
System.out.println("Test Case: " + this.getTestName());

this.executeTest();
this.checkActualResults();
this.syncResults();

boolean isMatch = this.isResultsMatch();
System.out
.println((isMatch ? "PASS: " : "FAIL: ") + this.getTestName());
return isMatch;
}


protected abstract void executeTest() throws Exception;


protected abstract void checkActualResults() throws Exception;


private boolean isResultsMatch() {
Iterator i = expectedResults.entrySet().iterator();
Map.Entry result;
while (i.hasNext()) {
result = (Map.Entry) i.next();
if (this.getExpectedResult(result.getKey()) != this
.getActualResult(result.getKey()))
return false;
}
return true;
}


private void syncResults() {
int exp = expectedResults.size();
int act = actualResults.size();
if (exp == act)
return;
Map.Entry result;
if (exp > act) {
Iterator i = expectedResults.entrySet().iterator();
while (i.hasNext()) {
result = (Map.Entry) i.next();
if (!actualResults.containsKey(result.getKey())) {
actualResults.put(result.getKey(), false);
}
}
} else {
Iterator i = actualResults.entrySet().iterator();
while (i.hasNext()) {
result = (Map.Entry) i.next();
if (!expectedResults.containsKey(result.getKey())) {
expectedResults.put(result.getKey(), false);
}
}
}
}

// reset all test conditions, and test results
public void initialize() {
testConditions.clear();
expectedResults.clear();
actualResults.clear();
}


public void setAllConditions(Object value) {
this.setMapValue(this.testConditions, value);
}


public void setAllExpectedResults(boolean value) {
this.setMapValue(this.expectedResults, value);
}

private void setMapValue(Map m, Object value) {
Iterator i = m.entrySet().iterator();
Map.Entry entry;
while (i.hasNext()) {
entry = (Map.Entry) i.next();
m.put(entry.getKey(), value);
}
}


public void setTestCondition(String key, Object value) {
testConditions.put(key, value);
}

public Object getTestCondition(String key) {
return testConditions.get(key);
}

public void setExpectedResult(String key, Boolean value) {
expectedResults.put(key, value);
}

public Boolean getExpectedResult(String key) {
return expectedResults.get(key);
}

public void setActualResult(String key, Boolean value) {
actualResults.put(key, value);
}

public Boolean getActualResult(String key) {
return actualResults.get(key);
}

public String getTestName() {
return testName;
}

public void setTestName(String testName) {
this.testName = testName;
}

}

AllTest will look like


import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;


@RunWith(Suite.class)

@SuiteClasses({LoginServiceTest.class })

public class AllTests {
}

An example of using this:

We have LoginService like this

public class LoginService {

public boolean isValid(String username, String password) {

if (username.equals("kanishka") && password.equals("vatsa"))
return true;
return false;
}

}

We develop the TestCase like this :

public class LoginServiceTestCase extends TestCase {


private LoginService loginService = new LoginService();
protected final String CONDITION_USERNAME = "userName";
protected final String CONDITION_PASSWORD = "password";

protected final String RESULT_IS_ERROR = "isError";

private boolean isError;

protected void checkActualResults() throws Exception {
setActualResult(RESULT_IS_ERROR, isError);
}

protected void executeTest() throws Exception {
try {
String userName = (String) getTestCondition(CONDITION_USERNAME);
String password = (String) getTestCondition(CONDITION_PASSWORD);
isError = !loginService.isValid(userName, password);
} catch (Exception e) {
isError = true;
}
}

}

We write the junit test case like :

public class LoginServiceTest {


LoginServiceTestCase loginTestCase = new LoginServiceTestCase();

@Before
public void setup() {
System.out.println(" in setup");
loginTestCase.initialize();
}

@After
public void teardown() {
}

@Test
public void testLoginWithValidAccount() throws Exception {
loginTestCase.setTestName("Validate Login with valid credentials");
loginTestCase.setTestCondition(loginTestCase.CONDITION_USERNAME,
"kanishka");
loginTestCase.setTestCondition(loginTestCase.CONDITION_PASSWORD, "vatsa");
loginTestCase.setExpectedResult(loginTestCase.RESULT_IS_ERROR, false);
assertTrue(loginTestCase.isTestPass());
}

@Test
public void testLoginWithEmptyCredentials() throws Exception {
loginTestCase.setTestName("Validate Login with empty credentials");
loginTestCase.setTestCondition(loginTestCase.CONDITION_USERNAME, "");
loginTestCase.setTestCondition(loginTestCase.CONDITION_PASSWORD, "");
loginTestCase.setExpectedResult(loginTestCase.RESULT_IS_ERROR, true);
assertTrue(loginTestCase.isTestPass());
}

@Test
public void testLoginWithInvalidCredentials() throws Exception {
loginTestCase.setTestName("Validate Login with invalid credentials");
loginTestCase.setTestCondition(loginTestCase.CONDITION_USERNAME,
"user");
loginTestCase.setTestCondition(loginTestCase.CONDITION_PASSWORD,
"password");
loginTestCase.setExpectedResult(loginTestCase.RESULT_IS_ERROR, true);
assertTrue(loginTestCase.isTestPass());
}
}

In the loginServiceTest class we are encapsulating the LoginTestCase instance hence we are delegating the responsibility to provide the application specific behavior(in our example the restful behavior) to the TestCase instance which will provide the behavior.

Hope you will like this simple but useful implementation. Looking forward for your comments.

Happy coding :)

Sunday, January 1, 2012

How can you get data highlighted in a Enhanced Data grid : dojo

Say we have a requirement to highlight the data in enhanced datagrid of dojo according to some rules. For example suppose you are building a portfolio management service and you want to highlight all the shares in portfolio that has given negative returns. How can you do that in an enhanced datagrid of dojo. I had the similar requirement.
First of all why would you need an enhanced datagrid at all.
The enhanced datagrid of dojo comes with a lot of features which is not available to the simple table of html. Some of the important features include
1) Out of box support for the sorting of data in a column.
2) Drag and drop facility
3) The support to the various event handlers like onmouseover, onstyleshow etc which gives a lot of flexibilities to provide the data.



dojo.require("dojox.data.HtmlStore");
dojo.require("dojox.grid.EnhancedGrid");
dojo.require('dojo.parser');
dojo.ready(function(){
function isbnformatter(indexdata,row, cell){
var item = grid.getItem(row);
var type = store.getValue(item, "isbn", null);
if(type == 1 || type ==5){
cell.customStyles.push( "color:red;font-weight: bold;");
}
return type;
}

var layoutBooks = [[{
field: "isbn",
name: "ISBN",
width: 10,
formatter:isbnformatter
},
{
field: "author",
name: "Author",
width: 10

},
{
field: "title",
name: "Title",
width: 'auto'
}]];

var store = new dojox.data.HtmlStore({url:'mytable.html',dataId:'books2'});
var obj = {
id: 'grid',
store: store,
structure: layoutBooks,
rowSelector: '20px'};

var grid = new dojox.grid.EnhancedGrid(obj,document.createElement('div'));


/*append the new grid to the div*/
dojo.byId("gridDiv").appendChild(grid.domNode);

/*Call startup() to render the grid*/
grid.startup();
});

create a div with the name gridDiv to provide a placeholder for the grid.


For url:'mytable.html'you will have to create a html file which will give the data to that HTML store. dataId:'books2' is the id of the table that we have created for the data.