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