Wednesday, February 20, 2013

Prefered way for referencing Beans from Java (updated 21-02)

When working in XPages SSJS (Server Side Javascript) it is very easy to reference your Managed Beans. Say you want to print the name of the user to the console and have a bean named User with a method getUsername(), you simply call:
print(User.getUsername());
In Java it is not quite that easy, you have to dig a lot deaper to reach the bean. Examples on how to to this are readily available on the internet, copy/paste one in a Utils class and you end up with something like this:
package nl.defrog;

import javax.faces.context.FacesContext;

public class Utils {
    public static Object getVariableValue(String varName) {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().getVariableResolver().resolveVariable(context, varName);
    }
}
Still want to print the name of the current user to the console? Call:
UserBean userBean = (UserBean) Utils.getVariableValue(UserBean.BEAN_NAME);
System.out.println(userBean.getUsername());
It’s quite a bit of code for just being able to get to the username.
PS: See what I did with the name of the bean? I stored it as the constant BEAN_NAME in the UserBean and made it publicly available. See below for the final version of the code.

Singleton pattern

To clean things up I’m following something common from the Singleton pattern.
A Singleton is a Java class of which only one instance will ever exist in the entire JVM. You cannot simply instantiate a new instance of the class by calling the constructor, you have to call the static method getInstance() on the class to get a handle to the object (that’s the relevant variant for this case, there are other ways).
This sounds a bit like a bean, where we don’t want to instantiate a new object, but want to retrieve the existing Managed Bean from either scope (application, session, view, request).

getInstance() on a Bean

To get the instance of the bean that’s already in a scope (or have it instantiated at the first access) we add a getInstance() method to the bean. This method will call the getVariableValue() method from the Utils class shown above and have it return the bean we’re looking for in the correct type.
See the complete UserBean below.
package nl.defrog.beans;

import nl.defrog.Utils;

import java.io.Serializable;

public class UserBean implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final String BEAN_NAME = "User";
    private String username;

    public UserBean() {

    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public static UserBean getInstance(String beanName) {
        return (UserBean) Utils.getVariableValue(beanName);
    }
 
    public static UserBean getInstance() {
        return getInstance(BEAN_NAME);
    }
}
Now if we want to print the name of the current user to the console, all it takes is a simple:
System.out.println(UserBean.getInstance().getUsername());
If you want to keep the bean around, you could call:
UserBean userBean = UserBean.getInstance();
Nice and clean, isn’t it? I thought so.
Happy hacking!

Updated 21-02-2013 12:30
As per Tim's suggestion (see comments) I've overloaded the getInstance() method so you can provide a bean name when calling the method. This is handy when you have multiple beans using the same Java class.

Now also available on XSnippets.

Sunday, February 17, 2013

Inline HTML vs. Components, the showdown

The last few days there was a bit of discussion in the XPages community on using inline HTML in XPages versus components. So whether you should write <div>My little div</div> (inline HTML) or <xp:div>My little div</xp:div> (component).

Paul Withers wrote a very nice blog (HTML or XPage Component) explaining what happens behind the scenes when you save your XPage. Read the blog if you haven’t already, you won’t regret it! To summarize: the XPage’s XML is converted to Java and, compared to the XPage with inline HTML, for the XPage with components less Java code is generated. Great, but Paul doesn’t explain whether that’s a plus or not.

The next day there’s a follow up blog by Tim Tripcony titled Passthru vs. component - my perspective. Tim dives deeper into the internals and provides even more insight into what happens behind the scenes. Again, read the blog! The bottom line: it might be that inline HTML produces more Java code, but the classes involved are less complex and quite likely rendering them will take a bit more effort and time.

The showdown

So when using components there’s less Java code to be generated, but the rendering of the components will quite likely take a bit more time. How much, is it a significant disadvantage? And additionally, how much do you loose in performance when you chose xp:panel over the dedicated components like for instance xp:div.

