Monday, April 15, 2013

Derived properties in Hibernate

It's not a question you get asked on the bus on your way to work. But on that fateful day when you do, your answer is likely to be followed by a scratch of the head. How would you represent derived properties in Hibernate.Derived properties are calculated at fetch time, usually read-only, well they are read only period, but how they are represented in Hibernate, not everyone knows, understandably so too. 

I vaguely recall learning about derived properties back in one of the SQL sessions, but nothing much afterwards really.So why this write up, well a question about derived properties popped up in one of the interviews I had recently. I mess around with Hibernate a lot, I am not a guru but I know my way around it, but I can't say I have come across a scenario that mandated the usage of derived properties so my answer was, let's just say, not satisfactory.

Well, enough about that. Let's see how it's done then. You got two options; option number one ; use the formula attribute of the property element in your hibernate mapping file (for those who prefer xml configuration over annotations), options number two; use the @Formula annotation. 

I' ll just jump straight to code and show you how it's done.

First the xml approach,
<property name="fullName" formula="CONCAT(fName,' ',lName)" />
  <property name="idMul" formula="id * 12.0" />
 
And now how to do it with annotations,
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Formula;

@Entity
@Table(name = "person")
public class Person {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String fName;
 private String lName;
 private Date dob;
 
 @Formula("id * 12.0")
 private float idMul;
 
 @Formula("CONCAT(fName,' ',lName)")
 private String fullName;

And you can now write your queries based around your derived properties in the following fashion 
List<Person> person2 = (List<Person>) session.createQuery("from Person p where p.idMul > 5 and p.id=2").list();

And if you inspect your console you will see the following output,
Hibernate: 
    select
        person0_.id as id0_,
        person0_.dob as dob0_,
        person0_.fName as fName0_,
        person0_.lName as lName0_,
        CONCAT(person0_.fName,
        ' ',
        person0_.lName) as formula0_,
        person0_.id * 12.0 as formula1_ 
    from
        person person0_ 
    where
        person0_.id * 12.0>5 
        and person0_.id=2

Now before you close this window and down vote this post, I have to tell you I did this seemingly odd multiplication operation with the 'id' field to demonstrate what can be achieved within a formula annotation. 

Although its not clear from the code above, you need to understand that whatever you put inside  this annotation or the  formula attribute, does not undergo any form of translation, if you are wondering what the heck I am on about, It means Hibernate regards this as plain SQL. Questions ; Yes you can put a whole plain SQL query there also yes this violates Hibernate's database independence since you can put vendor specific SQL there, and yes you have to use actual table column names instead of entity field names. But imagine the possibilities, used correctly this could be a very powerful feature also and this is from my personal experience, you hardly switch database vendors, I am not trying to justify using vendor specific SQL but you catch my drift.

Now everywhere you use this derived property in your HQL, Hibernate replaces it with what you have defined. Now imagine  using a whole plain SQL query there to do some serious calculations (possibly time intensive) and using the derive property in your HQL query, Hibernate would blindly replace the derived property with your SQL. Say for example you want to execute the following query.
List<Person> person2 = (List<Person>) session.createQuery("from Person p where (p.idMul > 5 or p.fullName like '%chi%' ) and p.id=2").list();

And if you take a moment to inspect your console you will see the following query being generated.
Hibernate: 
    select
        person0_.id as id0_,
        person0_.dob as dob0_,
        person0_.fName as fName0_,
        person0_.lName as lName0_,
        CONCAT(person0_.fName,
        ' ',
        person0_.lName) as formula0_,
        person0_.id * 12.0 as formula1_ 
    from
        person person0_ 
    where
        (
            person0_.id * 12.0>5 
            or CONCAT(person0_.fName,' ',person0_.lName) like '%chi%'
        ) 
        and person0_.id=2

So you have to be careful about using derived properties in Hibernate.

Another point to note is that @Formula annotation is not a JSR annotation, so if you don't want to mix hibernate annotation with persistence annotations and want a cleaner and an optimized solution for using derived properties in Hibernate then you have no other choice but to do what this guy has done here. It's a pretty good post covering most aspects you are likely to be concerned about when using derived properties.



Thursday, March 14, 2013

Custom Class Loaders

Custom class loaders are a pretty interesting subject area.
Now why would anyone want to write their own custom class loader, the question is why not. It's always better to write your own class loader to load the classes your applications use, this way you can make sure that when your applications are un-deployed the classes you loaded will be eligible for garbage collection and the world would be a better place. Also it's just darn good practice, you can avoid the notorious class loader exceptions and linkage exceptions and most of all out of memory exceptions. Unlike some languages Java manages it's own memory, as a developer you just have to make sure you do your part by disposing objects you no longer need.

But you often take this for granted sometimes because you are just too darn lazy and sometimes because you just don't get it. Well you should, if you haven't already, read about java class loaders and how they load classes.

Let's see what sort of situations demand custom class loaders.


1. To allow class loading from alternative repositories
This is the most common scenario, you can load classes from networks, different directories, over ftp etc

2. To partition code
Used mostly in Servlet engines, you can have class loaders load multiple instances of the same application in the same JVM without any issues

3.To allow unloading of classes
Class loaders maintain a cache of the classes they load you can de-reference
the class loader to unload all the classes that it loaded. This is quite handy, you can unload your classes when you are done. This way you can avoid perm gen errors.

4. To change the way bytecode is loaded
For example you can load encrypted byte-code over the wire

5. To modify the loaded byte-code
used with AOP mostly

6. Automatically verify a digital signature before executing un-trusted code

7. Transparently decrypt code with a use supplied password
    Related to point 4 above

8. To support hot deployment on an application server

9. Use different versions of the same class on the fly to do something

The possibilities are endless. Let's see when class loaders become a huge issue,


1. Say, a Developer accidently loads two different versions of the same class, there is no guarantee which version of the class will be invoked, and the funny thing is the JVM won't complain

2. An application may consist of several class loaders, they might be unrelated, you get this a lot in application servers/ web servers. Dependent libraries may require different versions of the same class, in which case you might get linkage errors and class loaders version issues.

Let's now see how you can write your own. Remember when writing your own class loader its always better to link to a super class loader. If your class loader cannot load the class the chances are that your super class loader can, and mostly because it's just good practice.


import java.io.FileInputStream;
import java.util.Hashtable;

public class customclassloader extends ClassLoader {
 private Hashtable<String, Class<?>> classes = new Hashtable<String, Class<?>>();

