Friday, July 27, 2012

Java 7, one year later

Java 7, one year later

Java 7 got released on the 28'th of July 2011
The world wide launch party was on the 7'th of July at the JUG with Alexis Moussine-Pouchkine: http://2011.geecon.org/speakerdetails/12

I had the privilege of presenting at the Jozi JUG on the 29'th of August

JRebel claims the adoption is now at 23%
Jelastic claimed 18% in the same article.

Within Jelastic's cloud service: Java 7 is at a massive 73% vs Java 6 at 27%
graph
(Thanks Judah)

Here is the git location of the source code I demoed way back.

git clone https://bitbucket.org/rjdkolb/java7jozijug.git
 
Or on the web : https://bitbucket.org/rjdkolb/java7jozijug/src 


Wednesday, July 25, 2012

Improving the performance of a Vaadin OpenLayers Map

The problem 


I am using Vaadin with it's openlayers addon
I am showing a map with about 10000 points and lines between them.
Vaadin started getting very sluglish

The Solution

Kiren Pillay suggested that I use JProfiler
So that is what I did.
I finally saw what in Vaadin was taking all the time.
getApplication() on the Panel was being called more than 50,000 times
isEnabled() was also being called on the same panel about the same amount of time.

These calls were very fast, but because of the shear number of requests, it was slowing my application down to a crawl.

So with the combination of  JProfiler and JRebel I could apply these changes without a restart!


// Snip
  
   Application app;
   public MyPanel( Application app){
       this.app = app;
   }

   @Override
    public boolean isEnabled(){
        return true;
    }

   @Override
    public Application getApplication(){
        return app;
    } 
 

The end result ?

A dramatic improvement in handing in the browser!


Tuesday, July 24, 2012

Your Java IDE, friend or foe ?

Your Java IDE, friend or foe ?


The new Eclipse Juno is released.
And surprise surprise, it's slow, and caused a couple of sleepless night for a friend of mine.

My advice to any new or experienced Java developer, try NetBeans 7.2.

I know Elcipse has had some of these features for ages, but
1) are they stable ?
2) Do you fear updating your ide ?
3) Is emotional attachment the biggest factor in your choice ?

Here are two videos. Copyright to Netbeans.




Original Netbeans 7.2 Overview







Original Netbeans TestNG , conditional breakpoints video



Monday, July 23, 2012

Production grade REST services


Writing a REST service in Java is easy, writing a production grade one is almost as easy :)

A simple service

// JSR 311 REST service
@Path("myservice")
public class MyDataLoaderREST {

    @PUT
    @Consumes({"application/json"})
    public void loadFile(String csvdata) {
      CSVReader reader = new CSVReader(new StringReader(data));
      String nextLine = reader.readNext();
      Customer c = new Customer( nextLine[0],nextLine[1]);
      em.persist(c);
    }

}

The above service will work, but it is not really production grade in my opinion.

1) It does not return a positive or negative value
2) If something goes wrong like the csv is malformed, it will be next to impossible to debug.

The solution simple service

1) Always return a result, never return a HTTP error, the end user will never be able to figure out what is wrong.
2) If something obvious and something not obvious go wrong, return the line where the error happened.
3) Also don't treat all exceptions in the same way. Catch a FileNotFoundException and a IOException, you may want to handle differently.
4) Catch the RuntimeException as a final resort
5) Write using TDD!

The test!

// A simple JUnit test for testing the import

public class TestMyDataLoaderREST {

    @Test

    public void testImportCustomer() throws IOException {

        MyDataLoaderREST importFile = new MyDataLoaderREST();

        NodeCalculationLoadResult calcResult = importFile.loadFile("1,2");

        Assert.assertTrue(calcResult.isSuccess());

   }

    @Test

    public void testImportCustomerNull() throws IOException {

        MyDataLoaderREST importFile = new MyDataLoaderREST();

        NodeCalculationLoadResult calcResult = importFile.loadFile(null);

        Assert.assertFalse(calcResult.isSuccess());//make sure an exception was not thrown

        Assert.assertEquals(1,calcResult.getlineNumber());//make sure it's not line 0

   }

The service

// The JSR 311 improved service

import au.com.bytecode.opencsv.CSVReader;

@Path("myservice")

public class MyDataLoaderREST {

    @PUT

    @Consumes({"application/json"})

    public CustomerResult loadFile(String csvdata) {

        int lineNumber = 0;// line number outside try to catch can use it

        try {

         

          CSVReader reader = new CSVReader(new StringReader(data));

          if (nextLine.length < 2) {

                    return new CustomerResult(false, 1, "Error reading at line " + lineNumber + " line should have two or more values");

                }

           while ((nextLine = reader.readNext()) != null) {

           }
            return new CustomerResult(false, -1, lineNumber +" lines parsed and imported");

         } catch (ParseException ex) {

            return new CustomerResult(false, lineNumber, "Error parsing data at line " + lineNumber + " " + ex.getMessage());

        } catch (NumberFormatException ex) {

            return new CustomerResult(false, lineNumber, "Error reading number at line " + lineNumber + " " + ex.getMessage());

        } catch (RuntimeException ex) {

            return new CustomerResult(false, lineNumber, "Programmatic error reading number at line " + lineNumber + " " + ex.getMessage());

        }

    }

}


The domain Class @XmlRootElement
@Data // Project Lombok does all my getters and setters for me

// The domain object

@Data // Project Lombok does all my getters and setters for me

public CustomerResult {

     private boolean success;

     private int lineNumber;

     private String errorMessage;

     private Customer customer;

     public CustomerResult(boolean success , int lineNumber,String errorMessage){

       this.success = success;

       this.lineNumber = lineNumber;

       this.errorMessage = errorMessage;

      }

      public CustomerResult(Customer customer){

         this.customer = customer;

      }

      

}


Tuesday, July 3, 2012

What happened to POI

I had to read a XLSX file in POI today

Problem 1:
You can no longer use the old
HSSFWorkbook wb     = new HSSFWorkbook(fileInputStream); 
syntax
or you will get :

The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)

