XmlBlaster Logo

REQUIREMENT

client.javascript.rhino

XmlBlaster Logo


Type NEW
Priority LOW
Status CLOSED
Topic XmlBlaster can be easly implemented in javascript code making use of the LiveConnect feature of the Rhino javascript interpreter (embedding of java code into javascript). The advantage of using this technology is that you can use which protocol you whish to communicate with xmlBlaster.
Des
cription
You can use the java I_XmlBlasterAccess class as you where programming in java. There is an implementation of the I_Callback Interface called org.xmlBlaster.client.JavascriptCallback which can be instantiated and passed when logging in. Whenever a message corresponds to a subscription, the update method is called. The update method of JavascriptCallback does invoke a javascript update function which you must provide. The signature of such method is currently the following:
      function update(sessionId, key, content, qos) {
        ....
        return ...
      }
      
where the types for the arguments passed are the same as for java with the only exception of the content which currently is a String (due to problems in interpreting byte[].

An example how it can be used with SVG is xmlBlaster's SVG internet chess.

Example
Javascript
/**
 * xmlBlaster/demo/javaclients/svg/rhino/chessRhino.svg
 *
 * This example is a Chess game where the GUI is an SVG document which can be opened
 * in a browser.
 * Since this example makes use of the LiveConnect techology which is implemented in
 * Rhino (http://www.mozilla.org)
 * it can only used in browsers which use this interpreter.
 * It has been tested in batik (http://xml.apache.org).
 *
 * @see 
 *   http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.javascript.rhino.html
 * @see xmlBlaster/demo/javaclients/svg/rhino/README how to invoke
 */

/**
 * This is the way to import packages into the Rhino Javascript Interpreter
 */
importPackage(java.awt);
importPackage(Packages.org.xmlBlaster.client);
importPackage(Packages.org.xmlBlaster.client.qos);
importPackage(Packages.org.xmlBlaster.client.protocol);
importPackage(Packages.org.xmlBlaster.engine.helper);
importPackage(Packages.org.xmlBlaster.util);


   var x0  = 0; // the x coordinate of the first point (used to calculate the movement)
   var y0  = 0; // the y coordinate ...
   var doc;     // this svg document 
   var currentElement // the element which has been selected.
   var xmlBlaster; // the connection object used to communicate with xmlBlaster
   var ME = "chessRhino.svg";
   var glob;    // the 'stack' (local data) of one client connection
   var log;     // log to file or console


   
   /**
    * The function which returns a generated user name which should be unique within
    * the same xmlBlaster server.
    */
   function getUser() {
      return System.getProperty("user.name") + System.currentTimeMillis();
   }
   

   /**
    * This function has been added to force batik to update.
    * Without it the screen does not update, probably because
    * batik only updates when an event has been fired
    * (xmlBlaster updates come in asynchroneously and do not generate a dom event).
    */
   function fireClickEvent() {
     var evt = doc.createEvent("MouseEvents");
     evt.initEvent("click", true, true);

     var el = doc.getElementById("0");
     el.dispatchEvent(evt);
   }


   /**
    * This is the method which is invoked by the XmlBlaster object when
    * a message matches a subscription
    */
   function update(loginName, key, content, qos) {
      var root = Xparse(new String(content));
      var element = root.contents[0];
      var id = element.contents[0].contents[0].value;
      log.info(ME, "Receiving chess move " + id);
      var transform = element.contents[1].contents[0].value;
      var el = doc.getElementById(id);
      el.setAttribute("transform", transform);

      // hack to update the screen in batik ...
      setTimeout('fireClickEvent()', 1);
      return "";
   }
  

   /**
    * This helper function builds the string to use as the 'translate' attribute.
    * It is this attribute which makes the element move.
    * If such an attribute does not exist, it is added, otherwise it is replaced.
    */
   function createTranslateAttribute(element, dx, dy) {
      var buf = element.getAttribute("transform");  // e.g. 'translate(150,300)'
      var pos = buf.indexOf("translate(");
      var x   = dx;
      var y   = dy;
   
      if (pos > -1) {
         buf = buf.substring(pos+10, buf.length()-1);  // e.g. '150,300'
         var A = new Array();
         A = buf.split(',');
         x += parseInt(A[0], 10);
         y += parseInt(A[1], 10);
      }
      var result = "translate(" + x + "," + y + ")";
      log.info(ME, "createTranslateAttribute() '" + buf + "' -> '" + result + "'");
      return result;
   }
  
  
   /**
    * A helper function build the xml string to send as to xmlBlaster as the
    * content of the message.
    */
   function toXml(id, transform) {
      var content = "<chess><id>" + id + "</id><transform>" +
                    transform + "</transform></chess>";
      return content;
   }
        

   /**
    * Called when opening this document, this function establishes a connection to
    * xmlBlaster, makes a login and a subscription to the messages it is insterested in.
    * <br />
    * It currently connects on the localhost.
    * You could easly change this by making it read the System properties, e.g.
    * <pre>
    * java -Djava.security.policy=${XMLBLASTER_HOME}/config/xmlBlaster.policy
    *      -Dprotocol=SOCKET -Ddispatch/connection/plugin/socket/hostname=myServer
    *       org.apache.batik.apps.svgbrowser.Main
    *       $XMLBLASTER_HOME/demo/javaclients/svg/rhino/chessRhino.svg
    * </pre>
    */
   function doInit(evt) { 
      doc = evt.target.ownerDocument;

      // you can set here the command line to pass to I_XmlBlasterAccess, e.g.
      var args = new Array();
      //args.push("-bootstrapHostname");        // If you use CORBA
      //args.push("myServer.myCompany.com");    // try "server.xmlBlaster.org"
      args.push("-protocol");
      args.push("SOCKET");
      //args.push("-dispatch/connection/plugin/socket/hostname");
      //args.push("217.83.166.225");
      args.push("-dispatch/connection/plugin/socket/port");
      args.push(new String(7607));
      
      xmlBlaster = new XmlBlasterAccess(args);
      
      glob = xmlBlaster.getGlobal();
      log = glob.getLog("svg");
      var connectQos = new ConnectQos(glob, getUser(), "secret");

      xmlBlaster.connect(connectQos, new JavascriptCallback(this));

      var key = new String("<key oid='' queryType='XPATH'>//chess</key>");
      var qos = new String("<qos/>");
      xmlBlaster.subscribe(key, qos);

      log.info(ME, "Connected to xmlBlaster server");
   }
    

   function shutdown(evt) { 
      var qos = new DisconnectQos(glob);
      xmlBlaster.disconnect(qos);
      glob.shutdown();
      xmlBlaster = null;
      glob = null;
      log.info(ME, "xmlBlaster connection closed");
   }


   /**
    * sets the starting point for the movement of the elment.
    */
   function setStartPosition(evt) {
      x0 = evt.getClientX();
      y0 = evt.getClientY();
      currentElement = evt.target;
   }
  
  
   /**
    * Calculates the movement and then publishes this information to xmlBlaster.
    * Note that it currently does only calculate movements based on the original
    * size of the document. In other words, if you resize the browser, 
    * you will get the wrong size of the movements.
    */
   function movePoint(evt) {
      if (currentElement == null) {
         return; // click on empty field
      }
      var dx = evt.getClientX() - x0;
      var dy = evt.getClientY() - y0;
          
      //   var id = currentElement.getAttribute("id");
      // the next lines are a workaround for the bug in batik.
      var id = currentElement.getAttribute("id") + "A"; // workaround for the Bug ?
      log.info(ME, "movePoint() -> Moving chess figure " + id);
      currentElement = doc.getElementById(id);
      // end of the bugfix

      var transform = createTranslateAttribute(currentElement, dx, dy);
      var content = new String(toXml(id, transform));
      var key = "<key oid=\'" +  id + "\'><chess>some chess name</chess></key>";
      var qos = "<qos></qos>";
     
      messageUnit = new MsgUnit(glob, key, content, qos);
      xmlBlaster.publish(messageUnit);

      currentElement = null;
   }
      
   // ... SVG markup ommitted, see chessRhino.svg

The above example is an excerpt from xmlBlaster/demo/javaclients/svg/rhino/chessRhino.svg.

To start this demo do following

  1. Start a session of the xmlBlaster server (the chessRhino.svg is configured for the localhost. If you use an other host, please change chessRhino.svg) by invoking
       java org.xmlBlaster.Main
    
  2. On another terminal start the SVG browser from batik by invoking
       java -Djava.security.policy=${XMLBLASTER_HOME}/config/xmlBlaster.policy 
            org.apache.batik.apps.svgbrowser.Main 
            $XMLBLASTER_HOME/demo/javaclients/svg/rhino/chessRhino.svg
    
    This loads already the chess game.
  3. Start another SVG browser on another terminal as you did in 2) and then you can start to play chess.

Performance

To test the performance you can start another client which randomly moves around the chess pieces. This can be done by invoking:

   java javaclients.svg.rhino.ChessMover -interval 500
      

where 30 here would be the number of milliseconds the application waits between the movement of each piece.

Configure

NOTE: Configuration parameters are specified on command line (-someValue 17) or in the xmlBlaster.properties file (someValue=17). See requirement "util.property" for details.
Columns named Impl tells you if the feature is implemented.
Columns named Hot tells you if the configuration is changeable in hot operation.

Todo
      Pass byte[] objects to the update method.
   
See API org.xmlBlaster.client.JavascriptCallback
See http://www.xmlBlaster.org/xmlBlaster/demo/javaclients/svg/rhino/README
See SVG chess screenshot
Testcase Batik runs fine, see xmlBlaster/demo/javaclients/svg/rhino/chessRhino.svg

This page is generated from the requirement XML file xmlBlaster/doc/requirements/client.javascript.rhino.xml

Back to overview