 public customclassloader() {
  // chaining is important here
  super(customclassloader.class.getClassLoader());
 }

 private byte getClassFromExternalLocation(String className)[] {
  System.out.println("Fetching class " + className
    + "from sampledirectory\\");
  byte result[];
  try {
   FileInputStream fileInputStream = new FileInputStream(
     "sampledirectory\\" + className + ".ext");
   result = new byte[fileInputStream.available()];
   fileInputStream.read(result);
   return result;
  } catch (Exception e) {
   System.out.println("Unable to load class " + className);
   return null;
  }
 }

 // Main function called by client to resolve class
 public synchronized Class<?> loadClass(String className, boolean resolveIt)
   throws ClassNotFoundException {
  System.out.println("Attempting to load class " + className);
  Class<?> result;
  byte classData[];

  /* Check our local cache for the class */
  result = (Class<?>) classes.get(className);
  if (result != null) {
   System.out.println("Returning a cached instance");
   return result;
  }

  /* Call super class loader */
  try {
   result = super.findSystemClass(className);
   System.out.println("Calling the super class loader");
   return result;
  } catch (ClassNotFoundException e) {
   System.out.println("Not a class parent classloader can load");
  }

  /* Try to load it from our repository */
  classData = getClassFromExternalLocation(className);
  if (classData == null) {
   throw new ClassNotFoundException();
  }

  /* Define the class */
  result = defineClass(className, classData, 0, classData.length);
  if (result == null) {
   System.out.println("Format Error");
   throw new ClassFormatError();
  }
  /* load reference classes as well if required */
  if (resolveIt) {
   resolveClass(result);
  }
  /* Store the loaded class in the cache */
  classes.put(className, result);
  return result;
 }
}

Notice how method "getClassFromExternalLocation" loads the class from a different directory. You can read more about class loaders in one of my previous posts here.

Java Classloaders



If someone asks you what class loaders are, you would probably say with a smile on your face, well!! they load classes in to JVM. And you would probably go on to explain what the perm gen space is and how it would run out if you got too many classes hogging it. It's not serious business, you might think, the chances are that you have gone through all your life not intefering with them. Its like that weird kid in the class, you don't mess with. He does his business you do yours, but sooner or later you gonna have to talk to him. Well class loaders are like that.

How many times have you hot deployed a web application and gotten the dreaded out of memory error, and how many times have you cursed before restarting to get it working again. Well the problem I am afraid does not lie in the application server (obviously), its how you have written your code. Do you ever look to see what the problem really is, well most people choose not to.

Now before we go any further let's see what class loaders do.

Class loaders do a pretty important job, when you compile your application you turn your java code into bytecode and save it in .class files, you go a step further and bind your .class files in to a jar. That's all good. Now when you want to use the classes in this jar file, you invariably add it to the class path of the application in question. And viola, you can use those classes in your application now. What happens here is not magic. Your .class files are, behind the scenes being loaded on to the JVM by classloaders.

Let’s see when classes are being loaded in to JVM.

Classes are loaded when you create instances of them, or when you make a static reference using a dot notation, loading classes is done on demand. Curious minds would inquire now how the references classes are loaded, well they are loaded along with your main class, but what about when you have multiple classes declaring instances of the same class, well class loaders keep caches of the classes they load hence if the class you require is already loaded they won’t load it again there's a catch here though. This brings us to an interesting revelation, how does the situation change when you have multiple class loaders. Multiple unrelated (isolated) class loaders can load the same class so that it’s possible for multiple instances of the same class to exist in the JVM and the funny thing is they will never be equal.

You might ask, what of that singleton class I wrote last week, I was so proud of, well what of it, your singletonness is guaranteed only to the class loader that loads it. How to protect your singleton from being loaded twice in to JVM by multiple class loaders is a question that begs a separate blog post. In short you basically need to write your own class loader or make sure you always chain your custom class loaders so that they always have a common parent.

Let’s now move on to types of class loaders in Java of which there are mainly three.
  1.            Bootstrap Class Loader
  2.            Extensions Class Loader
  3.            System Class Loader
Bootstrap class loader loads Java Core classes typically present in jre/lib folder, while extensions class loader as you may have guessed already load Java extensions typically present in jre/lib/ext you can also define your ext locations by setting the system property “java.ext.dir”. Systems class loader loads classes from the class path defined, you can also define this using “java.class.path” System variable.

And of course you can write your own custom class loaders, do this if you are pretty finicky, well most Java geeks like to be very hands-on. What you also need to understand is that these class loaders are executed in the order listed, first the bootstrap, then extensions and finally system which is implemented by sun.misc.Launcher$AppClassLoader.

