Disclaimer

The views and opinions expressed in this blog are my own and do not necessarily reflect those of my employer. The views and opinions expressed by visitors to this blog are theirs and do not necessarily reflect my own

Monday, January 23, 2012

Gnome 3 Rant (and fix for modal dialogs)

Back in the Gnome 2 days I used to love using Linux as my main developer machine but since Ubuntu and Gnome decided to build a mobile/cell phone interface for desktop PCs its gone back to the dark old days.

After Ubuntu switched to Unity I decided to jump ship to Linux Mint. Now Mint and most of the other big distros have gone Gnome 3, I'm left frustrated. These frustrations would be even worse if I'd chosen Fedora or SUSE as they don't offer the gnome shell extensions that make life bearable.

All the progress that was made with Gnome 2 and Compiz just seems to have been thrown away. The compiz-effects combined with Gnome 2 made for an awesome combination that rivalled anything I saw in Windows 7 or Mac OSX. They also kept me productive. Even Windows 8 will provide both a classic look and feel as well as there new Metro UI. With the exception of KDE based distros, Mint are the only distro that are trying to provide a choice to its consumers out of the box.

I don't know what has gone on with Nautilus but they have succeeded in making a newer version worse than the version that came before. However, that is a rant for another day. 

Fortunately what I really like about Mint is that they know who the target market for Linux is/was: developers, administrators and tinkerers. These are the type of people who need (and can deal with) a multi-tasking OS that can open more than one window at a time.

The new modal dialogs (a "feature" of gnome 3) have been really annoying me lately so I went on a hunt to find out how I could revert back to the traditional style of dialog. You know they type of dialog with a window bar that allows you to move it around the screen. Seriously everyone I know can deal with this concept. Let the developer choose the intent!

The solution is simple: gconf-editor to the rescue. Just open gconf-editor and untick /desktop/gnome/shell/windows/attach_modal_dialogs. Press Alt + F2, type r and press Enter (reloads gnome shell). Now you have the normal behavior back.

Tuesday, June 21, 2011

GWT : DisclosurePanel Images, IE6 and SSL

I recently worked on a project where we were using standard GWT Disclosure Panels and Tree components. When the application was sitting behind SSL we found that the arrow images were not visible in IE6. What was more frustrating was that in every other browser the images displayed correctly.

After a lot (and I mean a lot) of time I stumbled across the API documentation for image bundles which is the mechanism/technique Google have used to package up images for widgets into a composite image that help reduce calls to the server and speed up the user experience.
In summary, the problem is that GWT makes use an activeX control to process png transparency on IE6. Internet Explorer specifies that files which require the plugin for viewing must be cached to disk by the browser. By default the HTTP headers set by the GWT servlets when the image is requested specify that the payload should not be cached. The image then never stored to disk (cached) and the activeX control cannot process the image and display it to the page.

The solution is actually quite simple. You need to create an additional servlet that executes when image resources are requested. This is done by setting up a servlet in the web.xml with a file filter.

package xxxx.xxxxx.xxxxx;

public class ImageServlet extends HttpServlet {

 private boolean isIE6(final HttpServletRequest request){
  final String userAgent = ((HttpServletRequest) request).getHeader("User-Agent");
  return userAgent.contains("MSIE 6");
 }

 protected doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {

  if (isIE6(request) ){
   response.setHeader("Cache-Control", "");
   response.setHeader("Pragma", "" );

   // This should be some date in the future. Dynamically create the
   // date part of the string to be something in the future e.g.
   // sysdate + 1
   response.setHeader("Expires","Thu, 1 Jan 2013 00:00:00 ");
  }

  final String uri = request.getRequestURI();

  // Extract the icon name
  final String iconName = uri.substring(request.getContextPath().length(), uri.length() );

  // Supply the icon back to the browser
  continueProcessing(request, response, iconName);
 }

 protected void continueProcessing(final HttpServletRequest request
    , final HttpServletResponse response
    , final String iconName){

  final ServletContext context = getServletContext();
  final InputStream is  = context.getResourceAsStream(iconName);
  final OutputStream os = response.getOutputStream();
  response.setContentType("image/png");

  byte[] = new byte[8912];

  while (true){
   final int l = is.read(b);
   if (l < 0)
    break;
   os.write(b,0,l);
  }
 }
}
The servlet itself should look something like that below :

 ImageServlet
 xxxx.xxxxx.xxxxxx.ImageServlet


 ImageServlet
 *.png


