Including a Java Class in SSJS

You’re most likely aware that SSJS really is really turned into Java under the covers, but did you realize that you can use Java classes in SSJS? In this post, I’ll show how with a simple example.

Using a Java class in SSJS

There are examples similar to this in the DDE help when looking up how to get a document from a view:

var vec = new java.util.Vector();
vec.addElement('firstLookupKey');
vec.addElement('secondLookupKey');
var doc - myView.getDocumentByKey(vec);

And so on. Several view lookup methods take a vector as a way to look up documents or view entries with multiple keys for multiple sorted columns.

The first line specifies that it’s creating a new java.util.Vector() object. After that, you can use methods of that Java class right from SSJS.

Using Type Ahead Autocompletion for Java Class Methods

If you specify the type of the variable that you create, Domino Designer provide type ahead. Take this example:

var vec:java.util.Vector = new java.util.Vector();

Just type the variable name and a period, and (maybe after a slight pause), you’ll see a list of properties and methods to choose from:

Java Class in SSJS

Importing a Java Class into SSJS

If you want to refer to an object more easily in SSJS, you can import the class you want to use and then reference it just by the class name, rather than by the fully-qualified name. To do this, use importPackage().

Here’s how this would look different when working with a Vector:

importPackage (java.util.Vector);	
var vec = new Vector();

And now you have code that’s a little easier to follow and also has the ability to display the properties and methods of the class:

Java Class in SSJS 2

Clearly, there is far more opportunity to use this than the simple examples I’ve shown here, but I hope this gets the gears turning and becomes a useful feature for you.

XPages Tip: Using _dump to write information to the server console

I recently showed how to use a built-in client-side JavaScript function to dump the contents of an object for review. In this post, I’ll show a somewhat similar method available in Server-Side JavaScript.

_dump() is a global method available in SSJS. You can use it to write the contents of an object out to the server console (and log).

The XPages Portable Command Guide mentions using it to dump the contents of scope variable maps.

Since the requestScope automatically has a bunch of properties, I can see the results if I run this beforePageLoad:

_dump(requestScope);

Here is the output on the server console — basic URL, user, server, and page info:


HTTP JVM: com.sun.faces.context.RequestMap
HTTP JVM: =
HTTP JVM: {database=BlogTesting.nsf, __xspconvid=null, opensession=CN=XDev9/O=Xcellerant, userScope={}, session=CN=XDev9/O=Xcellerant, cookie={SessionID=javax.servlet.http.Cookie@7190719}, component
HTTP JVM: arameters=com.ibm.xsp.application.ComponentParameters@3f953f95, context=com.ibm.xsp.designer.context.ServletXSPContext@56fc56fc,
identityScope={}, serverScope={Anonymous={}}, opendatabase=BlogTesting.nsf, com.ibm.xsp.SESSION_ID=B7117B555E750057C2668FD5A46
HTTP JVM: 51CB288B7621}

The sessionScope is empty by default, but I can add a few properties and then look at the output:

sessionScope.property1 = 'abc';
sessionScope.property2 = 'def';
_dump(sessionScope);

HTTP JVM: com.sun.faces.context.SessionMap
HTTP JVM: =
HTTP JVM: {__XSP_STATE_FILE=com.ibm.xsp.application.FileStateManager$SessionState@70647064,
__notescontext_publicaccess=com.ibm.domino.xsp.module.nsf.NotesContext$AccessPrivileges@2a0b2a0b, property2=def, xsp.sessionData=com.ibm.xsp.designer.context.PersistentSessi
HTTP JVM: nData@34fb34fb, property1=abc}

Not exactly easy to read, but the information is there.

But you’re not limited to scope variables. Here’s an example of creating my own object and writing it out:

var myObject = {};
myObject.foo = 'xyz';
myObject.bar = 'uvw';
_dump(myObject);

