Monday, February 21, 2011

Java Observer Design Pattern using Rmi

Recently I had a requirement in my work, where I had to PUSH data from server to client, when new data arrives.
Now obviously I considered using the OBSERVER design pattern to solve my problem.
The clients were remote but in the same company network. And there was no messaging service available.

I could not find a way to use observer pattern over HTTP, so I chose to use RMI.

Implementing Observer design pattern over RMI is a bit tricky. After searching on the internet,
I found out that a good samaritan has already done the job.
Here is the link, where I took the basic codebase from
http://sites.google.com/site/jamespandavan/Home/java/sample-remote-observer-based-on-rmi

Now there is a problem in this design approach. Once you start the server and the client, the client perfectly receives the messages pushed by the server.
But if the server goes down for some reason, then there is no way for the client to know it. Yes, there is no RemoteException or ConnectException thrown in this case.
The client keeps itself running, wondering, why it is not getting any data from server.
The existing client will not receive any data, even when the server is back up.

To solve this problem, I used the last timestamp, when the client received PUSH data from server. If the time is more than a specified time, client considers the connection dead and tries to reconnect to the server.
This trying to reconnect goes on forever, until the server goes up. Then everything works fine, just like before, as if nothing happened.

Few words before sharing the codebase:
1) Don't forget to make your data serializable.
2) Generate the rmi stub class using the rmic command. Details about this command can be found in the Oracle website here.
2) After the server code is written, create a jar file, containing the RMIService interface, the Model class and the rmi stub.
3) Clients on separate JVM, have to put this jar in their classpath.

Here's the code, more or less the same code found in the above link, with slight modifications:

Running the Server/Client:

java -Djava.security.licy=security.policy RmiServer
java -Djava.security.licy=security.policy RmiClient
The Security Policy file:

