Sunday, October 30, 2011

HTML5 Canvas element has arrived

Good news: HTML5 has arrived (thank you in part to Apple).  We are no longer limited to using applet, object, svg or img tags to present dynamic visual content.  We can use the canvas element in addition to the geolocation and storage functionality.
As a first example, i have of course written a very rudimentary version of John Horton Conways' "Game of Life".  The William Gosper "glider gun" is an excellent proof of concept.
The following link will take you to a pure HTML5 document that renders the glider gun sequence. You will need the latest Android 2.x, Chrome, IE9, Firefox or Opera browser to see the canvas element.

Cellular Automata simulation in HTML5 using the canvas element
http://99.240.95.213:7101/radar/html5.xhtml (IE9, Chrome and (android based Firefox))
http://99.240.95.213:7101/radar/html5.html (android 2.x base browser)
http://99.240.95.213:7101/collatz/faces/index.xhtml
http://99.240.95.213:7101/collatz/ajaxclient.jsp

Cellular Automata simulation in a Java SE Applet
http://www.objectivej.com/inorganiclife/experiments/life/LifeAnimApplet.html

Cellular Automata simulation in a Wikipedia animated GIF
http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life

Sunday, May 8, 2011

Thread Safety

The following Java API is known to be not thread safe.

SimpleDateFormat is not thread safe
The SimpleDateFormat implementation of DateFormat is not thread safe by design. If you wish to use this API you have several architectures to choose from in your application.
Use sychronization in your implementation - not advisable since this will queue your requests
Use InheritedThreadLocal storage by using get/set to use an instance of SimpleDateFormat per thread - recommended for environments running in thread pools - like in EE application servers.
Here we use an InheritedThreadLocal map entry to store an instance of the DateFormat object for each thread. See p.45 section 3.3 Thread confinement of "Java Concurrency in Practice" by Brian Goetz. Also, do not set this field before starting this thread or the ThreadLocal map value will be cleared to initialValue()
Use a pool of SimpleDateFormat instances - not in this case.

I will use the ThreadLocal map to store a unique instance for each thread of my running application. However, any ThreadLocal will not do - as I may be running in a pooled environment - like in an application server container like WebLogic, Tomcat, OC4J, WebSphere, JBoss, Spring tc, Spring dm, Geronimo and even JRun. In this case we need to use the subclass InheritableThreadLocal. When child threads are created, these threads will get a reference to their parent thread's ThreadLocal value by default. We will also want to override the InheritableThreadLocal.childValue() function to clone the parent value so that we are fully threads safe. Doing so will ensure thread safety whether ThreadLocal variables are set before or after thread creation.

private static final InheritableThreadLocal format = new InheritableThreadLocal() {
    @Override
    public DateFormat initialValue() {
      // This default value will get replaced by non-default constructors
      return new SimpleDateFormat(DefaultFormat);
    }
    @Override
    // All child threads must clone the formatter and not share the parent formatter by default
    protected DateFormat childValue(DateFormat parentValue) {
     // Object.clone() is a shallow copy, however DateFormat.clone() replicates mutable fields
        return (DateFormat) parentValue.clone();
    }

  };

SAXParser in JDOM SAXBuilder is not thread safe
The parser in SAXBuilder must be set to not be reused in your constructor.
See the following API
http://www.jdom.org/docs/apidocs/org/jdom/input/SAXBuilder.html#setReuseParser(boolean)

aBuilder = new SAXBuilder();
  aBuilder.setReuseParser(false);

Monday, January 10, 2011

Multiple Instruction Multiple Data

    We need to start thinking about how existing and future Java API's will work with all the combinations of multiple data sets, multiple virtual machines, multiple physical hardware devices and multiple clients.  The issues surround how we handle concurrent access, availability, synchronization, distribution and sharing of all these resources.
I1: Data sharing:
  • shared database (old)
  • shared schema (new)
References:

Friday, November 5, 2010

