Sun Java Solaris Communities My SDN Account Join SDN
 
Enterprise Java Technologies Tech Tips

Customizing an ELResolver in JSP 2.1, and Introduction to jMaki

 
In this issue

Welcome to the Enterprise Java Technologies Tech Tips for January 27, 2007. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE).

This issue covers:

These tips were developed using the Java EE 5 SDK. You can download the SDK from the Java EE Downloads page.

You can download the sample archive for Fun With Expression Language in JSP 2.1 tip.

Any use of this code and/or information below is subject to the license terms.

 
Customizing an ELResolver in JSP 2.1
By Kin-man Chung  

Expression language (EL) was first introduced in the JavaServer Pages Standard Tag Library (JSTL) 1.0. The goal was to give developers easy access in a JavaServer Pages (JSP) technology page to application data in beans, arrays, request parameters, and cookies. EL has proven to be very useful in simplifying JSP authoring. For example, a simple line like the following could be used in a JSP page to access data in a bean:

   You have ${cart.itemCount} items in your cart.

The EL expression, ${cart.itemCount} accesses the value of the itemCount property in a bean referenced by the cart variable.

Because of its usefulness, EL was incorporated into JSP 2.0. JavaServer Faces technology 1.0 then adopted a version of EL. Since then, EL has been further extended to allow the setting of bean properties and to enable specifying methods for actions. A unified EL is new in JSP 2.1. It unifies the EL in JSP 2.0 and in JavaServer Faces technology 1.0.

This tip covers a number of new features of the unified EL introduced in JSP 2.1. A sample web application package accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package).

ELContext

One of the new things regarding EL in JSP 2.1 is the ELContext class. The class provides context information that the JSP engine uses to parse and evaluate EL expressions. The JSP container provides a default ELContext for JSP pages. Similarly, the JSF Servlet provides a default ELContext for EL expression evaluation in applications that use JavaServer Faces technology.

An ELContext object contains a reference to three objects that are used in parsing and evaluating EL expressions:

  • FunctionMapper, which is used to resolve EL functions when an EL expression is parsed
  • VariableMapper, which is used to resolve EL variables when an EL expression is parsed.
  • ELResolver, which is used to resolve objects and their properties when an EL expression is evaluated

One of the interesting aspects of ELContext is that it's pluggable. Using the JSP API, you can use a custom ELContext in a JSP page. The ELContext provided by the JSP container contains defaults for the FunctionMapper, VariableMapper, and ELResolver. Though there is usually no need to replace them, you can replace these referenced objects. Let's examine how to use a custom version of an ELResolver.

Using a Custom ELResolver

The August 26, 2006 Tech Tip Extending the Java EE Unified Expression Language with a Custom ELResolver covered how to create and use a custom ELResolver in JavaServer Faces technology. Now let's look at an example that uses a custom ELResolver in a JSP page. The example was originally created by Mark Roth who was the JSP 2.1 co-specification lead. In this example, the custom ELResolver enables screen colors to be specified in an EL expression using various formats, such as:

  • By name: ${Color.MidnightBlue}
  • By RGB values: ${Color[100][250][200]}
  • By hex string: ${ "#191970"}

Here is what the JSP page displays when you run the example:

JSP page display

Before examining the custom ELResolver, let's look at how to plug it into the JSP context. This is done in the ELResolverListener class. You can view the source code for ELResolverListener, as well as for other code examples in this tip, by opening the sample application package that accompanies this tip.

   public class ELResolverListener 
       implements ServletContextListener
   {
       public void contextInitialized(ServletContextEvent evt) {
           ServletContext context = evt.getServletContext();
           JspApplicationContext jspContext = 
             JspFactory.getDefaultFactory().getJspApplicationContext(context);
           jspContext.addELResolver(new ColorELResolver());
       }
       
   }

Notice that to plug the custom ELResolver into the JSP context, you first get the JspApplicationContext from the JspFactory. Then you invoke the JspApplicationContext method addELResolver, passing it an instance of the custom ELResolver. You must do this before the application receives any request.

The container's default ELResolver is actually a CompositeELResolver, which consists of a list of child ELResolvers in the following order:

  1. ImplicitObjectELResolver
  2. Custom ELResolvers
  3. MapELResolver
  4. ListELResolver
  5. ArrayELResolver
  6. BeanELResolver
  7. ScopedAttributeELResolver

