Pages

Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Wednesday, January 2, 2013

Ehcache refresh on DB change from external source

Problem statement:

  1. I have 2 web applications say WebApp-1 and WebApp-2, they access same database say DB-1 using Hibeernate 3.6. 
  2. WebApp-2 uses L2 cache i.e. Ehcache whereas WebApp-1 doesn't use any L2 caching.
  3. When WebApp-1 modifies DB state, L2 cache of WebApp-2 doesn't reflect that, as a result of that modifactions doen by WebApp-1 are not visible to WebApp-2.
Problem solution: 
I have found these three solutions from ehcache documentation.

Use one of the following strategies to keep the data in the cache in sync:
  • data expiration: use the eviction algorithms included with Ehcache along with the timeToIdleSeconds and timetoLiveSeconds setting to enforce a maximum time for elements to live in the cache (forcing a re-load from the database or SOR).
  • message bus: use an application to make all updates to the database. When updates are made, post a message onto a message queue with a key to the item that was updated. All application instances can subscribe to the message bus and receive messages about data that is updated, and can synchronize their local copy of the data accordingly (for example by invalidating the cache entry for updated data)
  • triggers: Using a database trigger can accomplish a similar task as the message bus approach. Use the database trigger to execute code that can publish a message to a message bus. The advantage to this approach is that updates to the database do not have to be made only through a special application. The downside is that not all database triggers support full execution environments and it is often unadvisable to execute heavy-weight processing such as publishing messages on a queue during a database trigger.
I thought of using the message bus or JMS kind of solution. But, I did't use that, for that matter what I did used is a broadcasting solution.

So, as per my problem, WebApp-1 broadcasts all the change events whereas WebApp-2 forks a thread which listens to any broadacast messages send by WebApp-1. Here is the code snippet for the broadcaster and receiver.