Problem 2:
So I tried to use the new API
Workbook workbook = WorkbookFactory.create(fileInputStream);

But where is org.apache.poi.ss.usermodel.WorkbookFactory ??

This is because you need another dependably now. Go figure.

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.8</version>
        </dependency>


Problem 3:

So as a 'good' Java dev, I started with unit testing, but I did not want to read a file in my JUnit test.
I came across this : http://stackoverflow.com/questions/2597271/easy-to-get-a-test-file-into-junit

My JUnit now looks like :

public class TestCalculator {

    @Rule
    public ResourceFile res = new ResourceFile("/Comparative.xlsx");// this file is in my test resources

    @Before
    public void before() throws IOException{
        Assert.assertNotNull( res.getFile());
    }
    @Test
    public void testParseXLSDoc(){
        Calculator c = new Calculator(res.file.getAbsolutePath());//the Java File
        c.parseActiveDocument();  
    }
}

//from stackoverflow
public class ResourceFile extends ExternalResource {

    String res;
    File file = null;
    InputStream stream;

    public ResourceFile(String res) {
        this.res = res;
    }

    public File getFile() throws IOException {
        if (file == null) {
            createFile();
        }
        return file;
    }

    public InputStream getInputStream() {
        return stream;
    }

    public InputStream createInputStream() {
        return getClass().getResourceAsStream(res);
    }

    public String getContent() throws IOException {
        return getContent("utf-8");
    }

    public String getContent(String charSet) throws IOException {
        InputStreamReader reader = new InputStreamReader(createInputStream(),
                Charset.forName(charSet));
        char[] tmp = new char[4096];
        StringBuilder b = new StringBuilder();
        try {
            while (true) {
                int len = reader.read(tmp);
                if (len < 0) {
                    break;
                }
                b.append(tmp, 0, len);
            }
            reader.close();
        } finally {
            reader.close();
        }
        return b.toString();
    }

    @Override
    protected void before() throws Throwable {
        super.before();
        stream = getClass().getResourceAsStream(res);
    }

    @Override
    protected void after() {
        try {
            if (stream != null) {
                stream.close();
            }
        } catch (IOException e) {
            // ignore
        }
        if (file != null) {
            file.delete();
        }
        super.after();
    }

    private void createFile() throws IOException {
        file = new File(".", res);
        InputStream stream = getClass().getResourceAsStream(res);
        try {
            file.createNewFile();
            FileOutputStream ostream = null;
            try {
                ostream = new FileOutputStream(file);
                byte[] buffer = new byte[4096];
                while (true) {
                    int len = stream.read(buffer);
                    if (len < 0) {
                        break;
                    }
                    ostream.write(buffer, 0, len);
                }
            } finally {
                if (ostream != null) {
                    ostream.close();
                }
            }
        } finally {
            stream.close();
        }
    }
}

Tuesday, August 9, 2011

A tale of two teams - Architectural prototyping


A tale of two teams - Herding the CATS (Developers)

1) Team 1, a typical team

For example three developers get a basic design for a website with 6 CRUDS and decide to use a new technology. Hibernate 3.6 , GWT etc
They each research the basic technology and start coding.

Each developer starts coding as they see it should be done, they hit problems and they each adjust their design.

At the end of the sprint they each show 3 CRUDS of about 90% quality, each with a slightly different implementation

In Sprint 2, each developer then start with their second assignments.
Each again develops another 3 CRUDS of about 91% quality, each with a slightly different implementation AGAIN.

What do you end up with ?

Six CRUDs in a new technology , all are coded differently, working differently and with less than 95% quality.
The code is a mess and needs a re-write.
Developers start blaming the GWT and Hibernate technology etc.

2) Team 2, Architectural prototyping

Again , for example three developers get a basic design for a website with 6 CRUDS and decide to use a new technology. Hibernate 3.6 , GWT etc
They each research the basic technology and start coding a throw away prototype implementing the same CRUD.
Before the sprint is complete, they all come together and discuss the problems they are having and discuss how they each solved the issue.
They then come together to create a 'perfect CRUD' template.
At sprint end, only one 'perfect CRUD' template is outputted.
Common code is defined in the template, so each developer can use the common code.

In Sprint 2 each developer code using the template
There will be problems faced, when the problems come up, the template is updated.
At the end of Sprint 2, another three CRUDS are outputted.




Tuesday, February 8, 2011

Using your private configuration in Maven

Getting Maven to use your own private setting defined in your settings.xml

In your build section in your settings.xml



my-dev-profile

true





0835405934
0835405934
0835405934
0835405934


...



In your build section in your pom.xml

....



src/test/resources
true





In your test resources

in your test resources or resources persistence.xml




org.eclipse.persistence.jpa.PersistenceProvider
za.co.xxxxx

true
NONE