HTTP JVM: Object
HTTP JVM: =
HTTP JVM: [object Object]
HTTP JVM:
HTTP JVM: +-
HTTP JVM: foo
HTTP JVM: :
HTTP JVM: string
HTTP JVM: =
HTTP JVM: xyz
HTTP JVM:
HTTP JVM: +-
HTTP JVM: bar
HTTP JVM: :
HTTP JVM: string
HTTP JVM: =
HTTP JVM: uvw

This seems ridiculously spread out, but it’s pretty easy to see the contents of the object.

All in all, MarkLeusink’s Debug Toolbar is a much nicer tool to use when working with scope variables, but if you’re doing some quick debugging — or setting up a consistent method of handling errors, the _dump() method can come in handy.

Article Published in The VIEW: Improve Application Performance with JSON-RPC

An article that I wrote on improving XPages application performance using JSON RPC has been published in The VIEW journal (subscription required).

One of the best-kept secrets of XPages is JSON-RPC control. It is the ideal solution for application developers who want:

  • Their XPages applications to be more efficient and run faster
  • To easily implement client-side and server-side JavaScript interaction

Abstract

If you want your XPages applications to perform more efficiently, or if you’ve ever struggled with executing server-side JavaScript from client-side JavaScript (or taken it a step further and plotted hacktastic workarounds for passing information back and forth), then you need to get to know JSON-RPC. Compared to workarounds that involve partial refreshes, JSON-RPC is a much cleaner method of client and server code interaction and is much more efficient because there is no form submission. JSON-RPC is also asynchronous, so it’s faster and appears more responsive because it doesn’t block user interaction. In this article, get an introduction to JSON-RPC and learn how to reap the benefits in your XPages applications.

Client-Side JavaScript Debugging Tip — Using XSP.dumpObject() and XSP.log()

The XSP object is a client-side JavaScript object that is built and delivered by the XPages runtime and it contains a number of useful functions, some of which are always available and some of which are context-specific. In this post, I’ll show two functions that are useful for client-side JavaScript debugging.

XSP.dumpObject()

The dumpObject() method returns a string representation of all properties of any object that you pass to it. If you want to track down why something isn’t working as expected, it may be helpful to inspect the properties of the object.

The object can be a variable that you programmatically create and modify or it can be an element on the page.

I used to make frequent use of a small script to display all properties of a JavaScript object, but this is a much simpler way to get that information.

Here’s an example of client-side JavaScript to build an object and use XSP.dumpObject() to write out all properties to the browser console:

var myObject = {}
myObject.property1 = 'One';
myObject.property2 = 'Two';
myObject.property3 = 'Three';
myObject.arrayProperty = ['a', 'b', 'c'];

console.log(XSP.dumpObject(myObject));

This information can be very helpful in debugging, so I would recommend using it when handling errors in a try-catch block.

XSP.log()

In addition to logging to the console, you have another similar option available by another XSP function. XSP.log() is analogous to the standard console.log() function that you use when debugging client-side

JavaScript, but the log() method opens up a new browser window and logs messages there, in descending order.

All we have to do is change the last line in the previous snippet:

XSP.log(XSP.dumpObject(myObject));

And this is what we see in a separate browser window:

XSPLog - 1

The log() method will continue appending any messages that you send until you close the window. The next call to XSP.log() will open a new, blank window and start logging again.

Using dumpObject on an HTML field and XPages control

You can also use dumpObject on an HTML element.

For example, if I have a pure HTML select with 3 options and an onchange event, this will be the output of if I get a handle to the element (the id is HTMLComboBox) and dump the object properties:

XSP.log(XSP.dumpObject(dojo.byId('htmlComboBox')));