 When Java code is compiled by the compiler, the complier adds a static final field called “class”, every class has it. And why I brought this seemingly irrelevant subject here is because using this property you can get the class loader which loaded the class, this is pretty handy. You can try this out with a class you wrote, the interesting this to note here that you can go up the hierarchy to access the parent class loaders, when you get null, is when you know you have hit the bootstrap class loader, because bootstrap class loader always returns null.

Before I wrap this post up, let me list the steps a class loader has to go through before loading a class in to JVM, important if you are writing your own

1.     Verify Class Name


Important if you write your own class loader, you don’t want people to use your class loader to load classes you didn’t intent to.

2.     Check to see if it has been loaded already


If the class is loaded, which it tracks by using a map of some sort, return the class already loaded

3.     Check to see if the class is a systems class


If it is then the chances are that it’s already loaded, don’t take chances through, pass control to your parent class loader.

4.     Attempt to fetch the class from the class loader repository


This is where the actual loading happens, your repository may reside over a network, or a separate folder, load your classes as a byte stream.

5.     Define the class for the JVM


First step is to verify that the byte code is valid, if not throw a class format error

6.     Resolve the class


 What this means is that you need to load the references (any classes that the class you are trying load is using) you also need to verify the legitimacy of these references, failing this step is what leads to the infamous Linkage Errors

7.     Return the class to the caller


Finally return your class to the caller. Ill show you in another post how to write your own class loader.

And that’s a wrap.


Saturday, January 5, 2013

Hibernate Many to Many with Additional Columns

So we had a slight hiccup in our plans to dynamically place products according to their location points on a screen. We had to associate each view with a set of products and each product, a location, easy. But here's the fun part, products could be part of many views and views could be part of many products. This meant we had to accompany location data along with each product that belongs to a view. Which boils down to adding additional columns to a M-M association.

I did, I guess what anyone would do in a situation quite like this, break the problem down in to manageable parts.  First map the association to an entity class, use a composite primary key for the new entity (you don't have to do this, you can go about it the usual way i.e having two individual entities), add the additional columns to the new entity and finally decorate the classes involved with annotations. 

Ok let's get down to business then. Here are my two entity classes, 
@Entity()
@Table(name = "assortment")
public class Assortment {
 private Long id;
 private String imgURL;
 private Set<AssortmentProduct> products = new HashSet<AssortmentProduct>(0);
       @OneToMany(fetch = FetchType.LAZY, mappedBy = "assortmentProductId.assortment", cascade = {
   CascadeType.PERSIST, CascadeType.MERGE }, orphanRemoval = true)
 @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE })
 public Set<AssortmentProduct> getProducts() {
  return products;
 }
 // Other Fields, accessors and mutators

And as for the Product entity,
@Entity
@Table(name = "product")
public class Product implements java.io.Serializable {
 private static final long serialVersionUID = 1L;
 private int id;
 private Set<AssortmentProduct> assortmentProducts = new HashSet<AssortmentProduct>(
   0);
@OneToMany(fetch=FetchType.LAZY,mappedBy="assortmentProductId.product")
 public Set<AssortmentProduct> getAssortmentProducts() {
  return assortmentProducts;
 }
 // Other Fields, accessors and mutators


Here is my composite primary key class,
@Embeddable
public class AssortmentProductId implements Serializable {
 private static final long serialVersionUID = -3712895453750701217L;
 private Assortment assortment;
 private Product product;
        /**
  * other stuff 
  */

Make sure you override the equals and hashcode methods of your composite primary key class as its important to do so.
And now the association entity,

import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "assortment_product")
@AssociationOverrides({
  @AssociationOverride(name = "assortmentProductId.product", joinColumns = { @JoinColumn(name = "product_id") }),
  @AssociationOverride(name = "assortmentProductId.assortment", joinColumns = { @JoinColumn(name = "assortment_id") }) })
public class AssortmentProduct {