During property resolution, the resolvers are queried based on their order in the list. The ImplicitObjectELResolver is always called first so it can't be overridden. But you can override any ELResolver lower in the order, say BeanELResolver or ScopedAttributeELResolver.

Here is part of the code in a custom ELResolver, ColorELResolver. The code handles expressions such as ${Color.blue}. The complete code for ColorELResolver handles additional expression formats.

   public class ColorELResolver extends ELResolver {
      public Object getValue(ELContext context, Object base, 
              Object property)
          throws ELException
     {
          Object result = null;
          if(base == null) {
              // Resolving first variable (e.g. ${Color}).
              String propertyName = (String)property;
              if(propertyName.equals("Color")) {
                  result = new ColorImplicitObject();
                  context.setPropertyResolved(true);
          }
      }
          else if(base instanceof ColorImplicitObject) {
              // Resolving a property on ${Color}
              ColorImplicitObject color = 
                      (ColorImplicitObject)base;
              result = ColorImplicitObject.fromName(colorName);
              context.setPropertyResolved(true);
          }
          return result;
      }
   }

A custom ELResolver must extend javax.el.ELResolver and provide implementations for all of its methods. In this example, the primary focus is the immediate evaluation of EL expressions. Because of that, the custom ELResolver, ColorELResolver, only implements the method getValue, and provides skeletal implementations for other methods.

The method getValue takes three arguments: an ELContext, a base, and a property. ColorELResolver, must handle special combinations of base and property. Note that evaluating an EL expression such as ${Color.blue} requires two trips to the ELResolvers. The first trip resolves the variable Color, in which case the base is null and the property is Color. Here ColorELResolver returns an instance of ColorImplicitObject for the method getValue.

In the second trip, the ELResolvers are again queried, but this time the base is a ColorImplicitObject and the property is the string "blue". Here, the result returned is an instance of ColorRGB representing the blue color. The class ColorImplicitObject contains a table that matches color names with color values, and a method, fromName, that converts color names to color values.

The statement context.setPropertyresolved(true); indicates that the pair (base, property) has been successfully resolved by this ELResolver. This means that it's not necessary to do further resolution in other ELResolvers.

The actual code for ColorELResolver is more complicated than what is shown above, because it has to handle other properties that must be resolved for an ColorImplicitObject. However the basic operation is as described.

A Second Example

Now let's look at a second example of using a custom ELResolver. In this example, the custom ELResolver extends EL to allow the invocation of bean methods. EL functions are restricted to static methods, and MethodExpressions, that is, expressions that refer to a method on an object, cannot be invoked in a JSP page. So if you want to invoke a method on an object, such as a bean method, in a JSP page, you need to use a technique such as the one in this example to do it. Note however that this approach does lead to some awkward syntax, but it does illustrate the extensibility of the EL.

The objective is to allow EL expressions such as the following:

   ${myBean.meth["arg1"]["arg2"]} 

Here, the EL expression invokes the method meth of the bean myBean, passing the method two arguments: arg1 and arg2.

Normally, in processing this expression the BeanResolver would invoke the getter method, getMethod, of myBean. However, because custom ELResolvers are queried before the BeanELResolver, you can use a custom ELResolver to inject the invocation of the method -- that is, if such a method exists. With a custom ELResolver, you can invoke any method in the bean, not only getter methods.