grant
{
    Permission java.security.AllPermission;
};
The POJO DTO (Don't forget the serializable part)

import java.io.Serializable;

public class Model implements Serializable{

 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private String name;
 private int id;
 private long lastTimsStamp;
 public Model(String name, int id,long lastTimsStamp) {
  super();
  this.name = name;
  this.id = id;
  this.lastTimsStamp = lastTimsStamp;
 }
 public String getName() {
  return name;
 }
 public int getId() {
  return id;
 }
 public long getLastTimsStamp() {
  return lastTimsStamp;
 }
 
 
}
Remote observer interface

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteObserver extends Remote {

    void update(Object observable, Object updateMsg) throws RemoteException;

}
RMI client program implementing the interface

import java.net.MalformedURLException;
import java.rmi.ConnectException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import rmisubject.Model;
import rmisubject.RemoteObserver;
import rmisubject.RmiSubjectService;

public class RmiObserverClient extends UnicastRemoteObject implements RemoteObserver {
    
 /**
  * If the client hasn't received any data for the span of connectionCheckInterval, it will try to reconnect the server.
  * It will keep trying until the server is not back up.
  * @param connectionCheckInterval
  * @throws RemoteException
  */
 public RmiObserverClient(long connectionCheckInterval) throws RemoteException{
        super();
        this.connectionCheckInterval = connectionCheckInterval;
    }
    private static long lastTimeStamp;
    private static final long serialVersionUID = 1L;
    private static long connectionCheckInterval = 10*1000;
    private static RmiSubjectService remoteService;
    Thread checkConnectionAlive = new Thread() {
       @Override
       public void run() {
           while (true) {
               try {
                   Thread.sleep(connectionCheckInterval);
               } catch (InterruptedException e) {
                   // ignore
               }
               long currentTimeStamp = System.currentTimeMillis();
               
               System.out.println("Inside client checkConnectionAlive : " + currentTimeStamp);
               
               if (currentTimeStamp - lastTimeStamp>connectionCheckInterval )subscribe();
           }
       };
   };
   
    public static void main(String[] args) {
     try {
      RmiObserverClient rc = new RmiObserverClient(10 * 1000);
   rc.subscribe();
   rc.checkConnectionAlive.start();
  } catch (RemoteException e) {
   e.printStackTrace();
  }
     
    }
    public void subscribe(){
     if (System.getSecurityManager() == null)
            System.setSecurityManager(new RMISecurityManager());
        try {
            remoteService = (RmiSubjectService) Naming.lookup("//localhost:9999/RmiService");
            remoteService.addObserver(this);
        } catch (ConnectException ex) {
            ex.printStackTrace();
        }catch (RemoteException e) {
          e.printStackTrace();
  }catch (MalformedURLException e) {
   e.printStackTrace();
  }catch (NotBoundException e) {
   e.printStackTrace();
  }
    }
    @Override
    public void update(Object observable, Object updateMsg)
            throws RemoteException {
        System.out.println("===============start message=============");
        Model model = (Model)updateMsg;
        System.out.println(model.getName());
        System.out.println(model.getId());
        lastTimeStamp = model.getLastTimsStamp();
        System.out.println(lastTimeStamp);
        System.out.println("===============end message=============");
    }
}
RMI service interface

public interface RmiSubjectService extends Remote {

   void addObserver(RemoteObserver o) throws RemoteException;
}
RMI server (the observable)

import java.io.Serializable;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Observable;
import java.util.Observer;

public class RmiSubjectImpl extends Observable implements RmiSubjectService {

    private class WrappedObserver implements Observer, Serializable {

        private static final long serialVersionUID = 1L;
       
        private RemoteObserver ro = null;

        public WrappedObserver(RemoteObserver ro) {
            this.ro = ro;
        }

        @Override
        public void update(Observable o, Object arg) {
            try {
                ro.update(o.toString(), arg);
            } catch (RemoteException e) {
                System.out
                        .println("Remote exception removing observer:" + this);
                o.deleteObserver(this);
            }
        }

    }

    @Override
    public void addObserver(RemoteObserver o) throws RemoteException {
        WrappedObserver mo = new WrappedObserver(o);
        addObserver(mo);
        System.out.println("Added observer:" + mo);
    }

    Thread thread = new Thread() {
      private int i=0;
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    // ignore
                }
                setChanged();
                notifyObservers(new Model("model", i++,System.currentTimeMillis()));
                //notifyObservers(new Date());
            }
        };
    };

    public RmiSubjectImpl() {
        thread.start();
    }

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        if (System.getSecurityManager() == null)
            System.setSecurityManager(new RMISecurityManager());
        try {
            Registry rmiRegistry = LocateRegistry.createRegistry(9999);
            RmiSubjectService rmiService = (RmiSubjectService) UnicastRemoteObject
                    .exportObject(new RmiSubjectImpl(), 9999);
            rmiRegistry.bind("RmiService", rmiService);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

Hope this helps. Let me know if it doesn't.

Wednesday, February 16, 2011

How to Convert XML attributes to elements using XSLT

Recently I was using Apache Digester to convert( Transform) a XML content into List of Objects.
Out of all the APIs I tried, I found digester was the best solution for my of requirement.
For people who didnot use Digester before, I would recommend giving it a try. It will make your life
easier. You can go home from work early and spend some quality time with quality people.
I will probably post some code snippets on how to use Digester, but this post is not about that.

Coming back to point.
Just like any other XML, the XML content I was trying to parse, contained few attributes, alongwith the elements.
Now digester might be having some features to take care of attributes, but I found it hard to follow.
I created the following XSLT instead. Which, when applied to a XML, transforms all it's attributes into TAGS.
The XSLT is generic enough to be used on any xml content.
If you are not sure, how to apply this xslt to your XML, keep reading. I have some sample code too.

Firstly, the XSLT content:



<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="UTF-8"/>
  <xsl:strip-space elements="*" />
  <xsl:template match="*">
  <xsl:copy >
      <xsl:if test="@*">
        <xsl:for-each select="@*">
          <xsl:element name="{name()}" >
            <xsl:value-of select="." />
          </xsl:element>
        </xsl:for-each>
      </xsl:if>
      <xsl:apply-templates />
    </xsl:copy>
    </xsl:template>
</xsl:stylesheet> 



It is a small XSLT and should be easy to understand. In case you have problem understanding the logic, ask me.

Sample code to transform any XML using any XSLT:

Prerequisite:-
A JAVA environment offcourse. Lets not get into that deep. Amongst all the libraries that come with the distribution, the one you actively need is

rt.jar

Here is some sample code. The method names are self-explanatory.


 public static String convertAllAttributesToElements(String xmlContent) throws TransformerException{
   javax.xml.transform.Source xmlSource =new javax.xml.transform.stream.StreamSource(new StringReader(xmlContent));
   javax.xml.transform.Source xsltSource =new javax.xml.transform.stream.StreamSource(xsltFile);
   return transformContent(xmlSource,xsltSource);
 }
 
 public static String convertAllAttributesToElements(File xmlFile) throws TransformerException{
   javax.xml.transform.Source xmlSource = new javax.xml.transform.stream.StreamSource(xmlFile);
   javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
   return transformContent(xmlSource,xsltSource);
 }
 
 private static String transformContent(javax.xml.transform.Source xmlSource,javax.xml.transform.Source xsltSource) throws TransformerException{
  String modifiedContent = null;
  javax.xml.transform.TransformerFactory transFact = javax.xml.transform.TransformerFactory.newInstance();
  ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  StreamResult result = new javax.xml.transform.stream.StreamResult(outStream);
  javax.xml.transform.Transformer trans = transFact.newTransformer(xsltSource);
  trans.transform(xmlSource, result);
  byte[] b = ((ByteArrayOutputStream)result.getOutputStream()).toByteArray();  
  modifiedContent = new String (b);
  //removing any line feed or spaces to save bytes.
  modifiedContent = modifiedContent.replaceAll("[\\n\\r\\s]+","");
  return modifiedContent;
 }
 


I hope this helps guys. Let me know if there are any issues.


Monday, January 10, 2011

ResultSet to XML converter

Sometimes there is a need to convert a resultset into a xml file. The xml file can be shared across webservices.
I had a similar requirement but found no example online.
So I created this utility to convert resultsets into xml. The language of development is Java.
The code has provision to accept multiple resultsets. All the resultsets will be appended in the xml file.
The rows of tables can be indentified by row identifiers. Which is user supplied.

Understanding that the resultsets can be very large, I have used stax based parser to write the xml.
Amongst STAX based parsers, I have choosen WOODSTOX as my parser. Because it has very good performance ratings in various benchmark tests.
Details of Woodstox can be found here.

I have uploaded my source files in sourceforge. And can be found at the following location.

https://sourceforge.net/projects/rstoxmlwriter/

A typical usage might be:

  for (String tableName : tableNames) {
          String rowId = "row";
   String query = "Select "+selectClause+" from "+table+restrictions;
   ResultSet tableData = getResult(query);
   XmlElementInfo xmlElementInfo = new XmlElementInfo(tableData,
                        rowId.toUpperCase(),table.toUpperCase());
   xmlElementInfos.add(xmlElementInfo);
  }
  try {
   new XMLWriter().writeXML(xmlElementInfos,parentTag, outputLocation+xmlFileName);
  } catch (XMLWriterException e) {
   e.printStackTrace();
  }
  closeDB();






I would be happy, if anybody finds this useful. 
Also please put your comments. Let me know if there are any bugs. Let me know if there is any further enhancement requests.


Monday, February 22, 2010

Update Twitter status using this java code


import sun.misc.BASE64Encoder;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStreamWriter;
import java.net.URLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class Twitter {

public static void main(String[] args) throws Exception {


URL url = new URL("https://twitter.com/statuses/update.xml");
URLConnection connection = url.openConnection();

String crendetials = "username" + ":" + "password";

BASE64Encoder encoder = new BASE64Encoder();

String encodedCredentials = new String(encoder.encodeBuffer(crendetials.getBytes())).trim();

connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);

OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("status=" + URLEncoder.encode("It was really simple to write simple status message updation code using Java. This message also goes thought my Java code. It's fun", "UTF-8"));
out.close();

BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response;
while ((response = in.readLine()) != null) {
System.out.println(response);
}
in.close();
}

}