 private AssortmentProductId assortmentProductId = new AssortmentProductId();
 private PlaceHolder placeHolder;

 @EmbeddedId
 public AssortmentProductId getAssortmentProductId() {
  return assortmentProductId;
 }

 public void setAssortmentProductId(AssortmentProductId assortmentProductId) {
  this.assortmentProductId = assortmentProductId;
 }

 @Transient
 public Assortment getAssortment() {
  return assortmentProductId.getAssortment();
 }

 @Transient
 public Product getProduct() {
  return assortmentProductId.getProduct();
 }

 @OneToOne
 public PlaceHolder getPlaceHolder() {
  return placeHolder;
 }
}
And that's it. 

Friday, January 4, 2013

Using DB4o

db4o is an excellent Database Management System, it's a fresh breath of air to us relational database users. For years we have been battling with Object/Relational impedance mismatches. And I am not about revive an age old debate here, but I have been giving this some serious thought ever since our last client rejected using a really popular ORM outright(sadly I think you know what it is), in his words "it's too slow". A little part of me died that day. His solution, a home grown framework, a quite amazing one at that. Maintainability was a little price to pay for much sought after performance gains, it wasn't too difficult too once you get the hang of it.

I digressed a little, apologies, anyways getting back to db4o. What I love about it is it's simplicity. Ok lets talk basic necessities, what do you need to get this baby up and running, a cuppa coffee or a can of redbull, you sit right down after a sip, get your data model pinned down. And that's it. Yeah that really is it. There's no more complex mappings, annotations or configurations. It really is that simple.

Lets talk querying, db4o offers three types of querying techniques, There's Query By Example(QBE), Native Queries(NQ) and SODA Query API. For a newbie QBE offers the perfect solution, its pretty much the same as Hibernate, apart from a few trivial differences you can totally wrap your head around. Native queries are even easier, they offer type safety, compile-time checks and refactorability, how cool is that. SODA Query API is db4o's low level querying API,it's pretty verbose for my liking. 

db4o is perfect for freely distributed applications under proper licences, although stepping off this boundary would cost you. How much you ask, well it depends. Is it worth it, well it depends too, but that's a topic best left for another post, if the suspense is killing you, http://www.db4o.com/ offers very compelling reasons why you should.

Let's get dirty with a sample application then, apologies in advance for my data model, I was merely testing this out in an actual application and too lazy to whip up a quick starter pack.

Ok then, here's the maven dependency you need, now there are a few complaints about the unavailability of this particular repository (and yes you won't find this in the default maven repository) although I haven't personally been at the receiving end of this. You need to add the following to your maven configuration.


<repositories>
 <repository>
  <id>source.db4o</id>
  <url>http://source.db4o.com/maven/</url>
 </repository>
</repositories>

And now we are all set to resolve the dependency.

<dependency>
 <groupId>com.db4o</groupId>
 <artifactId>db4o-core-java5</artifactId>
 <version>8.1-SNAPSHOT</version>
</dependency>

As for the data model, now this is a model class I created to persist image downloads be warned as it's simplicity might astound you.

public class DownloadImage{
 public String imageUrl;
 public DownloadImage(String imageUrl) {
  this.imageUrl = imageUrl;
 }

