Wednesday 3 October 2012

Maven and eclipse part 2


Installing the maven eclipse plugin:

In my previous post i described how to use Maven to build an eclipse project to import. Now i will describe how to use the Maven Integration for Eclipse plugin to import a Maven project.

From the help menu select the Eclipse marketplace


Then search for the maven plugin


Then click the install button on the Maven Integration for Eclipse.

Then click next and finish the installation.

Once you have installed the maven Integration for Eclipse, we can import our maven projects.
Open the File menu then select the import option.


From the import menu, we want to import an Existing Maven project. This is located under the Maven folder.


Now browse to the root directory of your project. This is the folder with your parent maven pom file.

Now you can select finish. This will import your project as a Maven project using the Maven integration.

You can now build the project automatically using Maven from Eclipse.

One issue i ran into with Maven in combination with eclipse and wtp is that it wasn't deploying my other pom dependencies correctly so i had to disable "Resolve dependencies from Workspace projects" from the properties menu






Wednesday 29 August 2012

JUnit Tests



Unit Tests:

Unit tests give developers the ability to isolate and test individual sections of code to validate it against expected results. They are useful to verify code while development and when updated to ensure correctness.

In this blog we will be looking at JUit 4.X with maven. To include the JUnit test dependency in your POM  you need to include:

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>

This will allow you to include JUint with your project. To use JUnit tests you will need to import at least these basics:

import org.junit.Assert;
import org.junit.Test;

JUint uses annotations to define tests and methods used to setup and cleanup after tests. So you can annotate multiple methods with each of these to have many tests and multiple setup or clean up functions.


@Test
Defines the method to run for a test.
@Ignore
Ignores a test case
@Before
Executes the method before each test to setup any data or resources
@After
Executes the method after each tests to cleanup and data or resources
@BeforeClass
Executes the method once before all tests cases in this class. Can be used to setup systems that can be used for all tests to save time. This method must be static.
@AfterClass
Executes the method once after all tests cases in this class, to clean up any resources once the testing of this class is complete. This method must be static.

The @test annotation can have two optional parameters. the first being the type of exception that is expected. If the exception is not thrown, the test case will fail. 

        @Test(expected=NullPointerException.class)

the second option parameter is a timeout, the test will fail if it takes longer then the timeout.

        @Test(timeout=100)

First we will declare a simple class we want to test. This just has one function that returns the value 10.

public class ClassToTest {

       public int functionTotest() {
              return 10;
       }
}