object
  0: [object HTMLOptionElement] (Maximum Depth Reached)
  1: [object HTMLOptionElement] (Maximum Depth Reached)
  2: [object HTMLOptionElement] (Maximum Depth Reached)
  autofocus: false
  disabled: false
  form: [object HTMLFormElement] (Maximum Depth Reached)
  multiple: false
  name: 
  required: false
  size: 0
  type: select-one
  options: [object HTMLOptionsCollection] (Maximum Depth Reached)
  length: 3
  selectedOptions: [object HTMLCollection] (Maximum Depth Reached)
  selectedIndex: 0
  value: v1
  willValidate: true
  validity: [object ValidityState] (Maximum Depth Reached)
  validationMessage: 
  title: 
  lang: 
  dir: 
  dataset: [object DOMStringMap] (Maximum Depth Reached)
  itemScope: false
  itemType:  (Maximum Depth Reached)
  itemId: 
  itemRef:  (Maximum Depth Reached)
  itemProp:  (Maximum Depth Reached)
  properties: [object HTMLPropertiesCollection]... (Maximum Depth Reached)
  itemValue:  (Maximum Depth Reached)
  hidden: false
  tabIndex: 0
  accessKey: 
  accessKeyLabel: 
  draggable: false
  contentEditable: inherit
  isContentEditable: false
  contextMenu:  (Maximum Depth Reached)
  spellcheck: false
  style: [object CSS2Properties] (Maximum Depth Reached)
  className: 
  oncopy:  (Maximum Depth Reached)
  oncut:  (Maximum Depth Reached)
  onpaste:  (Maximum Depth Reached)
  offsetParent: [object HTMLBodyElement] (Maximum Depth Reached)
  offsetTop: 39
  offsetLeft: 0
  offsetWidth: 67
  offsetHeight: 19
  onabort:  (Maximum Depth Reached)
  onblur:  (Maximum Depth Reached)
  onfocus:  (Maximum Depth Reached)
  oncanplay:  (Maximum Depth Reached)
  oncanplaythrough:  (Maximum Depth Reached)
  onchange:  (Maximum Depth Reached)
  onclick:  (Maximum Depth Reached)
  oncontextmenu:  (Maximum Depth Reached)
  ondblclick:  (Maximum Depth Reached)
  ondrag:  (Maximum Depth Reached)
  ondragend:  (Maximum Depth Reached)
  ondragenter:  (Maximum Depth Reached)
  ondragleave:  (Maximum Depth Reached)
  ondragover:  (Maximum Depth Reached)
  ondragstart:  (Maximum Depth Reached)
  ondrop:  (Maximum Depth Reached)
  ondurationchange:  (Maximum Depth Reached)
  onemptied:  (Maximum Depth Reached)
  onended:  (Maximum Depth Reached)
  oninput:  (Maximum Depth Reached)
  oninvalid:  (Maximum Depth Reached)
  onkeydown:  (Maximum Depth Reached)
  onkeypress:  (Maximum Depth Reached)
  onkeyup:  (Maximum Depth Reached)
  onload:  (Maximum Depth Reached)
  onloadeddata:  (Maximum Depth Reached)
  onloadedmetadata:  (Maximum Depth Reached)
  onloadstart:  (Maximum Depth Reached)
  onmousedown:  (Maximum Depth Reached)
  onmouseenter:  (Maximum Depth Reached)
  onmouseleave:  (Maximum Depth Reached)
  onmousemove:  (Maximum Depth Reached)
  onmouseout:  (Maximum Depth Reached)
  onmouseover:  (Maximum Depth Reached)
  onmouseup:  (Maximum Depth Reached)
  onpause:  (Maximum Depth Reached)
  onplay:  (Maximum Depth Reached)
  onplaying:  (Maximum Depth Reached)
  onprogress:  (Maximum Depth Reached)
  onratechange:  (Maximum Depth Reached)
  onreset:  (Maximum Depth Reached)
  onscroll:  (Maximum Depth Reached)
  onseeked:  (Maximum Depth Reached)
  onseeking:  (Maximum Depth Reached)
  onselect:  (Maximum Depth Reached)
  onshow:  (Maximum Depth Reached)
  onstalled:  (Maximum Depth Reached)
  onsubmit:  (Maximum Depth Reached)
  onsuspend:  (Maximum Depth Reached)
  ontimeupdate:  (Maximum Depth Reached)
  onvolumechange:  (Maximum Depth Reached)
  onwaiting:  (Maximum Depth Reached)
  onmozfullscreenchange:  (Maximum Depth Reached)
  onmozfullscreenerror:  (Maximum Depth Reached)
  onmozpointerlockchange:  (Maximum Depth Reached)
  onmozpointerlockerror:  (Maximum Depth Reached)
  onerror:  (Maximum Depth Reached)
  tagName: SELECT
  id: htmlComboBox
  classList:  (Maximum Depth Reached)
  attributes: [object MozNamedAttrMap] (Maximum Depth Reached)
  onwheel:  (Maximum Depth Reached)
  scrollTop: 0
  scrollLeft: 0
  scrollWidth: 67
  scrollHeight: 19
  clientTop: 0
  clientLeft: 0
  clientWidth: 67
  clientHeight: 19
  scrollTopMax: 0
  scrollLeftMax: 0
  innerHTML: <option value="v1">Value 1</option><option value="v2">Value 2</option><option value="v3">Value 3</option>
  outerHTML: <select id="htmlComboBox"><option value="v1">Value 1</option><option value="v2">Value 2</option><option value="v3">Value 3</option></select>
  previousElementSibling: [object HTMLBRElement] (Maximum Depth Reached)
  nextElementSibling: [object HTMLBRElement] (Maximum Depth Reached)
  children: [object HTMLCollection] (Maximum Depth Reached)
  firstElementChild: [object HTMLOptionElement] (Maximum Depth Reached)
  lastElementChild: [object HTMLOptionElement] (Maximum Depth Reached)
  childElementCount: 3
  nodeType: 1
  nodeName: SELECT
  baseURI: http://127.0.0.2/BlogTesting.nsf/dumpObject.xsp
  ownerDocument: [object HTMLDocument] (Maximum Depth Reached)
  parentNode: [object HTMLFormElement] (Maximum Depth Reached)
  parentElement: [object HTMLFormElement] (Maximum Depth Reached)
  childNodes: [object NodeList] (Maximum Depth Reached)
  firstChild: [object HTMLOptionElement] (Maximum Depth Reached)
  lastChild: [object HTMLOptionElement] (Maximum Depth Reached)
  previousSibling: [object Text] (Maximum Depth Reached)
  nextSibling: [object HTMLBRElement] (Maximum Depth Reached)
  nodeValue:  (Maximum Depth Reached)
  textContent: Value 1Value 2Value 3
  namespaceURI: http://www.w3.org/1999/xhtml
  prefix:  (Maximum Depth Reached)
  localName: select
  ELEMENT_NODE: 1
  ATTRIBUTE_NODE: 2
  TEXT_NODE: 3
  CDATA_SECTION_NODE: 4
  ENTITY_REFERENCE_NODE: 5
  ENTITY_NODE: 6
  PROCESSING_INSTRUCTION_NODE: 7
  COMMENT_NODE: 8
  DOCUMENT_NODE: 9
  DOCUMENT_TYPE_NODE: 10
  DOCUMENT_FRAGMENT_NODE: 11
  NOTATION_NODE: 12
  DOCUMENT_POSITION_DISCONNECTED: 1
  DOCUMENT_POSITION_PRECEDING: 2
  DOCUMENT_POSITION_FOLLOWING: 4
  DOCUMENT_POSITION_CONTAINS: 8
  DOCUMENT_POSITION_CONTAINED_BY: 16
  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32