 public String getImageUrl() {
  return imageUrl;
 }
}

Here comes the heavy works, now it's best if you keep the connection awake/open as long as possible, why you ask, simples, for performance, when you open and close connections, db4o has to reload data, recreate class metadata/structures etc etc there's a lot of re-'s, although these are standard procedures and hence fast, you don't need this additional overhead, you opted to use db4o for its performance gains after all right. Right.

Now in the code to follow I am using the singleton pattern and my ObjectContainer (definition to follow) is created/opened only once, and it comes with a neat built-in shutdown hook, so I thought what the heck. 


import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.config.EmbeddedConfiguration;
import com.db4o.constraints.UniqueFieldValueConstraint;
import com.kohls.strategies.DownloadImage;

public class DatabaseConnection {
 private DatabaseConnection() {

 }

 private static final ObjectContainer OBJECT_CONTAINER = Db4oEmbedded
   .openFile(Configuration.getConfig(), PropertyLoader.getDbLocation());

 private static class Configuration {
  private static EmbeddedConfiguration getConfig() {
   EmbeddedConfiguration CONFIGURATION = Db4oEmbedded
     .newConfiguration();
   CONFIGURATION.common().objectClass(DownloadImage.class)
     .objectField("imageUrl").indexed(true);
   CONFIGURATION.common().add(new UniqueFieldValueConstraint(DownloadImage.class,"imageUrl"));
   return CONFIGURATION;
  }
 }

 public static ObjectContainer getInstance() {
  return OBJECT_CONTAINER;
 }

 private Object readResolve() {
  // Return the one true instance and let the garbage collector
  // take care of the impersonator.
  return OBJECT_CONTAINER;
 }
}

Hmm now what's that shifty bit there with the private static class, well by default db4o won't check for uniqueness of your records, hence you can store multiple, yeah multiple identical records. To avoid that you need to add constraints. But no, this alone won't guarantee uniqueness. You need to be little clever and put additional checks in place during persistence, a small price to pay if you ask me. 

At this point I think I should tell you what an Object Container is. An Object Container represents your database and all operations would be executed using this. You can have multiple Object Containers.

And finally for the DAO class, cleverly disguised as a service class, I dropped the backing interface definition for this for simplicity.



import java.util.Collection;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.constraints.UniqueFieldValueConstraintViolationException;
import com.kohls.service.DataService;
import com.kohls.strategies.DownloadImage;
import com.kohls.utils.DatabaseConnection;

public class DataServiceImpl {
 private ObjectContainer db = null;