Wednesday, December 30, 2009

Java String array - Single and Multidimensional

In java arrays can be single as well as multi dimentional. This is true not only for Strings, but also for int, double, char etc all datatypes.
Arrays can be declared in two ways. Today i will show you how to declare arrays in Java.
This post will cover both the ways array can be declared and also how to access the elements.
Please comment if this post helps you or if there is something I missed.
Happy Coding.

Lets start with Single Dimension Arrays:





 String [] OneDArray1 = new String[10];
  OneDArray1[0] = "1";
  OneDArray1[2] = "2";
  OneDArray1[5] = "3";

  for(int i=0;i
   System.out.println(OneDArray1[i]);
  }
  
Output of this code snippet:

 1
 null
 2
 null
 null
 3
 null
 null
 null
 null



Another way of declaring single dimension arrays:


 String [] OneDArray2 = {"1","2","3"};
  
  for(int i=0;i
   System.out.println(OneDArray2[i]);
  }
  
Output of this code snippet:

 1
 2 
 3
 

Multi Dimensional Arrays


  String TwoDArray1[][] = new String[2][3];
  
  TwoDArray1[0][0] = "1";
  TwoDArray1[0][1] = "2";
  TwoDArray1[0][2] = "3";
  
  TwoDArray1[1][0] = "4";
  TwoDArray1[1][1] = "5";
  TwoDArray1[1][2] = "6";
  
  for(int i=0;i
   for(int j=0;j
    System.out.println(TwoDArray1[i][j]);
   }
  }