If I have a similar Combo Box control in XPages, the output is the same because the HTML element that is generated is virtually identical.

Note: You must pass a fully-qualified client-side ID to dumpObject(), so if you’re passing it an XPages element, use the pass-thru EL syntax "#{id:myControl}" or a client-side query that looks for the element id ending with the name of the control, such as dojo.query('[id~=myControl]')[0].id

console.dir(object)

There’s a method built into browser development tools that performs a similar function. This can be similarly handy when troubleshooting something directly on the page.

For example, to see all of the properties of the first input field on the form, you can use it like this:

console.dir(dojo.query('input')[0]);

Setting the Maximum File Upload Size for an XPages Application

If you want to control the maximum value for an uploaded file, you can use the xsp.upload.maximumsize setting in xsp.properties.

Application-Level Maximum Upload Size

There is no maximum upload set at the application level by default. (Although there is a server-level setting that I’ll come back to later in this post.)

To set it, you can use the Xsp Properties design element and set the Maximum size property under File Upload Options in the first column of the General tab. Specify the value in kilobytes (KB)

MaxFileUploadTesting-0-Setting

This adds the following value to the xsp.properties file (as seen on the Source tab):

xsp.upload.maximumsize=400

Error Message

If you add an Error Message control for the File Upload control or an Error Messages control on the form, you will see an error message regarding the file size setting when you try to submit a form with an attachment that’s too large.