 public void addDownloadable(DownloadImage downloadable) {
  try {
   db = DatabaseConnection.getInstance();
   db.store(downloadable);
   db.commit();
  } catch (UniqueFieldValueConstraintViolationException e) {
   db.rollback();
  } finally {
  }
 }

 public Collection<DownloadImage> getDownloadables() {
  ObjectSet<DownloadImage> downloadables = null;
  try {
   db = DatabaseConnection.getInstance();
   downloadables = db.queryByExample(new DownloadImage(null));
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
  }
  return downloadables;
 }

 public Collection<DownloadImage> getDownloadableByUrl(String url) {
  ObjectSet<DownloadImage> downloadables = null;
  try {
   db = DatabaseConnection.getInstance();
   downloadables = db.queryByExample(new DownloadImage(url));
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
  }
  return downloadables;
 }

 public DownloadImageupdateDownloadable(DownloadImage downloadable) {
  ObjectSet<DownloadImage> result = null;
  DownloadImagefound = null;
  try {
   db = DatabaseConnection.getInstance();
   result = db.queryByExample(downloadable);
   found = result.next();
   //do something with it
   db.commit();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return found;
 }

 public void delete(DownloadImage downloadable) {
  ObjectSet<DownloadImage> result = null;
  DownloadImagefound = null;
  try {
   db = DatabaseConnection.getInstance();
   result = db.queryByExample(downloadable);
   found = result.next();
   db.delete(found);
   db.commit();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

Every operation happens in a transaction hence the explicit commits. Apart from this , explicit commits also allow you to capture exceptions, allowing you to, yeah you guessed it, rollback. It's good practice when you are storing or deleting records, to grab the record in question first.

Ok that's all I have time for.

Saturday, December 29, 2012

Simple Java NIO Socket Server

There are plenty of awesome Java Socket Server Implementations out there, the purpose of writing a rather simple implementation of my own is purely academic. Interested readers can check out,

  1. Netty at https://netty.io/
  2. Apache MINA at http://mina.apache.org/
The above implementations/frameworks have gone way past the point of being just "NIO Socket Servers". They are in fact fully evolved event based asynchronous systems you can use for a wide variety of needs.

Let's get down to business then, The following implementation simulates a request-reply.

The server simply listens for connections on a port and responds to valid requests with a reply.

package com.sockets.server;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Date;

public class ProcessSocketChannel implements Runnable {
 private SocketChannel socketChannel;
 private int BUFFER_SIZE = 1024;

 public ProcessSocketChannel(SocketChannel socketChannel) {
  this.socketChannel = socketChannel;
  Thread thread = new Thread(this);
  thread.start();
 }

 public void run() {
  System.out.println("Connection received from "
    + socketChannel.socket().getInetAddress().getHostAddress());
  readMessage();
  sendMessage("This is the server!!");
 }

 void sendMessage(String msg) {
  String fullmessage = new Date().toString() + " > " + msg;
  ByteBuffer buf = ByteBuffer.allocate(fullmessage.getBytes().length);
  buf.clear();
  buf.put(fullmessage.getBytes());
  buf.flip();
  while (buf.hasRemaining()) {
   try {
    socketChannel.write(buf);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

 void readMessage() {
  ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
  Charset charset = Charset.forName("us-ascii");
  CharsetDecoder decoder = charset.newDecoder();
  CharBuffer charBuffer;
  try {
   int bytes = socketChannel.read(byteBuffer);
   byteBuffer.flip();
   charBuffer = decoder.decode(byteBuffer);
   String result = charBuffer.toString();
   System.out.println(result);
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   byteBuffer = null;
   charset = null;
   decoder = null;
   charBuffer = null;
  }
 }
}

Processing of requests is delegated to a thread ProcessSocketChannel ,

package com.sockets.server;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Date;

public class ProcessSocketChannel implements Runnable {
 private SocketChannel socketChannel;
 private int BUFFER_SIZE = 1024;

 public ProcessSocketChannel(SocketChannel socketChannel) {
  this.socketChannel = socketChannel;
  Thread thread = new Thread(this);
  thread.start();
 }

 public void run() {
  System.out.println("Connection received from "
    + socketChannel.socket().getInetAddress().getHostAddress());
  readMessage();
  sendMessage("This is the server!!");
 }

 void sendMessage(String msg) {
  String fullmessage = new Date().toString() + " > " + msg;
  ByteBuffer buf = ByteBuffer.allocate(fullmessage.getBytes().length);
  buf.clear();
  buf.put(fullmessage.getBytes());
  buf.flip();
  while (buf.hasRemaining()) {
   try {
    socketChannel.write(buf);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

 void readMessage() {
  ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
  Charset charset = Charset.forName("us-ascii");
  CharsetDecoder decoder = charset.newDecoder();
  CharBuffer charBuffer;
  try {
   int bytes = socketChannel.read(byteBuffer);
   byteBuffer.flip();
   charBuffer = decoder.decode(byteBuffer);
   String result = charBuffer.toString();
   System.out.println(result);
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   byteBuffer = null;
   charset = null;
   decoder = null;
   charBuffer = null;
  }
 }
}

As for the client

package com.sockets.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Date;

public class Client {
 //The default buffer size
 private final int BUFFER_SIZE = 1024;
 private SocketChannel clientSocket;
 //The port of the server connecting to
 private int port = 7777;

 void run() {
  try {
   clientSocket = SocketChannel.open();
   //Obtaining the localhost
   InetAddress host = InetAddress.getLocalHost();
   //Connecting to server
   clientSocket.connect(new InetSocketAddress(host, port));
   System.out.println(String.format("Connected to %s on port %d",
     host.getHostAddress(), port));
   //Sending a message to the server
   sendMessage("Hello Server!!");
   //Reading the reply sent from the server
   readMessage();
  } catch (UnknownHostException unknownHost) {
   System.err.println("You are trying to connect to an unknown host!");
  } catch (IOException ioException) {
   ioException.printStackTrace();
  } finally {
   //Closing connection
   try {
    clientSocket.close();
   } catch (IOException ioException) {
    ioException.printStackTrace();
   }
  }
 }

 void sendMessage(String msg) throws IOException {
  String fullmessage = new Date().toString() + " > " + msg;

  ByteBuffer buf = ByteBuffer.allocate(fullmessage.getBytes().length);
  //Initialize the buffer
  buf.clear();
  buf.put(fullmessage.getBytes());
  //Flip the content of the buffer before writing
  buf.flip();
  //Writing Buffer Content to socket
  while (buf.hasRemaining()) {
   clientSocket.write(buf);
  }
 }

 void readMessage() {
  //Reads a text message
  ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
  Charset charset = Charset.forName("us-ascii");
  CharsetDecoder decoder = charset.newDecoder();
  CharBuffer charBuffer;
  try {
   int bytes = clientSocket.read(byteBuffer);
   byteBuffer.flip();
   charBuffer = decoder.decode(byteBuffer);
   String result = charBuffer.toString();
   System.out.println(result);
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   byteBuffer = null;
   charset = null;
   decoder = null;
   charBuffer = null;
  }
 }

 public static void main(String args[]) {
  Client client = new Client();
  client.run();
 }
}

While I admit that the above implementation is less than ideal, given that it captures the basics of socket communications, I think it's a good starting point for those who still care about how the clock actually ticks.

Tuesday, December 25, 2012

Downloading Images with java NIO

So We got this flex application, it's got tons of images it's got to show and the client is not too happy with the loading time. It connects to a JEE back-end which pushes these image URLs. 

I have already cached requests at the back end, solved half the problem actually. And while we were at it, we cached the images at the front end too. Now, it takes around 6-7 seconds for a screen(state) to load the first time around, but we have managed to cut the subsequent requests down to 2-3 seconds range with request and content caching. The client, well he is still not too happy with initial loading times(no surprises there). So we came up with the idea to pre-download the images on to the local machine the application is running on.


Which brings us over to the topic of the post, downloading images. We wanted this to be light weight, so I initially planned on using Apache's HTTP client to do the dirty work asynchronously.Turns out it's slower than my arthritic granny, I couldn't have that. So I figured why not NIO, it's fast, it is efficient and gets the job done.


The download action is given below, I used an interface, but this is really not necessary, as I am not adding anything to it.

public interface Downloadable extends Runnable {
 
}

and here is the implementation of the download artifact,

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;

public class DownloadImage implements Downloadable {
 private String imageUrl;

 public DownloadImage(String imageUrl) {
  this.imageUrl = imageUrl;
 }

 public void run() {
  String resultFileName = DigestTools.getMD5Digest(imageUrl);
  try {
   URL url = new URL(imageUrl);
   ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
   FileOutputStream fileOutputStream = new FileOutputStream(
     PropertyLoader.getDownloadFileLocation() + resultFileName);
   FileChannel fileChannel = fileOutputStream.getChannel();
   fileChannel.transferFrom(readableByteChannel,0, 1 << 24);
   fileOutputStream.close();
   fileChannel.close();
   readableByteChannel.close();
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }catch (IOException e) {
   e.printStackTrace();
  }
 }

 /*
  * (non-Javadoc)
  * 
  * @see java.lang.Object#hashCode()
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result
    + ((imageUrl == null) ? 0 : imageUrl.hashCode());
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see java.lang.Object#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj) {
   return true;
  }
  if (obj == null) {
   return false;
  }
  if (!(obj instanceof DownloadImage)) {
   return false;
  }
  DownloadImage other = (DownloadImage) obj;
  if (imageUrl == null) {
   if (other.imageUrl != null) {
    return false;
   }
  } else if (!imageUrl.equals(other.imageUrl)) {
   return false;
  }
  return true;
 }

 @Override
 public String toString() {
  return "Download Artifact : " + imageUrl;
 }
}

Note that I have used several custom utility classes, like DigestTools and PropertyLoader. And now to the executor, I decided to go with Java Executor Service.

public class ImageDownloader {
 private static final Logger LOGGER = Logger
   .getLogger(ImageDownloader.class);
 private static final boolean DEBUG = LOGGER.isDebugEnabled();
 Collection<Downloadable> downloadables;
 ExecutorService executorService = Executors.newFixedThreadPool(PropertyLoader.getConcurrentThreads());

 public ImageDownloader() {
  if (DEBUG) {
   LOGGER.debug("Initializing image downloader");
  }
  downloadables = new HashSet<Downloadable>();
 }

 public void addDownloadable(Downloadable downloadable) {
  if (DEBUG) {
   LOGGER.debug("Adding downloadable with url " + downloadable);
  }
  downloadables.add(downloadable);
 }

 public void downloadImages() throws InterruptedException,
   ExecutionException, TimeoutException {
  if (executorService.isShutdown()) {
   executorService = Executors.newFixedThreadPool(PropertyLoader.getConcurrentThreads());
  }
  Collection<Future<Downloadable>> futures = new HashSet<Future<Downloadable>>();
  for (Downloadable downloadable : downloadables) {
   Future<Downloadable> future = executorService.submit(downloadable,downloadable);
   future.get(6, TimeUnit.SECONDS);
   futures.add(future);
  }
  for (Future<Downloadable> future : futures) {
   future.get();
  }
  executorService.shutdown();
  downloadables = Collections.EMPTY_SET;
 }
}

It's just a matter of firing it up now.



public class PartyStarter {

 /**
  * @param args
  * @throws ExecutionException 
  * @throws InterruptedException 
  * @throws TimeoutException 
  * @throws IOException 
  */
 public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException, IOException {
  Downloadable d1 = new DownloadImage("image_url1");
  Downloadable d2 = new DownloadImage("image_url2");
  
  ImageDownloader imageDownloader = new ImageDownloader();
  imageDownloader.addDownloadable(d1);
  imageDownloader.downloadImages();
 }

}
That's it for this post folks.