For the test I’ve created an XPage with three repeaters. Each repeater will run 10.000 times and create the HTML equivalent of div.myClass>span>table>tr>td*2 (Emmet). The first one will use the dedicated components, the second one generic panel components and the third will use inline HTML. For each repeater I will measure how long it takes to run it.

Note: the HTML output will be hidden with a style “display: none;”, to keep things readable in the browser. As this is a client-side-only setting, it will not affect the outcome of the test.

Running the test page (for the code, see below) 10 times and averaging the numbers gives the following outcome:

Run time for repeater
Inline HTML 132ms
Components 226ms + 94ms
Panels 283ms + 57ms
Average from 10 runs

So, when you have a repeater that runs 10,000 (ten thousand) times, and you create 6 nested components on each run, you loose 94ms in total on components compared to using inline HTML. For using panels there’s an extra cost of 57ms.

The positive thing to take away from this is that it really doesn’t matter, speed-wise, if you use inline HTML or XPages components (incl. panels). Which of the two to use depends on a) your own personal preference and b) whether you need the use the extra functionality the XP components provide.

A caveat

The test I did is a bit primitive and doesn’t represent something you’d do in The Real World(™). If you look at the code below, you’ll find a disabled xp:text component. In one of the td’s the current line number is printed. If I enable that and re-run the test you get a slightly different outcome:

Run time for repeater
Inline HTML 320ms
Components 482ms + 162ms
Average from 10 runs

Interestingly the difference in the time it takes to render the HTML increases. I’m not sure why, but at least it gives a hint that the first test is a bit too simplistic to provide real world guidance. Your mileage may vary.

The code for the test XPage

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">
    <xp:this.dataContexts>
        <xp:dataContext var="manyNumbers">
            <xp:this.value><![CDATA[${javascript:
var numbers = [];
for (var i = 0; i < 10000; i++)
    numbers.push(i);
return numbers;
}]]></xp:this.value>
        </xp:dataContext>
    </xp:this.dataContexts>

    <xp:text escape="true" id="computedField1" value="#{javascript:start = new Date(); return '';}"></xp:text>

    <xp:repeat id="repeat1" rows="#{javascript:manyNumbers.length}" var="number" value="#{manyNumbers}" style="display: none;">
        <xp:div styleClass="myDiv">
            <xp:span>
                <xp:table>
                    <xp:tr>
                        <xp:td>Number</xp:td>
                        <xp:td>
                            <!--<xp:text escape="true" value="#{number}"></xp:text>-->
                        </xp:td>
                    </xp:tr>
                </xp:table>
            </xp:span>
        </xp:div>
    </xp:repeat>

    Repeat with components:&#160;
    <xp:text escape="true" id="computedField2" value="#{javascript:var now = new Date(); now.getTime() - start.getTime();}">
        <xp:this.converter>
            <xp:convertNumber type="number" integerOnly="true"></xp:convertNumber>
        </xp:this.converter>
    </xp:text>
    ms

    <br />

    <xp:text escape="true" id="computedField3" value="#{javascript:start = new Date(); return '';}"></xp:text>

    <xp:repeat id="repeat3" rows="#{javascript:manyNumbers.length}" var="number" value="#{manyNumbers}" style="display: none;">
        <xp:panel tagName="div" styleClass="myDiv">
            <xp:panel tagName="span">
                <xp:panel tagName="table">
                    <xp:panel tagName="tr">
                        <xp:panel tagName="td">Number</xp:panel>
                        <xp:panel tagName="td">
                            <!--<xp:text escape="true" value="#{number}"></xp:text>-->
                        </xp:panel>
                    </xp:panel>
                </xp:panel>
            </xp:panel>
        </xp:panel>
    </xp:repeat>

    Repeat with panels:&#160;
    <xp:text escape="true" id="computedField5" value="#{javascript:var now = new Date(); now.getTime() - start.getTime();}">
        <xp:this.converter>
            <xp:convertNumber type="number" integerOnly="true"></xp:convertNumber>
        </xp:this.converter>
    </xp:text>
    ms

    <br />

    <xp:text escape="true" id="computedField4" value="#{javascript:start = new Date(); return '';}"></xp:text>

    <xp:repeat id="repeat2" rows="#{javascript:manyNumbers.length}" var="number" value="#{manyNumbers}" style="display: none;">
        <div class="myDiv">
            <span>
                <table>
                    <tr>
                        <td>Number</td>
                        <td>
                            <!--<xp:text escape="true" value="#{number}"></xp:text>-->
                        </td>
                    </tr>
                </table>
            </span>
        </div>
    </xp:repeat>

    Repeat with inline HTML:&#160;
    <xp:text escape="true" id="computedField6" value="#{javascript:var now = new Date(); now.getTime() - start.getTime();}">
        <xp:this.converter>
            <xp:convertNumber type="number" integerOnly="true"></xp:convertNumber>
        </xp:this.converter>
    </xp:text>
    ms