Output of this code snippet:

 1
 2
 3
 4
 5
 6
 

Another way of declaring multi dimensional arrays:


 String TwoDArray2[][] = { {"1","2"},{"3","4"} };
  
  for(int i=0;i
   for(int j=0;j
    System.out.println(TwoDArray2[i][j]);
   }
  }
 
Output of this code snippet:
 1
 2
 3
 4



Friday, December 18, 2009

Java find longest matching part or substring of string

Finding largest common sub string from an array of strings is often very useful. Recently I had this requirement, where I was trying to exclude a list of strings by using regex patterns. For this I had to find the greatest matching substring among the strings, so that I put that substring as a regex, and save a lot of effort.
Unfortunately I didn't find any ready made code on the net, that does the same thing. So I wrote my own.

I tried to make the logic as optimum as possible.
If anyone has a better algorithm in mind, please share it with me.

I have used a custom string length comparator, so optimise the string traversing. Readers can write their own implementation of the comparator, or copy my custom string length comparator class from here.



 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;

 public class SubString {

  public static void main(String[] args) {
    String [] strs = {
     "this is a very big first string which should be processed at last",
     "this is a very small string" ,
     "this is a very boring string nothing special",
     "this is a very simple yet bigger string, second large"
    };

   //Arrays.sort(strs, new CustomStringLengthComparator());
   String sub = strs[0];
   Map subStrings = new HashMap();
   int j=strs[0].length();

   String comparingString =strs[1];
   while (j>=0) {
    for(int i=0;i< j;i++) {
     sub = strs[0].substring(i, j);
     if (comparingString.contains(sub)) {
      subStrings.put(sub.length(),sub);
     }
    }
    j--;
   }
   boolean flag =false;
   if(!subStrings.isEmpty()) {
    Set set = subStrings.keySet();
    TreeSet treeSet = new TreeSet(set);     
    String matchedString = subStrings.get(treeSet.last());   
    for(int k=2;k
     if (strs[k].contains(matchedString)) {
      flag=true;     
     }else {
      flag=false;     
      break;     
     }   
    }     
    if (flag) { 
     System.out.println("Matched : " + subStrings.get(treeSet.last()));
    }else {       
     System.out.println("No Match");     
    }   
   } 
  } 
 }