TODO

  1. investigate the excellent article from Microsoft Research on multinenancy as part of most SaaS http://msdn.microsoft.com/en-us/library/aa479086.aspx implementations 
  2. Add applications to live application server
    http://99.240.95.213/radar/html5.xhtml
  3. MapReduce (via Apache Hadoop) on one of my clusters or one of my Amazon EC2 AWS instances using Amazon Elastic MapReduce as a wrapper for Hadoop or on the upcoming Oracle cloud service - see http://www.youtube.com/watch?v=Wu9HMM9l3Go
  4. Project Fortress from the programming languages lab of very honoured new coworker Guy Steele !
  5. Full review of historical architectures MIT Cosmic Cube (MIMD), CM-2 (SIMD) and Illiac IV (SIMD) and how they influence the KiloCore prototype
  6. JVM Bytecode spec section and Proxy.getNewInstance()
  7. Finish review of BeMicro's board for the 22k Altera FPGA
  8. JRebel for ZeroTurnaround
  9. Three phase commit protocol for databases
  10. Spring Roo, Insight and AOP
  11. Java needs an automatic for loop parallelization API like other languages like .NET
  12. .NET JMS client for WebLogic http://download.oracle.com/docs/cd/E12840_01/wls/docs103/jms_dotnet/overview.html
Links
http://jre.sfbay.sun.com/java/re/jdk/6u24/promoted/fcs/b07/licenseebundles/jdk6_24/
Inform Ed Ort of Oracle that the JAX RS example on the main Java EE site does not compile (it was written back in Dec 2009 when the spec first came out)
http://www.oracle.com/technetwork/articles/javaee/javaee6overview-141808.html#jaxrs

For example, the following imports are invalid and have syntax errors
import javax.ws.rs.Get;
   import javax.ws.rs.Post;
   import javax.ws.rs.core UriInfo;
These should be
import javax.ws.rs.GET;
   import javax.ws.rs.POST;
   import javax.ws.rs.core.UriInfo;
In order to match their use as annotations later on.
I try to copy only directly from my Eclipse or NetBeans IDE - and not edit code directly on a blog - so this does not happen.

