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 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.

Wednesday, January 12, 2011

I'm back (again)

I had intentions of developing my blog back in 2006 and managed to write a few half decent articles. Well its now 2011 and I’ve decided to take up blogging again.

My career has shifted more towards Java and OO Development and I’m no longer working so closely with Application Express but maintain an active interest in the good work the folks at Oracle are doing. My primary interest for blogging is to stop me forgetting some of that important stuff you come across when coding, hopefully someone out there will find this stuff useful too.

I’m currently playing with GWT, JBoss, Groovy, Grails and all things open source with a little Oracle and Weblogic thrown in there for good measure so hopefully they’ll be more to come from me on those technologies.