MaxFileUploadTesting-1-Error

Server-wide Limit

As mentioned earlier, there’s no default at the application level. The default is the server-wide setting, which defaults to roughly 10 MB.

Even if you set the maximum at the application level, it can never exceed the server setting.

The server setting is defined on the Server document in the Domino Directory. It can be found on the Internet Protocols tab, HTTP subtab in the HTTP Protocol Limits section.

MaxFileUploadTesting-3-ServerSetting

If you try to upload a file larger than the server-wide limit, it aborts the connection and throws an ugly error. (HTTP 500 – Internal Server Error)

MaxFileUpload-ServerError

Even if you set an application level maximum lower than the server maximum, if you try to upload a file larger than the server maximum, it will throw the same HTTP error.

Domino Usage Survey

As you may have already heard, PSC has posted a survey to gauge current usage and future direction for Domino.

If you haven’t already taken the survey, please take a moment and let us know how Domino is used in your organization. Please also share the link – the more feedback we get, the stronger the results will be.

http://bit.ly/PSCXPagesSurvey

The survey will be open until October 3rd and results will be posted publicly on October 6th.

Modifying an XSP Property fo a Single XPage

I’m familiar with setting XSP properties in xsp.properties at the application or server level and I’ve used tags to do the same within a theme, but I did not realize until recently that you can also set these properties at the XPage level to override the broader settings on a page-by-page basis.

Select the root tag for the page and go to All Properties in the Properties view. Under the data subtab, click on properties and click the plus (+) button to add a property.

This adds a new parameter and defaults the name attribute to param and the value attribute to val. In the source, it adds an xp:this.properties tag containing an xp:parameter tag.

XSP Property Page Level - 1

Let’s see this in action with a few examples.

Here’s the first fiew lines of a brand new, unmodified XPage on my test server. The application leaves the server defaults for the HTML doctype and character set (although the latter is not visible in this output).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title></title>

If you want to add a meta tag to the page that displays the doctype and character set, you can add the xsp.html.meta.contenttype property to the page and set its value to true.

You can also override the HTML doctype and character set for the page with additional properties. (Click on the picture to enlarge.)

XSP Property Page Level - 2

Here’s the updated first few lines of output, including the meta tag and reflecting the updated doctype and character set:

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title>

There are many more properties that can be modified at the page level (though not all of them). If you have the XPages Portable Command Guide, you can find them all described in depth there (The book covers through 8.5.3. Sven Hasselbach has a good post on some new properties that were added in Notes 9.)

It appears that you can similarly modify properties at the custom control level, but I have not tested the effectiveness or how conflicts are handled.

Follow

Get every new post delivered to your Inbox.

Join 52 other followers