Here is part of the customELResolver, MethodInvocationELResolver:

   public class MethodInvocationELResolver
       extends ELResolver
   {
       public Object getValue(ELContext context, Object base, 
         Object property)
           throws ELException
       {
           ...
           
           ResolvedMethod meth;
           if (base instanceof ResolvedMethod) {
               meth = (ResolvedMethod) base;
               meth.add(property);
               context.setPropertyResolved(true);
               return meth.isReady()? meth.invoke(): meth;
           }
   
           meth = getMethod(base, properties);
           if (meth != null) {
               context.setPropertyResolved(true);
               result = meth.isReady()? meth.invoke(): meth;
               return result;
           }
   
           return null;
       }
       private ResolvedMethod getMethod(
         Object base, Object property) {
           String methodName = property.toString();
           Class beanClass = base.getClass();
           for (Method method: beanClass.getMethods()) {
               if (method.getName().equals(methodName)) {
                   return new ResolvedMethod(method);
               }
            }
            return null;
       }
       
       private static class ResolvedMethod {
               Method method;
               int argumentCount;
               ArrayList<Object> args = new ArrayList<Object>();
       
               public ResolvedMethod(Method method) {
                   this.method = method;
                   argumentCount = 
                     method.getParameterTypes().length;
        }
   
       ...

As usual, the customELResolver extends ELResolver. It also overrides getValue. MethodInvocationELResolver checks to see if the argument property, which is expected to be a String, is a method in the bean, passed as the argument base. If so, and if the method has no arguments, it's immediately invoked. If the method has arguments, MethodInvocationELResolver saves the method information. Saving the method information is necessary because when resolving the pair (myBean, method), the customELresolver has not encountered the arguments. MethodInvocationELResolver can invoke the method only after receiving all the arguments.

Evaluating an EL expression with two arguments, such as ${myBean.meth["arg1"]["arg2"]} requires four trips to MethodInvocationELResolver. Each of them contains a different combination of the pair (base, property) in its getValue method. The customELResolver needs to resolve them all.

To test the customELResolver, the example includes a JSP page, invoke.jsp:

   <jsp:useBean id="map" class="java.util.HashMap"/>

   Adding ("key1", "item1"): ${map.put["key1"]["item1"]} </br>
   Adding ("key2", "item2"): ${map.put["key2"]["item2"]} </br>

   map is ${map}<br/>

The page invokes the method put of a HashMap bean twice. Each time it invokes the method, it passes it two arguments. It then prints the value of the HashMap.

Here is what the JSP page displays when you run the example:

JSP page display #2

For more information about the Unified Expression Language as well as other new features in JSP 2.1, see Web Tier to Go With Java EE 5 : Summary of New Features in JSP 2.1 Technology.

Running the Example

You can run the sample application in any application server that conforms to Java EE 5, such as the application server in the Java EE 5 SDK. You can download the Java EE 5 SDK from the Java EE Downloads page.

  1. Download and unzip the sample application that accompanies this tip. You should see the file ttjan2007el.war.

  2. Then copy the file ttjan2007el.war into
    <install_dir>/domains/domain1/autodeploy, where <install_dir> is the directory in which you installed your application server.

  3. Start the application server.

  4. To run the first example, point you browser to the following URL:
    http://localhost:8080/ttjan2007el/elcolor.jsp
  5. To run the second example, point you browser to the following URL:
    http://locathost:8080/ttjan2007el/invoke.jsp

About the Author

Kin-man Chung is a senior staff engineer at Sun Microsystems. He has worked on code generation and optimizations for the C++ SPARC compiler. More recently, Kin-man has worked on web containers, including Tomcat and GlassFish. He is currently a co-specification lead for JavaServer Pages 2.1 technology.

Introduction to jMaki
By Carla Mott  

jMaki is a lightweight framework for creating Web 2.0 applications using standards-based technologies such as CSS, HTML, and JavaScript. The jMaki framework provides:

  • Template CSS layouts
  • A widget model
  • Client services such as publish/subscribe events to tie widgets together
  • JavaScript action handlers
  • A generic proxy to interact with external RESTful web services

The jMaki framework abstracts much of the JavaScript and CSS by providing defaults for widgets. However it makes the JavaScript and CSS for the widgets easily accessible so a designer or page developer can easily customize the code.

jMaki focuses on the aspects of delivering JavaScript to the client allowing the JavaScript to communicate with server-side technologies in a way that's neutral to the technology. The server-side technologies include PHP, JavaServer Pages (JSP) technology, JavaServer Faces technology, and Phobos.

The term jMaki signifies the concept of a JavaScript wrapper -- the "j" in jMaki is the first letter in JavaScript, and "maki" is Japanese for wrapper. The framework makes available widgets from popular toolkits such as Dojo, Yahoo, Scriptaculous, and Google in way that's familiar to Java technology, PHP, or Phobos developers. It does this by writing wrappers around the widgets in those toolkits.

If you're familiar with using JSP technology, jMaki allows you to include a widget from any of the supported toolkits as a JSP taglib. For example, to start using jMaki, you add the following tag declaration to the top of a JSP page:

   <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>

If you use JavaServer Faces technology, you can include a widget as a JavaServer Faces component. Here's the tag declaration that you add to the top of a JSP page to use widgets as JavaServer Faces components:

   <%@ taglib prefix="a" uri="http://java.sun.com/jmaki-jsf" %>

If you're a PHP developer, you can include a widget as a PHP tag. The PHP declaration looks like this:

   <?php require_once 'Jmaki.php'; ?>

Or if you're a Phobos developer you can include widgets as enterprise components.

jMaki automatically generates the appropriate JavaScript code to render the widgets on the page and wire components together.

In this tip you'll learn some of the basics of the jMaki framework and also see some examples of jMaki in use.

What's In the jMaki Framework?

The jMaki framework includes client components and server components. Let's look at some of these components.

Client Components

One of the most useful client components for developing web applications is layouts. These are templates based on HTML and CSS that you can use to create specific format styles for your application. The jMaki layout gallery shows the jMaki layout templates that are available. All of the templates are plain CSS so you can easily customize them. The layout gallery itself was developed using a customized version of one of the templates.

Another client component is the runtime, which is responsible for bootstrapping widgets and passing arguments from the server runtime. The client runtime component renders the widgets on a page based on the information in tags. You call the client runtime for a widget by adding the ajax custom tag to a page. For example, one of the widgets in jMaki wraps the table widget that's provided in the Dojo toolkit. You can include the Dojo table widget in a JSP page by adding the following tag (the example is shown on multiple lines to fit the width of this page):

   <a:ajax name="dojo.table"
   value="{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']]}" />

The name attribute in the ajax custom tag refers to the widget's name, dojo.table. The value attribute specifies the data for the Dojo table. This is only one of several ways you can provide data for the widget.

If you use PHP, you can include the Dojo table in your page by adding the following PHP call (the example is shown on multiple lines to fit the width of this page):

   <?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']
                ]}");
   ?>   