Broadcaster:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import net.atomex.dashboard.controllers.AdvertiserController;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CacheEventBroadcaster extends Thread {

        private String entityName = null;
        private Integer entityId = null;

        private DatagramSocket socket = null;

        private Logger logger = LoggerFactory.getLogger(AdvertiserController.class);

        
        public CacheEventBroadcaster(String entityName, Integer entityId)
                        throws IOException {                
                this("CacheEventThread", entityName, entityId);
        }

        public CacheEventBroadcaster(String name, String entityName,
                        Integer entityId) throws IOException {
                super(name);
                this.entityId = entityId;
                this.entityName = entityName;
                logger.trace("Starting cache event broadcaster...");
        }

        public void run() {
                try {
                        boolean connected = false;
                        while (!connected) {
                                // Create the datagram socket
                                try{
                                socket = new DatagramSocket(4445);
                                }catch (Exception e) {
                                        //do nothing but retry
                                        logger.trace("Exception: " + e.getMessage());
                                }
                                connected = true;
                        }

                        // Create the broadcast message
                        byte[] buf = new byte[1024];
                        String dString = entityName + ":" + entityId;
                        buf = dString.getBytes();
                        logger.trace("Broadcast message created : [" + dString + "]");

                        // Create the broadcast group
                        InetAddress group = InetAddress.getByName("230.0.0.1");
                        DatagramPacket packet = new DatagramPacket(buf, buf.length, group,
                                        4446);
                        logger.trace("Sending message to : " + group.getHostAddress());

                        // Send the message to broadcast group
                        socket.send(packet);
                        logger.trace("Message sent successfully.");

                        // close the socket
                        socket.close();
                } catch (IOException e) {
                        logger.trace("An error occured while brodcasting the message. "
                                        + e.getMessage());
                        e.printStackTrace();
                }
        }

        public static void broadcastCacheEvent(String entityName, Integer entityId) {
                try {
                        new CacheEventBroadcaster(entityName, entityId).start();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
}


Use this piece of code to send the broadcast message.

CacheEventBroadcaster.broadcastCacheEvent("EntityName", id);


Receiver: 

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.komli.prime.service.shared.cache.HibernateCacheProvider;
import com.komli.prime.service.shared.util.db.DatabaseFactory;

public class CacheEventsReceiver {
        static final Logger logger = LoggerFactory.getLogger(CacheEventsReceiver.class);
        public static void receiveCacheEvents() throws IOException {
                logger.info("Cache event listner deamon thread started...");
                new ReceiverThread().start();
        }
}

class ReceiverThread extends Thread {

        static final String QUERY_CACHE = "org.hibernate.cache.StandardQueryCache";
        static final Logger logger = LoggerFactory.getLogger(ReceiverThread.class);
        static CacheManager cacheManager = HibernateCacheProvider.getCacheManager();

        public void run() {

                MulticastSocket socket;
                try {
                        socket = new MulticastSocket(4446);
                        InetAddress address = InetAddress.getByName("230.0.0.1");
                        socket.joinGroup(address);
                        DatagramPacket packet;
                        String entityName;
                        Integer entityId;

                        while (true) {

                                byte[] buf = new byte[1024];
                                packet = new DatagramPacket(buf, buf.length);
                                socket.receive(packet);

                                String message = new String(packet.getData(), 0,
                                                packet.getLength());

                                if (message != null && !message.equals("")) {

                                        String inputs[] = message.split(":");
                                        entityName = inputs[0];
                                        entityId = new Integer(inputs[1]);

                                        logger.info("Received new cache event, message is "
                                                        + message);

                                        @SuppressWarnings("unchecked")
                                        Object entity = getById(
                                                        CacheObjectMap.getMappedClass(entityName), entityId);
                                        
                                        //Remove the query cache to get the latest changes,                                        
                                        Cache queryCache = cacheManager.getCache(QUERY_CACHE);
                                        queryCache.removeAll();
                                        logger.info("Query Cache Cleared...");                                        

                                        // Evict the entity from session
                                        DatabaseFactory
                                                        .createDatabase()
                                                        .getSessionFactory()
                                                        .evict(CacheObjectMap.getMappedClass(entityName),
                                                                        entityId);
                                }
                        }
                } catch (IOException e) {
                        logger.info("An error occured while brodcasting the message. "
                                                        + e.getMessage());
                        e.printStackTrace();
                }

        }

        public  T getById(Class c, long id) {
                DatabaseFactory.createDatabase().getSessionFactory()
                                .getCurrentSession().beginTransaction();
                Criteria criteria = DatabaseFactory.createDatabase()
                                .getSessionFactory().getCurrentSession().createCriteria(c);
                criteria.add(Restrictions.eq("id", (int) id));

                @SuppressWarnings("unchecked")
                List result = (List) criteria.list();
                if (result == null || result.size() == 0)
                        return null;
                return result.get(0);
        }
}


Put this piece somewhere to register/start above piece of code.

try {
        CacheEventsReceiver.receiveCacheEvents();
} catch (IOException e) {
        e.printStackTrace();
}


The CacheObjectMap is a string to class mapper. The sample code snippet is as below.

import java.util.HashMap;

public class CacheObjectMap {

        private static HashMap<String, Class> classMap;

        static {
                classMap = new HashMap<String, Class>();
                
                classMap.put("EntityName", com.komli.prime.service.shared.db.model.Entity.class);
                                
        }
        
        public static Class getMappedClass(String className){
                return classMap.get(className);
        }
}

Wednesday, December 19, 2012

Current epoch time

Perl                    time
PHP                     time()
Java                  long epoch = System.currentTimeMillis()/1000;
MySQL                 SELECT unix_timestamp(now())
Oracle PL/SQL         SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00','DD-MM-YYY HH24:MI:SS')) * 24 * 60 * 60 FROM DUAL
JavaScript           Math.round(new Date().getTime()/1000.0) getTime() returns time in milliseconds.
Unix/Linux Shell     date +%s

Tuesday, December 18, 2012

Character count problem

You have a string of small letters a-e, which can be represented as a regular expression in the form of [a-e]*

Example: abcdef, eafdceeafe, etc etc

Problem: Write a program that counts maximum continuous occurrence of a character and their indexes. For example, if the string is "abbbbdcdef", it will be "b" : 4, starting at index 1 to 4.

public class TestStringCharCount {

   public static void main(String[] args) {

        int start = 0;
        int count = 0;
        int maxCount = 0;
        char maxChar = 'a';
        String str = "abcdefabbbbbbbbcdaeff";
        char[] chars = str.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            count = 0;
            for (int j = i; j < chars.length; j++) {

                if (chars[i] == chars[j]) {
                    count++;
                } else {
                    break;
                }
                i = j;
            }

            if (count > maxCount) {
                maxCount = count;
                maxChar = chars[i];
                start = i;
            }

        }
        System.out.println("string = "+ str + ", length = "+ str.length());
        
        System.out.println(maxChar + ":" + maxCount + " starting at "
                + (start - maxCount) + " to " + start);
    }
}

Output: 
string = abcdefabbbbbbbbcdaeff, length = 21
b:8 starting at 6 to 14

Thursday, June 7, 2012

Java program to find host name and IP address of local and remote machine

Problem Statement: Many times we need to find the host name and IP address of local and the remote machines. Most importantly I want to do this with a Java program.

Solution: Here is the main class, I have named it as HostNameFinder and to test these methods I've another class called as HostNameFinderTest.

/**
 * 
 * Classname : HostNameFinder.java
 * <b>HostNameFinder<b><br> 
 * <p>
 *     This class helps to get the host name and the IP addresses of the local machine and 
 *     remote machines. It provides static methods that can be used to get the very specific
 *     information such as host name or the IP address.
 * </p>
 * 
 * @author Manohar Negi
 * @version 1.0
 * @since 1.0
 * @see
 * Copyright notice
 *
 * Revision History: 
 *
 * Date            By              Version        Comments
 * ---------------------------------------------------------------------------------
 * Aug 31, 2011    Manohar Negi    1.0            Initial Draft
 * Sep 01, 2011    Manohar Negi    1.1            Modified to include more methods
 *
 **/

package com.mani.util;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * <p>
 * <b>Functional Description:</b>
 * <p>
 * Some Description of the file
 * 
 * Created: Month, Day ,YYYY
 * 
 * @author
 * @version
 */
public class HostNameFinder {

    public static String getMyHostName() {
        String hostname = null;
        try {
            InetAddress addr = InetAddress.getLocalHost();
            hostname = addr.getHostName();
            System.out.println("Host Name = " + hostname);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return hostname;
    }

    public static String getMyIPAddress() {
        String ipAddress = null;
        try {
            InetAddress addr = InetAddress.getLocalHost();
            String ipAddr = addr.getHostAddress();
            System.out.println("IP Address = " + ipAddr.toString());

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return ipAddress;
    }

    public static String getIPByAddress(String address) {
        String ipAddress = null;
        try {
            InetAddress addr = InetAddress.getByName(address);
            String ipAddr = addr.getHostAddress();
            System.out.println("IP Address = " + ipAddr.toString());

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return ipAddress;
    }

    public static String getHostNameByAdress(String address) {
        String hostname = null;
        try {
            InetAddress addr = InetAddress.getByName(address);
            hostname = addr.getHostName();
            System.out.println("Host Name = " + hostname);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return hostname;
    }

}


Here is the test class.

/**
 * 
 * Classname : HostNameFinderTest.java
 * <b>HostNameFinderTest<b><br> 
 * <p>
 *     This class is to test the methods of HostNameFinder.class
 * </p>
 * 
 * @author Manohar Negi
 * @version 1.0
 * @since 1.0
 * @see
 * Copyright notice
 *
 * Revision History: 
 *
 * Date            By              Version        Comments
 * ---------------------------------------------------------------------------------
 * Aug 31, 2011    Manohar Negi    1.0            Initial Draft
 * Sep 01, 2011    Manohar Negi    1.1            Modified to include more methods
 *
 **/
package com.mani.util;

public class HotmNameFinderTest {

    public static void main(String[] args) {

        /* get the host name for local machine */
        HostNameFinder.getMyHostName();

        /* get the IP for local machine */
        HostNameFinder.getMyIPAddress();

        /* get the host name for localhost */
        HostNameFinder.getHostNameByAdress("localhost");

        /* get the IP for localhost */
        HostNameFinder.getIPByAddress("localhost");

        /* get the host name for www.google.com */
        HostNameFinder.getHostNameByAdress("www.google.com");

        /* get the IP for www.google.com */
        HostNameFinder.getIPByAddress("www.google.com");

    }

}


And here is the output that I got.

Host Name = mani-mac
IP Address = 192.168.2.4
Host Name = localhost
IP Address = 127.0.0.1
Host Name = www.google.com
IP Address = 74.125.236.83

Tuesday, May 1, 2012

Features of Java 7


Initially Java 7 was proposed to have many new features such as
  1. Modularization
  2. Anonymous methods (closures)
  3. Simplifications in generics implementations
  4. Enhanced exception handling
  5. Strings in switch statements
  6. Dynamic languages support
  7. Simplified initialization of collections
  8. Elvis operators
  9. API changes
Out of above listed features a few were dropped from actual release of Java 7 and they are supposed to be released as part of Java 8. And they are 
  1. Anonymous methods (closures)
  2. Simplified initialization of collections
  3. Elvis operators

New features in Java 7
  1. Change in language syntax
    • Constants
      • Binary constants
      • Underscore in numeric constants
    • Strings in switch statement
    • Extended try catch
    • Multi-catch
    • Diamond operator
  2. Better support of dynamic languages
    • New bytecode  instruction
    • New dynamic linkage mechanism
  3. JDBC 4.1
    • try-with-resources statement
    • RowSet 1.1
  4. NIO 2
    • Comes with a set of views
    • New abstract class java.nio.file.Path
    • Notion of metadata
  5. Updates in Swing API
  6. Unicode 6
  7. Updates in concurrency package
  8. Automatic resource closure

Friday, April 20, 2012

Installing Eclipse J2EE Indigo SR2 in Ubuntu 11.10

In this section we will see how to install Eclipse J2EE Indigo .

Installing eclipse
  1. Install .gz file from eclipse web site
  2. I will copy the .gz file to ~/softwares
  3. Unpack the .gz file
    tar -zxf eclipse-jee-indigo-SR2-linux-gtk.tar.gz
    

  4. You will have a new directory "eclipse"
  5. Create desktop shortcut by right clicking eclipse -> Copy To -> Desktop
  6. Launch eclipse from desktop

Thursday, April 19, 2012

Installing Oracle/Sun Java in Ubuntu 11.10

Mostly Linux systems comes with Open JDK. In order to install Sun/Oracle Java, follow the steps below. Please note! you will need sudo access for this. In this section I will install Sun/Oracle Java version 1.6.0_06.

  1. Test for Java version installed. Use command java -version.
  2. sudo add-apt-repository "deb http://us.archive.ubuntu.com/ubuntu/ hardy multiverse"

  3. sudo apt-get update
  4. sudo apt-get install sun-java6-jdk


    Select Ok

    Select Yes
  5. java -version (check the java version installed)
  6. javac -version (check the javac version installed)

In case java is not showing Sun/Oracle JDK as default. You can use below command to set the default version of Java.

  • sudo update-alternatives --config java

Tuesday, April 17, 2012

Ubuntu 11.10 in a VM for Java Developers

Gearing up for serious Java development. From past few weeks I was working on top set up Ubuntu and Java workspace in a virtual machine. Everyone around me is little bit inclined towards Ubuntu, I still don't know why. Before starting how to do so here is the hardware and software I'm working with.


VM On Windows 7 (64 bit)

Hardware details

Laptop: Dell INSPIRON
CPU: Intel Core I3-2330M CPU @ 2.20 GHz
RAM: 4 GB RAM

Software details

OS: Windows 7 (64 bit)
VM: Oracle VirtualBox

VM On Mac OS X Snow Leopard

Hardware details

Laptop: MacBook Pro
CPU: Intel Core I5
RAM: 4 GB RAM

Software details

OS: Snow Leopard
VM: VMWare Fusion


Being a Java developer, I'm mostly interested in installing Git, Sun/Oracle Java, MySQL, Apache ANT, Apache Maven and Eclipse.

Follow below links for installation and setup.
  1. Git - Distributed Version Control System
  2. Java - Installing Sun/Oracle Java
  3. MySQL Server 5.1 and MySQL Workbench 5.2.39
  4. Apache ANT 1.8.2
  5. Apache Maven 3.0.4
  6. Eclipse J2EE Indigo SR2