You then need to set up the servlet mapping in your web.xml so that all png requests get routed through this new servlet. The example could be improved by adding caching of images requested. This would also speed up load performance of your application for images that are requested more than once.

Saturday, June 04, 2011

JBOSS, GWT and Request Factory : Unknown Entity Exception

I've been playing around with RequestFactory, GWT's data centric transport/serialization mechanism and was really struggling to set up a new project that could pull data from an existing set of database tables and I wanted to share my experiences if you decide to use an existing schema.

The tutorial can be found over on the GWT developer documentation and I don't want repeat what can be found there.

I decided to use an Oracle XE database and the world famous HR sample database, creating JPA entities for the EMPLOYEES and DEPARTMENTS tables.

JPA/Hibernate benefits from having a version column that is updated each time the object is persisted. RequestFactory uses this to determine whether changes have happened on the entity.

The first problem I encountered was that I kept seeing "Unknown Entity Exception" in the server logs (JBoss-6.0.0-Final). This was eventually solved by ensuring that the employees table had a "VERSION" column of type NUMBER(38). The annotated JPA class also requires the type to be of type Integer (Use the boxed/wrapper type and not int).

Initially I tried using Long for the "VERSION" column however that produces more errors in the logs and it was quickly evident this needs to be set to an Integer to be compatible with the @Version annotation.

Below is my entity definition that maps to the employees table.

@Entity
@Table(name = "EMPLOYEES", schema = "HR")
public class Employees implements Serializable {

 private static final long serialVersionUID = 1717056757381711656L;
 private static final Logger logger = Logger.getLogger(Employees.class);

 @Id
 @Column(name = "EMPLOYEE_ID")
 @NotNull
 private Long id;

 @Column(name = "VERSION")
 @Version
 private Integer version;

 @Column(name = "FIRST_NAME")
 private String firstName;

 @Column(name = "LAST_NAME")
 private String lastName;

 public Long getId() { return id; }

 public void setId(Long id) { this.id = id; }
 
 public Integer getVersion() { return version; }

 public void setVersion(Integer version) {this.version = version; }
.....
}

Finally you'll need to ensure that all rows in your schema are initialized with a default version. A simple update statement solves this:

update EMPLOYEE set version = 0;

While trying to solve this problem google searches led me down the garden path suggesting that one checks the JPA annotated class imports javax.persistence.Entity and not org.hibernate.persistence.Entity. Other searches suggested it was a incorrect configuration when using non-container based persistence. This was also not the problem as I was using a JTA datasource. The configuration for which is below.


  
    hrDS
    jdbc:oracle:thin:@localhost:1521:xe
    oracle.jdbc.driver.OracleDriver
    HR
    password
    org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter
      
         Oracle9i
      
  


My persistence.xml file was as follows:


    
        org.hibernate.ejb.HibernatePersistence
        java:hrDS
        
            
            
            
               
        
    
 

Again hope that helps someone else out there.

Monday, January 24, 2011

Accessing BLOBs and Servlets, Serving Images Stored in H2

In a previous post I looked at how to store images in a H2 database using groovy. The example served as nothing more than a little bit of fun. I just wondered how you'd go about doing it and wanted to explore how to get this done in groovy and H2, so wrote a script to load some images into the database.

After this I thought well how can we make use of these from a web application. In this post I'll take a look at how to serve up images through a servlet so that we can display them in a web page. I was more interested in the perceived speed of such a technique over storing the file on the file system and I must say it actually didn't feel that slow.

The code is as follows:
public class GetImage extends HttpServlet {