One more important client component is the widget model, which provides the component model for jMaki widgets. The model specifies three files that comprise a jMaki widget:

  • An HTML template file named component.htm
  • A JavaScript file named component.js
  • A CSS file named component.css

The component.js file specifies the behavior of the widget, and the component.css file specifies the style of the widget's display. These files are provided for each of the widgets packaged with jMaki. Another file, widget.json, is provided for describing a widget so that the widget can be accessed by tools.

If you want to wrap a widget that isn't included with jMaki, you need to create a component.htm, component.js, and component.css file for the widget. The files are recognized by the framework and loaded when the page that contains the widget reference is rendered.

Here's an example of what goes in a component.js file:

  jmaki.namespace("jmaki.widgets.foo.bar");
  jmaki.widgets.foo.bar.Widget = function(wargs) {
     // widget code here    }

The code example shows a constructor for a widget named foo.bar followed by the widget code. All jMaki widgets have a constructor under the jmaki namespace. The jmaki namespace is used to avoid cluttering the JavaScript global namespace. Notice that the widget in this example is in namespace jmaki.foo.bar and is called Widget. The Widget constructor is passed the widget arguments.

jMaki Glue

jMaki provides convenient APIs for performing XMLHttpRequests and other services such as a publish/subscribe mechanism on the client. It provides these services to all widgets as a means of communication. The publish/subscribe mechanism allows a widget to publish an event to a topic. Individual applications can then subscribe to that topic. This mechanism give you a relatively easy way to specify an application's response to an event on a widget. You can see an example of how the publish/subscribe mechanism works in Handling jMaki Widget Events Using the Publish and Subscribe Mechanism.

jMaki Glue is built on top of the publish/subscribe event mechanism. The glue is a powerful feature that allows you to define application behavior and tie widgets together using JavaScript actions when a specific event is published to a topic. An application developer provides the code that is used by the glue feature. The current release of the jMaki framework includes the glue code needed to tie the Yahoo Geocoder to either the Yahoo or Google map widgets.

Server Components

There are two server components in the jMaki framework: the server runtime and a proxy named XmlHttproxy. The server runtime component is responsible for tying the jMaki client runtime to a server runtime such as Java, PHP, or Phobos. The server runtime component tracks and renders all the script and CSS references based on the library type being used. This ensures that script and CSS links are not duplicated. The server runtime makes sure that API keys, such as Google and Yahoo Map keys, are applied when necessary based on a configurable set of keys. The server runtime also renders the HTML templates and serializes data in JavaScript such that each widget instance is provided the proper data.

The XmlHttproxy component allows an Ajax-enabled client to access external services outside the web application domain. It does this by communicating with the services on the client's behalf. In addition, the proxy can perform data conversions so that you can restrict the format of the data from third party services. The proxy allows clients to access RESTful web services such as RSS feeds, the Yahoo Geocoding service, and Flickr image searches. Last, the proxy allows widgets to access services in a uniform way by providing XSL-to-JSON transformations that can be easily customized.

jMaki Examples

Now that you've learned about some of the components in jMaki, let's look at some examples that use a jMaki widget in a web application.

Using the Editor Widget

In the first example, you'll include as a JSP tag handler the Dojo editor widget provided by jMaki. This widget presents a text editor that can be used to create and manipulate documents.

Recall that to use a jMaki widget as a JSP tag handler, you first add an appropriate tag declaration to the top of a JSP page.

   <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>

Then you add the ajax custom tag for the widget in your page.

   <a:ajax id="myeditor" name="dojo.editor" value="Edit me."/>

Your JSP page should also include JavaScript code to show what a user enters into the editor.

   <script type="text/javascript">
   function showEditorContents() {
   var data = jmaki.attributes.get('myeditor').getEditorContent();
   alert("contents=" + data);
   }
   </script>
   <a href="javascript:showEditorContents()">Show Editor</a>

This JavaScript code brings up a window with the contents in the editor that the user added.

All that's left to provide is some surrounding HTML code. Here's the complete code for the application:

   <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>
   <h2>Dojo Editor Test</h2>
   <hr>

   <div style="height:300px">
   <a:ajax id="myeditor" name="dojo.editor" value="Edit me." />
   </div>

   <script type="text/javascript">
   function showEditorContents() {
   var data = jmaki.attributes.get('myeditor').getValue();
   alert("contents=" + data);
   }

   </script>
   <a href="javascript:showEditorContents()">
      Show Editor Contents</a>

You can also view this code by clicking the "Source" link for the Editor widget in the jMaki Widget Gallery. If you click on the "See Live" link you can run the application.

Here's what you should initially see when you click on "See Live":

Dojo Editor Example #1

Enter some text in the editor widget and see what happens.

Dojo Editor Example #2

Using jMaki Glue

The second example uses the jMaki glue code to tie together the Yahoo Geocoder and Google map widgets on a JSP page.

   <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>

      <h2>Maps Page</h2>
      <hr>

      <div style="height:300px">
      <a:ajax name="yahoo.geocoder" service="/xhp" />

      <a:ajax name="google.map" 
         args="{
            centerLat:37.39316,
            centerLong:-121.947333700,
           }"/>

      </div>