Hardware:
  1. 256 bit ALU using PB8X-32
  2. Vector ALU pipeline
  3. 128 bit universal bidirectional shift register
  4. Toroidal grid parallel processor (Propeller PA8X-32 or XMOS G4
  5. Ambric like mesh processor where each PU executes a single Java Object thread (so a kilocore represents 1024 pooled object instances)
  6. Data flow machine where each processing unit node represents a scalar operation or data element in a RPN or Forth like flow

Tuesday, November 2, 2010

Accessing multiple remote EJB 3.0 Session Beans via JNDI in an SE Client - Experiment

Update: This project is superceeded by the Collatz Distributed Java EE Application Tutorial
Note: This code will run on both a Java SE client or an EE container like Oracle WebLogic.

Here as a preparation for using or understanding how a distributed java application runs under a shared level 2 cache before we actually use one. We can develop our own naive cache by referencing ''session beans'' on one or more WebLogic server applications acting as a distributed application and possibly using our own HashMap - old school and unnecessary but part of essential learning.




WebLogic RMI Client Configuration
Here we have a very simple JNDI client that acts as a hello world distributed host and manages remote session beans on two physical WebLogic servers.
The JNDI protocol uses t3
The JNDI factory class for WebLogic is weblogic.jndi.WLInitialContextFactory
The default JNDI name for you SSB can be redifined via the mappedName annotation to ejb/Node with the corresponding remoteReference as java:comp/env/ejb/Node
The key to using an EJB 3.0 session bean remotely is to narrow the Object to the bean interface.
The following stateful session bean goes into an EAR and is deployed on each EE container in your cluster.

@Stateful(mappedName="ejb/Node")
@Local
public class Node implements NodeRemote, NodeLocal {
    private int transition;
    private int state;        
    public void setState(int aState) {
        System.out.println("_Distributed: new state: " + aState);
        state = aState;
    }
    public int getState() { return state;  }
}
This goes on your SE client.

public class JNDIClient {
    public static final List<String serverNames = new ArrayList<String>();
    private Map<String, Hashtable<String, String>> contextMap = new HashMap<String, Hashtable<String, String>>();
    private Map<String, Context> rmiContextMap = new HashMap<String, Context>();    
    private Map<String, NodeRemote> remoteObjects = new HashMap<String, NodeRemote>();    
    private Map<String, Integer> stateToSet = new HashMap<String, Integer>();
    private static Map<String, String>  serverIPMap = new HashMap<String, String>();
    // How many processors are available (real + hyperthreaded)
    private static int availableProcessors; 
    private static final String CONTEXT_FACTORY_NAME = "weblogic.jndi.WLInitialContextFactory";
    private static final String SESSION_BEAN_REMOTE_NAME = "ejb/Node#org.eclipse.persistence.example.distributed.NodeRemote"; 
    //private String sessionBeanRemoteName = "java:comp/env/ejb/Node"; // EE only
    //private String sessionBeanRemoteName = "org_eclipse_persistence_example_distributed_ClientEARorg_eclipse_persistence_example_distributed_ClientEJB_jarNode_Home" ;

    /**
     * For each server add the name key and corresponding RMI URL
     */
    static {
        // Beowulf5 on Cat6 1Gb/Sec
        serverNames.add("beowulf5");
        serverIPMap.put("beowulf5", "t3://192.168.0.165:7001");
        // Beowulf6 on Cat6 1Gb/Sec
        serverNames.add("beowulf6");
        serverIPMap.put("beowulf6", "t3://192.168.0.166:7001");
        availableProcessors = Runtime.getRuntime().availableProcessors();
    }

    public void connect() {
        /**
         * Note: only import weblogic.jar and naming.jar
         */
        // For JNDI we are forced to use Hashtable instead of HashMap
        // populate the hashtables        
        for(String aServer : serverNames) {
            Hashtable aTable =  new Hashtable();
            contextMap.put(aServer,aTable);
            aTable.put(Context.INITIAL_CONTEXT_FACTORY,CONTEXT_FACTORY_NAME);
            aTable.put(Context.PROVIDER_URL, serverIPMap.get(aServer));
        }
        System.out.println("Available Processors on this System: " + availableProcessors);
        /**
         * Setup and connect to RMI Objects
         */
        try {            
            // Establish RMI connections to the session beans
            for(String aServer : serverNames) {
                Context aContext = new InitialContext(contextMap.get(aServer));
                rmiContextMap.put(aServer, aContext);
                System.out.println("Context for " + aServer + " : " + aContext);
                // For qualified name look for weblogic log "EJB Deployed EJB with JNDI name"
                Object aRemoteReference = aContext.lookup(SESSION_BEAN_REMOTE_NAME);        
                System.out.println("Remote Object: " + aRemoteReference);        
                NodeRemote aNode = (NodeRemote) PortableRemoteObject.narrow(aRemoteReference, NodeRemote.class);
                remoteObjects.put(aServer, aNode);
                System.out.println("Narrowed Session Bean: " + aNode);        
                // initialize state list
                stateToSet.put(aServer, new Integer(0));
            }
            
            NodeRemote aNode;
            StringBuffer aBuffer = new StringBuffer();           
            // Endlessly generate RMI requests
            for(;;) {
                // Send messages to entire grid in parallel
                /**
                 * Issue: One JVM halt will affect the entire distributed app.
                 */
                for(String remoteServer : remoteObjects.keySet()) {
                    aNode = remoteObjects.get(remoteServer);
                    // increment server's pending state
                    stateToSet.put(remoteServer, stateToSet.get(remoteServer).intValue() + 1);
                    try {
                        aNode.setState(stateToSet.get(remoteServer));
                        aBuffer = new StringBuffer("State from: ");
                        aBuffer.append(remoteServer);
                        aBuffer.append(" = ");
                        aBuffer.append(aNode.getState());                   
                        System.out.println(aBuffer.toString());
                    } catch (EJBException e) {
                        //  weblogic.transaction.internal.TimedOutException: Transaction timed out after 29 seconds 
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        JNDIClient client = new JNDIClient();
        client.connect();
    }
}


The key point is to rename your session bean and reference it by name#application.

Java EE Stateless Session Bean

@Stateless(mappedName = "ejb/CollatzFacade")
public class CollatzFacade implements CollatzFacadeRemote, CollatzFacadeLocal {
Java SE Client
    private static final String SESSION_BEAN_REMOTE_NAME = 
      "ejb/CollatzFacade#org.eclipse.persistence.example.distributed.collatz.business.CollatzFacadeRemote"; 




GlassFish 3.1 and Remote EJB clients
GlassFish 3.1 no longer ships with the non-OSGI gf-client.jar, however the actual OSGI gf-client-module.jar that the manifest in gf-client wraps is still in the modules directory.
see:
http://java.net/jira/browse/GLASSFISH-13295

GlassFish 3.0.1 Results:
You don't need to specify the HashTable parameter for the InitialContext connection for GlassFish.

run:
Context for xps435 : javax.naming.InitialContext@c8f6f8
Feb 6, 2011 6:53:18 PM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates
INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate
Remote Object: org.dataparallel.collatz.business._CollatzFacadeRemote_Wrapper@498cb673
Narrowed Session Bean: org.dataparallel.collatz.business._CollatzFacadeRemote_Wrapper@498cb673