Custom String Length Comparator Java

The default sort method for strings is Java is it's character values. For example, If we have a string array:



String [] strs = {"abc", "xyz", "mnop123"};
And we use Arrays.sort(strs), the output will be in the following order:


abc
mnop123
xyz
But there are times, when we want to sort strings, by their length. The following custom string length comparator will serve the purpose:


import java.util.Comparator;

public class CustomStringLengthComparator implements Comparator{

 public int compare(String o1, String o2) {
  if (o1.length() < o2.length()) {
        return -1;
      } else if (o1.length() > o2.length()) {
        return 1;
      } else {
        return 0;
      }
 }

}


Instead of using


Arrays.sort(strs)
we have to use


Arrays.sort(strs, new CustomStringLengthComparator());



Wednesday, December 9, 2009

Currency format

As we know the way of formatting currency are different in many country. Main there is a big difference in European and British way. This code snippet converts the currency to appropriate formats and also does the reverse parsing.



 
public static void main(String args[]){
  // Format
     Locale locale = Locale.FRANCE;
     String string1 = NumberFormat.getCurrencyInstance(locale).format(123456789.12);
     System.out.println(string1);
    
     locale = Locale.US;
     String string = NumberFormat.getCurrencyInstance(locale).format(123456789.12);
     System.out.println(string);
    
     // Parse
     try {
         Number number = NumberFormat.getCurrencyInstance(locale).parse(string1);
         System.out.println(number.toString());
         number = NumberFormat.getCurrencyInstance(locale).parse(string);
         System.out.println(number.toString());
     } catch (ParseException e) {
     }
 }
 
 

List The Contents of a ZIP File

This is a utility program to view the contents of a zip file


import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 *
 * @author Rakesh P
 * ZipFile Function Accept the Path of the Zip File 
 */
public class ZipContents{
   
    public void listContentsOfZipFile() {
       
        try {
            ZipFile zipFile = new ZipFile("d:/FeedtoInterfaces.zip");
           
            Enumeration zipEntries = zipFile.entries();
           
            while (zipEntries.hasMoreElements()) {
               
                //Process the name, here we just print it out
                System.out.println(((ZipEntry)zipEntries.nextElement()).getName());
               
            }
           
        } catch (IOException ex) {
            ex.printStackTrace();
        }
       
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
        new  ZipContents().listContentsOfZipFile();
       
    }
}

Sunday, October 25, 2009

Java Swing Example: Image dimension from url

This code can be used to get the dimension of any image using its url. Minor tweaks can be made to get localized image dimensions too.Hope this helps.


import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JFrame;

public class ImageDimensions extends JFrame {
 
 protected static Toolkit tool = Toolkit.getDefaultToolkit();
 
 public ImageDimensions() {
 }

 protected void calculateHeightWidth()
   throws InterruptedException {
  Image image = null;
  try {
   image = tool.createImage(new URL("Image URL"));
   
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }catch(Exception e1){
   e1.printStackTrace();
  }
  
  MediaTracker mTracker = new MediaTracker(this);
  mTracker.addImage(image, 1);
  int i = 0;
  do {
   mTracker.waitForID(1);
   //added counter and break for the 404 or bad url 
   i++;
   if (i==5) break;
  } while (mTracker.statusID(1, true) != MediaTracker.COMPLETE);

System.out.println(image.getHeight(null));
System.out.println(image.getWidth(null));
 }
 
 public static void main(String[] args) {
 try {
  new ImageDimensions().calculateHeightWidth();
 } catch (InterruptedException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } 
 }
 
}