</xp:view>

Thursday, January 17, 2013

Be careful feeding the ResponseWriter, use big bites

Earlier this week I got bitten by one of the consequences of writing JavaScript code in a Java environment. There are some things you need to be aware of and I for one was not.

In this case: the XPages run-time can't always determine what the type is of the JavaScript value you're feeding to a Java method. It can be problematic with single position values, either a string or a number. Is it a char, a String or an int?

What's happening? Consider the following XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var writer = facesContext.getResponseWriter();

writer.write("abc");
writer.write("a"); /* BOOM!! */

writer.endDocument();
}]]></xp:this.afterRenderResponse>
</xp:view>

You would expect this XPage to output abca, but it doesn't. It will output abc and at the same time show the following error on the Domino server's console:

HTTP JVM: com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing JavaScript action expression

Changing the "a" to something with two characters fixed the error and gave the expected output. But feeding it the number 0 (which was my original problem) did not. 12 on the other hand was fine.

If course, this had to be a bug, so I send a nice little report to Paul Hannan. Unfortunately it's not (so much for street credibility points), and Martin Donnelly explains why:
The com.sun.faces.renderkit.html_basic.HtmlResponseWriter class has overloaded write() methods - like this:
void write(char)   
void write(char[], int, int)   
void write(int)   
void write(String)   
void write(String, int, int)

For writer.write("g"); the engine does not know whether to call void write(char) or void write(String) on the Java side.

This is a general JavaScript to Java issue, as there is no JavaScript character type so we cannot be type-explicit on the SSJS calling side.

To pass in a single character to the writer class that you either:
a) find a non-ambiguous version of a write method and force that to be called,
b) declare the var as an explicit Java type and pass that in

Both are shown here:


var writer = facesContext.getResponseWriter();
writer.write("abc");
writer.write("gh");
//writer.write("g"); //nope
// This will work ...
writer.write("z",0,1);
// So will this ...
var r = new java.lang.Character('r');
writer.write(r);
writer.endDocument();

This problem can happen easily when you're creating an XAgent. Be careful what you feed the writer.write(). If you're not, you might get some hard to debug errors.

Happy hacking!

Thursday, January 10, 2013

Slides for "On REST and Beans"

Last month I did a presentation called "On REST and Beans" on the Dutch XPages & Beer event. It was my first ever presentation on a technical subject and I felt quite a bit of tension beforehand. But the presentation went well and I got some very nice, positive feedback. That convinced me to submit an abstract, on the same subject, for BLUG. Fingers crossed!

The slides are in Dutch. If my abstract for BLUG gets accepted, I'll make an English version.


Friday, July 6, 2012

Use HTML5 elements in Internet Explorer 6-8