Now we want to declare our test cases. First we need to create our class to hold our test case, There isn't anything specific needed to declare a class as holding test cases.

       package com.cred.industries.platform.test;
       public class MyTestCase {

We need to annotate our methods to define our unit tests. First we need to setup our tests cases, we can annotate a method with @Before to use it to setup our classes. This will execute this method once before all tests cases
      
       private ClassToTest clsToTest;
       @Before
       public void beforeTest() {
             
              clsToTest = new ClassToTest();
       }

To declare a test case we annotate a method with @Test
      
       @Test
       public void testCase1() {
             

We can use Assert.* to validate our data. If an assertion is failed it will fail the test case

              Assert.assertNotNull(clsToTest);
              Assert.assertTrue(clsToTest.functionToTest() == 10);
       }

To run our test cases we open the class with the test cases. Then in eclipse we select from the menu, Run -> Debug as -> JUint Test




This will also open the results tab that will give you a break down on the test case results.


 That is enough to setup most test cases, but for more documentation see http://www.junit.org/

Maven:

Maven will automatically run test cases as long as they are located in 

      src/test/java
      src/test/resources

to run tests with maven you just execute

         mvn test

Your test cases will run by default with maven builds. However, You may not always want to run test case because some can take a long time. You can disabled or skip tests using
mvn install -Dmaven.test.skip=true

Sunday 8 January 2012

Java 7's automatically closing files and resources with try catch

As part of Java 7's project coin Java introduces automatically closing files and resources. This allows us to greatly simplify the error prone boiler plate code in Java 6.

I won't go into the Java 6 way of handling resources since it has been blogged about many times,  but I will show you an example of what it looks like  below. As you can see you declare your resources, then in a try block use them. The try block has a finally that you need to close your resources in. But when closing the resources you need surround each in try-catch to make sure if you get an exception in one close it doesn't prevent the other ones from closing. As you can see there are a lot of steps to take, and a lot of places to go wrong.

Connection connect = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
             
String metricValuename = "test";
int metricId = 0;
try {
                    
       //if we don't find the value lets create one
       String sqlQuery = "INSERT INTO  metricsvaluename VALUES(?,?)";
       connect = DBConnectionManager.getInstance().getConnection();
       connect.setAutoCommit(false);
       preparedStatement = connect.prepareStatement(sqlQuery,
              Statement.RETURN_GENERATED_KEYS);
       preparedStatement.setInt(1, 0);
       preparedStatement.setString(2, metricValuename);
      
       int updated = preparedStatement.executeUpdate();
                    
       if(updated == 0) {
              throw new ApplicationException(
                ReturnCodes.UNKNOWN_ERROR.toString(),
                "no rows changed when creating new MetricValueId "
                 + metricValuename);
       }
                    
       resultSet = preparedStatement.getGeneratedKeys();
       if(resultSet.next()) {
              metricId = resultSet.getInt(1);
              DoSomethingWithId(metricId);
              connect.commit();
       } else {
              connect.rollback();
              throw new ApplicationException(
                ReturnCodes.UNKNOWN_ERROR.toString(),
                "no metricTypeId generated " + metricValuename);
       }
                    
} catch (SQLException e) {
                    
       try { connect.rollback(); }
       catch(Throwable ignore) { /* Propagate the original exception */ }
       e.printStackTrace();
} catch (IllegalArgumentException e) {
                    
       try { connect.rollback(); }
       catch(Throwable ignore) { /* Propagate the original exception */ }
       e.printStackTrace();
} finally {
                    
       try { if(resultSet != null) resultSet.close(); }
       catch (Throwable  ignore) { /* Propagate the original exception */ }
       try { if(preparedStatement != null) preparedStatement.close(); }
       catch (Throwable  ignore) { /* Propagate the original exception */ }
       try { if(connect != null) connect.close(); }
       catch(Throwable ignore) { /* Propagate the original exception */ }
}

Using Java 7 we are able to remove a lot of the boiler plate code, and thus remove a lot of potential errors. By declaring your resources inside of the try ( ... ) statement we allow the system to manage the lifetime of the resources and automatically close them once we leave the try block.

String metricValuename = "test";
int metricId = 0;
String sqlQuery = "INSERT INTO  metricsvaluename VALUES(?,?)";
try (Connection connect = DBConnectionManager.getInstance().getConnection();
       PreparedStatement preparedStatement = connect.prepareStatement(sqlQuery,
              Statement.RETURN_GENERATED_KEYS);){
                    
      
       connect.setAutoCommit(false);
             
       preparedStatement.setInt(1, 0);
       preparedStatement.setString(2, metricValuename);
             
       try {
              int updated = preparedStatement.executeUpdate();
                          
              if(updated == 0) {
                     throw new ApplicationException(
                       ReturnCodes.UNKNOWN_ERROR.toString(),
                       "no rows changed creating new MetricValueId " +
                       metricValuename);
              }
                          
              try (ResultSet resultSet =
                     preparedStatement.getGeneratedKeys()) {
                                 
                     if(resultSet.next()) {
                            metricId = resultSet.getInt(1);
                            connect.commit();
                     } else {
                            connect.rollback();
                            throw new ApplicationException(
                             ReturnCodes.UNKNOWN_ERROR.toString(),
                              "no metricTypeId generated "
                             + metricValuename);
                     }
              }
                          
       } catch (IllegalArgumentException | SQLException e) {
                    
              try { connect.rollback(); }
              catch(Throwable ignore) { /* Propagate the original exception */ }
              e.printStackTrace();
       }
                    
} catch (SQLException e) {
                    
       e.printStackTrace();
}

Since the automatic resource closing only deals with the closing of the resources we still need to worry about when to commit and rollback transactions for JDBC. Before we would roll back the transaction as part of the catch

                try {
              ... //open and use some resources
} catch (SQLException e) {
                    
       try { connect.rollback(); }
       catch(Throwable ignore) { /* Propagate the original exception */ }
       e.printStackTrace();
} finally {
              ... //close the resources
}

However with Java 7  this does not work because the resources is closed before we reach the catch statement. The code below gives me a compile error that connect cannot be resolved.

try (Connection connect = DBConnectionManager.getInstance().getConnection()) {

              ... // use some resources
} catch (SQLException e) {
                    
       try { connect.rollback(); }              //compiler error
       catch(Throwable ignore)    { /* Propagate the original exception */ }
       e.printStackTrace();
}

To overcome this, inside of the try we create the resources with, we use another try to catch any exceptions so we can rollback our changes. Then using Java 7's enhanced exception handling you can manage the exception how you like.

try (Connection connect = DBConnectionManager.getInstance().getConnection()) {

              ... // do some work you dont need to rollback

        try {
      
                     ... // do any work you need to rollback
                        connect.commit();

              } catch (IllegalArgumentException | SQLException e) {
                       
                try { connect.rollback(); }
                catch(Throwable ignore) { /* Propagate the original exception */ }
                e.printStackTrace();
        }
      
} catch (SQLException e) {
                    
       e.printStackTrace();
}

Also above you can see that we can catch many exceptions in the same catch using the syntax
        catch (IllegalArgumentException | SQLException e)

this allows us to use the same code for multiple exceptions without cheating and just catching
       catch (Exception e)