 private static final long serialVersionUID = -3505939293849012116L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response) 
       throws ServletException, IOException {

  String beerId = com.google.common.base.Preconditions.checkNotNull(request.getParameter("id"));

  InitialContext ctx;
  DataSource ds = null;
  Connection connection = null;
  PreparedStatement stmt = null;

  try {
   ctx = new InitialContext();
   ds = (DataSource) ctx.lookup("java:/beerDS");
   connection = ds.getConnection();

   String sql = "select image1, image1_content_type " +
     "from beer where id = ? and rownum() = 1";

   stmt = connection.prepareStatement(sql);

   stmt.setInt(1, Integer.valueOf(beerId));
   stmt.execute();

   ResultSet rs = stmt.getResultSet();

   while (rs.next()) {
    byte[] bytes = rs.getBytes("image1");
    String contentType = rs.getString("image1_content_type");
    int length = bytes.length;
    response.setContentType(contentType);
    response.setContentLength(length);
    response.getOutputStream().write(bytes);
   }
   response.getOutputStream().flush();
   response.getOutputStream().close();

  } catch (NamingException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  } catch (NullPointerException npe) {
   return;
  } finally {

   if (connection != null)
    try {
     connection.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
   if (stmt != null)
    try {
     stmt.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
  }
 }
}


A few things to note include:

  • You can't write multiple images to the response, not if you wan't something that can be understood by a browser. You refer to the servlet like any other file when using the url html or dynamic content. To access the image in a html page you would use a standard img tag as follows, like in the following example :
  • 
    
  • For the link to work, you'll need an entry in your web.xml (or Guice server module configuration - which is a really kool way to get rid of web.xml entirely) that ensures theres a mapping between "/my/*" url pattern and the GetImage servlet.
  • The underlying example uses my beer database configured as a data source as described in a this post
  • You'll need to ensure there is a blob in the database for the beer with ID 22 in the beer table. See my groovy script example that looks at how to get images into the database.

Sunday, January 23, 2011

Configuring a H2 Data Source in JBOSS 6

In this post I'll look at setting up a data source for JBOSS so that you can use a JNDI lookup to connect to your database from your web application. It's really easy and takes no time at all. JBOSS includes some example datasource configurations under JBOSS_HOME/docs/examples/jca that you can copy and edit for your own purposes.

I copied the hsqldb-ds.xml to my server profile under JBOSS_HOME/server/all/deploy and edited it as follows :



   
      beerDS
      jdbc:h2:tcp://localhost/~/BEER

      org.h2.jdbcx.JdbcDataSource
      sa
      

      
      5
      20

      0
      32

   


H2 is compatible with the HSQLDB drivers but they recommend using the H2 driver so thats the first thing I changed.
org.h2.jdbcx.JdbcDataSource
I then changed the connection url and specified my database, “BEER” in this case.
jdbc:h2:tcp://localhost/~/BEER
The configuration shown also sets up a connection pool which should help optimise performance.

Before you can use H2 from within your web application you need to make sure the H2*.jar is on the classpath. I copied my h2*.jar to JBOSS_HOME/common/lib.

Ensure your database is started and use the following code to get a handle to a connection you can then work with in your servlet code:
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/beerDS");
Connection connection = ds.getConnection();

You can then use the connection to query the database using sql or use JPA persistence and the JDNI name java:/beerDS.

These examples use my Beer database I set up in the previous post. This script will allow you to get a H2 sample database up and running. See my previous post for more details

BLOBS with Groovy and H2 [or your database of choice – Oracle, MySQL]

I am slowly building a couple of environments and set of applications that will allow me to explore techniques, design patterns (as-well as re-learn those forgotten ones) and test drive shiny new technologies like GWT and Grails. More of a reference set for myself than anything else.

As part of this I've needed to set up a database and application server. I decided on H2 as I feel it might be useful for some other pet projects I have in mind. I grabbed a free dataset from www.freebase.com who provide open source data-sets. I massaged the structure and normalised it into a couple of tables and added the appropriate primary keys. I chose a dataset that most people could relate to, beer.

Just for fun I thought I would try storing logo's against a given beer inside the database to keep everything self contained and to see how H2 performed.

Having dipped in and out of groovy and taking time to learn the rudimentary basics I haven't found much of an opportunity to use it and it seemed a nice fit for
this as I can imagine it is something you might want to script.

The code is as follows :
import groovy.sql.Sql

println "---- A working test of writing a blob into a H2 DB ----";

sql = Sql.newInstance("jdbc:h2:tcp://localhost/~/BEER;MAX_LENGTH_INPLACE_LOB=4096;COMPRESS_LOB=LZF ", "sa","", "org.h2.Driver" );

try {
 File f = new File("/tmp/stella.jpg");
 InputStream fis = new FileInputStream(f);

 def image_type = "image/jpeg";
 def updateStatement = "update beer set image1 = ? , image1_content_type = ? where id = ? ";
 def ps = sql.connection.prepareStatement(updateStatement);
 
// Set the BLOB with the FileInputStream
 ps.setBinaryStream(1, fis, (int)f.length());
 ps.setObject(2, image_type);
 ps.setObject(3, "22")  // Pilsner - 926, Stella - 22
 ps.execute()

 sql.commit()
} catch (Exception e) {
 println "Failed: $e"
 sql.rollback()
} finally {
 sql.connection.close()
}
println("finished");


The uploaded file has some extra comments explaining whats happening but there is a few things to note:
  • You can swap the jdbc url and h2 driver for those of your own database
  • You need to ensure the jdbc url is correct
  • The jdbc drivers must be on the class path
  • The jdbc url here specifies the H2 optimisations for working with LOBs
  • It is a good idea to store the mime-type in case we decide to serve this up over the web later.
  • You'll need a copy of my database for this to work beer db

The sql script was a direct export of my database so you should just be able to run it from the standard web interface that comes with H2 when you start it. You can start H2 by double clicking on the H2*.jar if you have jars associated with the Java 6 runtime.

To run it should be as simple as :

$ groovy -cp "/path/to/h2-XXXXX.jar" write-blob.groovy

Files

Saturday, January 22, 2011

Java Databases

I've been playing around with some database engines based purely on Java recently (H2, HSQLDB and Apache Derby) and I've been pleasantly surprised. The one I'd like to concentrate on here is H2.

It lists an impressive set of features especially compared to other databases. There is also a more detailed comparison on the H2 website

However what I most like is its size. The whole distribution is less than 1.2 MB and that includes a reasonably sophisticated web front end for running queries and inspecting the databases. Its also seems incredibly fast (considering its written in Java) and especially so when compared to Derby though I only have anecdotal evidence for this from my experience building a couple of sample projects.

If you haven't tried it already, I really recommend giving it a go as its incredibly easy to get applications up and running with especially in Java.

Thursday, January 13, 2011

GWT and JRE managed persistence (JPA) with Apache Derby

A while back I was playing with JPA/EJB3 persistence and GWT (Google Web Toolkit) but didn't want to use a heavy weight Application Server . The idea behind the application I was looking at was that it should be distributable and always run locally.

I downloaded the hibernate and JPA annotations from the hibernate website and thought it would be a simple case of configuring the persistence.xml file. After a some difficulties getting my application to hit the test Derby database I turned to google and it seems others had problems too.

I was expecting to have to create the persistence.xml file under “war/META-INF/” in my eclipse project. This is just wrong, it seems the persistence.xml file has to be on the classpath when your not using container based persistence.

The next problem I encountered was that I'd not included all the necessary jars from the hibernate distribution. The following combination seemed to work for me in the end.

WEB-INF/lib/

  • hibernate3.jar
  • hibernate-jpa-2.0-api.1.0.0.Final.jar
  • javassist-3.12.0.GA.jar
  • jta-1.1.jar
  • slf3j-api-1.6.1.jar

My persistence.xml was as follows:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
  <persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
   <provider>org.hibernate.ejb.HibernatePersistence</provider>  
  <properties>  
   <property name="hibernate.archive.autodetection" value="class" />  
   <property name="hibernate.format_sql" value="true" />  
   <property name="hibernate.show_sql" value="true" />  
   <!-- <property name="hibernate.hbm2ddl.auto" value="create-drop" />-->  
   <property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/slicr;" />  
   <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />  
   <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />  
   <!-- <property name="hibernate.connection.username" value="user" />  
   <property name="hibernate.connection.password" value="password" /> -->  
  </properties>    
  </persistence-unit>
</persistence>


I was only knocking up a quick and dirty application as a learning exercise but spent a good couple of hours just trying to hit the database. Hopefully this will help others in the same situation.