One of the (as you probably know many) problems with Internet Explorer is that up to version 8 it refuses to render unknown HTML elements. Being created before the HTML5 standard was finalized, you're out of luck if you want to make a nice HTML5 web site and use the new elements like header, footer or menu. IE will treat them as inline elements and not apply any styling you defined in a stylesheet.

Fortunately, it turns out to be pretty easy to teach IE about these new elements, so that it will render them correctly. The trick is to use Javascript to create the elements you need in the DOM before the browser starts rendering.

For XPages applications I use the following code. Put it in your theme's <resources> section. It will only be included for visitors who use Internet Explorer 6 up to 8 and it create a bit of Javascript in the head of each page.

<script
    clientSide="true" 
    rendered="#{javascript:context.getUserAgent().isIE(6,8)}" 
    contents="document.createElement('header');document.createElement('hgroup');
        document.createElement('nav');document.createElement('menu');
        document.createElement('section');document.createElement('article');
        document.createElement('aside');document.createElement('footer');">
</script> 

With this IE will treat the elements as if they are div's, and that's pretty much all you need.

Game on!

Thursday, May 31, 2012

Quick tip: Get hostname with EL

Here's a quick little tip, something I hadn't realized before and wanted to share.

Normally when I need to get the host name used in the current request I would do something like:
#{javascript:context.getUrl().getHost()}
It's a Javascript call, which is always slower than pure Java or Expression Language (EL). Where possible I try to use EL instead of Javascript.

So, can you achieve the same result with EL? Yes, and it's actually pretty straightforward. Just drop the "get" and "()" and fix the case:
#{context.url.host}
There's another example on the XPages Wiki.

Happy hacking!

Monday, April 23, 2012

Settings bean - parameterized method call from EL

With Xpages it's convenient to keep your settings in a properties file. They're easy to create, maintain and access from EL (Expression Language), SSJS (Server Side JavaScript) and Java. And they're fast too! But what if your settings are somewhere else, like in a central database? What can you do to create something that works from all three languages (EL, SSJS and Java) and have it fast too?

Beans are great for solving these kind of problems. But there's one issue: it's not possible to use parameters from EL when calling methods.

Example: imagine you have this User bean and it has a method called getName(). From Java or SSJS you call User.getName(), from EL you use User.name. No problem.

Now you do the same with a Settings bean. You handcraft a method getValue(String name) that retrieves the value for the property that was passed as a parameter. From Java or SSJS you would call something like Settings.getValue('db_names'). But how do you call the same function from EL? Settings.value['db_names'] won't work. The system expects the getValue() method to return a Map and will try to get the value for 'db_names' from that Map. The Settings bean itself won't even get to see the parameter 'db_names' and thus can't do any smart things itself. So how do you solve that without creating a hard coded method for every possible setting?

I found the answer in an article on MyFaces Wiki. What you do is add a parameter-less method getValue() to the Setting bean, next to the getValue(String name) method that's already there. This method returns a object of a class that implements the Map interface. This class has a custom made implementation for the Map method get(). This method itself will see the 'db_names' parameter and with that is able to retrieve the correct value from its parent, the Settings bean.

Got it? No? Code speaks louder than words.

Settings bean
package nl.thimojansenit.bean;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import nl.thimojansenit.DummyMap;

/**
 * @author Thimo Jansen <thimo@jansenit.nl>
 */
public class Settings implements Serializable {

 private static final long serialVersionUID = 1L;
 private Map<String, Cache> _cache = new HashMap<String, Cache>();

 /**
  * Retrieve cached value of setting. If not yet cached or value is too old (> 60 minutes), get fresh value
  * 
  * @param name
  *            of setting to retrieve
  * @return value of setting
  */
 public String getValue(String name) {
  Date now = new Date();
  if (!_cache.containsKey(name) || (now.getTime() - _cache.get(name).getDatetime().getTime()) > 1000 * 60 * 60) {
   _cache.put(name, new Cache(getFromMap(name)));
  }

  return _cache.get(name).getValue();
 }