If you enter a location in the Geocoder widget, it returns longitude and latitude values that are picked up by the Google map widget and plotted.

Maps page example

Summary

You can use jMaki to add Web 2.0 functionality to your existing applications or to create new applications. Take advantage of the features you need. Currently a Beta version of jMaki is available for download. It contains all the features discussed in this tip. Also, the jMaki page has documentation, blogs, and a screencast to help you get started. For more information on jMaki see the article New Technologies for Ajax and Web Application Development: Project jMaki, and the blog entry Building web 2.0 apps with jMaki.

About the Author

Carla Mott is a contributor on Project jMaki. She is also an editor on The Aquarium webblog, a Java Enterprise Community leader on java.net and a committer on Dojo, an open-source JavaScript toolkit. Previously, she was a project owner for Project GlassFish where she helped to open source Sun's application server and to build the GlassFish community.

Correction to Last Month's Tip

In the December 16, 2006 Tech Tip Pitfalls in Constructing Java Persistence Query Language Queries the section "Using a LIKE Expression With an Escape Character" included the following sentence:

In this case, the expression is true if the value of customer.name is "fore" or "forego" but not if it's "four" or "f_rst".

The sentence should be:

In this case, the expression is true if the value of customer.name is "fore" or "forego" but not if it's "four".

 
2007 JavaOne Conference Registration is Live

Register today for the JavaOne conference and save $200. The program is new and expanded. Check the 2007 JavaOne Conference page for details.

 
Java Application Platform SDK Update 2 Now Available

Java Application Platform SDK Update 2 supports the newly released Java SE 6 and introduces a new runtime component, Portlet Container 1.0 Beta, to develop and test Java portlets.

 
Developer Assistance

Need programming advice on Java EE? Try Developer Expert Assistance.

 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.