Blog do projektu Open Source JavaHotel

poniedziałek, 2 maja 2011

GWT + DB2 + BIRT

Database application without reporting is like a sea without fish. Looks like a sea but something important is missing.
So I decided to add some reporting feature to my GwtSample application.

Refactoring

But firstly I realized  that it is necessary to release tight coupling with database schema (here Employee table) and to get rid of direct references to Employee class attributes (Employee.getEmpno(), Employee.getMidinit() etc).
So, in the share package, additional class (GetField.java) was created providing some general description of the table schema instead of direct column names and types.

public interface IRecord {
}

public class Employee imlements IRecord,Serializable {
}

public class GetField {

    public enum FieldType {
        INTEGER, DATE, STRING, NUMBER
    }

    /**
     * Field, column value (C union structure would be the best)
     * Only one attribute should be set
     * @author sbartkowski
     * 
     */
    public static class FieldValue {
        /** Timestamp. date column. */
        private final Timestamp dField;
        /** char, carchar2 column. */
        private final String sField;
        /** integer column. */
        private final int iField;
        /** decimal column. */
        private final BigDecimal nField;

    }

    /**
     * Description of one column in IRecord object
     * @author sbartkowski
     *
     */
    public static class FieldInfo {
        /** Column identifier. */
        private final String fId;
        /** Column type. */
        private final FieldType fType;
        /** Column description, title. */
        private final String fDescr;
        /** Column size to display (in pixels). */
        private final int cSize;
    }

    /**  
     * Get list of all columns
     * @return List of columns (FieldInfo)
     */
    public static List<fieldinfo> getfList() {
        return fList;
    }

     /**
     * Get column value from the record
     * @param field Column identifier (fId attribute in FieldInfo)
     * @param i IRecord, record, row
     * @return FieldValue class with proper attribut set according to column type
     */

    public static FieldValue getValue(String field, IRecord i) {
    } 

This set of classes and functions is enough to strip off from client (gwt) code any direct reference to Employee class. So it could be easily extended to the general purpose display client read for any sql statement.

Printing

As a reporting engine I decided to use BIRT. There is an easy path to utilize BIRT : via defining JDBC data source and run and display simply SQL statement (SELECT * FROM EMPLOYEE) and launch report by calling proper URL.
But I don't like this solution. Firstly for security reason : we have to provide the credentials for accessing database also to the BIRT engine just creating the next security access point. Also we have to duplicate some logic in the BIRT -  run the same SQL statement like in our main application.  It could be also complicated to implement all features : order by and the direction for the ordering.
So I chose the hard way : via XML data source. The general idea is as follows:
  1. The user clicks the Print button.
  2. Client sends back to the server all rows displayed on the screen in current order and direction.
  3. Server creates temporary XML file on the server containing all data and returns to the client the file name.
  4. Client launches BIRT report via URL providing in the URL the file name.
  5. BIRT run the report using the file name taken from URL as a XML data source.
Simple class for creating XML file (general purpose) - CreateXML.java
URL (host and port) used to launch BIRT report is defined as a resource variable in server.xml file, also the report design file name.

The advantage of this solution:
  1. More safe, the data access credentials used only at one point (application server).
  2. The table in the report is sorted in exactly the same way as visible on the screen. No additional logic is required in the BIRT engine.
The disadvantage:
  1. More complicated, more coding, more network traffic.
  2. Temporary files are left on the server, cleaning possible only after stopping the application server or machine restart.
  3. Application server and BIRT engine (resource thirsty) should be installed on the same machine.
But finally - it is working.
The source code for the application and BIRT project:
SampleGWT
SampleReports

1 komentarz:

  1. Great tip on using BIRT with GWT and DB2. Can you also submit a link to your article on BIRT Exchange devshare (http://www.birt-exchange.org/org/devshare/) so more BIRT developers can benefit from it?

    OdpowiedzUsuń