 /**
  * Get SettingsMap object through which EL can fetch the value for a setting
  * 
  * @return SettingsMap
  */
 public SettingsMap getValue() {
  return new SettingsMap(this);
 }

 /**
  * Static method to retrieve settings, replace this code with your own logic
  */
 static private String getFromMap(String name) {
  Map<String, String> settings = new HashMap<String, String>();
  settings.put("hostname", "www.thimojansenit.nl");
  settings.put("db_names", "names.nsf");

  return settings.get(name);
 }

 /**
  * InnerClass used to provide settings to EL. This class uses the parent bean to fetch values for settings
  */
 @SuppressWarnings("unchecked")
 private class SettingsMap extends DummyMap implements Map {
  // Reference to parent Settings bean
  private Settings _settings;

  public SettingsMap(Settings settings) {
   _settings = settings;
  }

  public Object get(Object obj) {
   return _settings.getValue((String) obj);
  }
 }

 /**
  * InnerClass used to store cached values, includes date/time stamp
  */
 private class Cache {
  private Date _datetime;
  private String _value;

  public Cache(String value) {
   _datetime = new Date();
   _value = value;
  }

  public Date getDatetime() {
   return _datetime;
  }

  public String getValue() {
   return _value;
  }
 }
}

As explained above, this is just a Settings bean. It has a _cache map to store retrieved values in. It stores them as an object of class Cache with both the value and a time-stamp. The method getValue(String name) looks at the _cache map and tries to get the value from that. It it's not there or if it's too old, it gets the value from the method getFromMap(String name). This method is the one that you normally would replace with a lookup in a database, or something similar.

So far so good. This works fine when called from Java or SSJS. But not in EL.

The special bits to make this work with EL are the getValue() method that returns a SettingsMap and the innerclass SettingsMap that implements Map and extends DummyMap.

The DummyMap (see below for code) is just there so you don't have to implement each required Map method every time you use this construction. Convenience.

The class SettingsMap itself has a constructor and an implementation of the get() method. The constructor expects a reference to the parent Bean as an argument, so the code can use that reference later on to easily retrieve values back from the Bean. With this it knows where to find the Bean.

The get(Object obj) method is what's called when the EL tries to get the value from the Map. Because this method now has our own implementation, we're able to see the parameter (which was not possible before) and retrieve the value on the fly. In this case we use the reference to the Settings Bean to call the getValue(String name) method there and return that.

EL tear down

The EL for this call would look like this:
Settings.value['db_names']
Let's tear that down and explain what each part does.

Settings references the Settings bean, value calls the parameter-less getValue() method on the Settings bean that returns the SettingsMap. That Map is used to retrieve the value with the call SettingsMap.get("db_names"). Now as we've written the implementation for this get() ourselves, we now have the power to use the parameter and get the value from the parent's getValue("db_names") method and return that to the XPage.

Pretty clever right?


DummyClass

As promised, here's the code for DummyClass:
package nl.thimojansenit;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

// abstract class used by java server faces to pass parameter to a method as map key
@SuppressWarnings("unchecked")
public abstract class DummyMap implements Map {
 public Collection values() {
  return null;
 }

 public Object put(Object key, Object value) {
  return null;
 }

 public Set keySet() {
  return null;
 }

 public boolean isEmpty() {
  return false;
 }

 public int size() {
  return 0;
 }

 public void putAll(Map t) {
 }

 public void clear() {
 }

 public boolean containsValue(Object value) {
  return false;
 }

 public Object remove(Object key) {
  return null;
 }

 public boolean containsKey(Object key) {
  return false;
 }

 public Set entrySet() {
  return null;
 }

 // subclasses should override this method call their method with obj as the parameter
 public abstract Object get(Object obj);
}
Disclaimer/attribution: The code for this DummyClass is just about copy/pasted from the Myfaces Wiki.

Hope this explains it a bit and that you found it useful. Happy hacking!