UIX Developer's Guide
Go to Table of Contents
Contents
Go to previous page
Previous
Go to next page
Next

18. UIX JSP Tag Libraries

Java Server Pages (JSPs) have become a well-known technology for developing web interfaces. We believe that a fully declarative technology - like uiXML - is a more robust and performant architecture for delivering large-scale enterprise applications. But for those that disagree, we do provide a tag library that provides access to most of the functionality of the UIX library with a syntax that will prove familiar to uiXML developers.

This chapter contains the following sections:

Installing the Tag library

With a JSP 1.2-compliant engine like Tomcat 4 or OC4J 9.0.3, if you've installed the UIX JARs into the WEB-INF/lib directory, you've installed the UIX JSP tags. As with any tag library, you need to declare the prefix used for that library, so in each JSP page that will use the UIX tag library, add the following line near the top:

<%@ taglib uri="http://xmlns.oracle.com/uix/ui" prefix="uix" %>

If your servlet engine doesn't support this, or you've installed the UIX JARs in a different location, you will need to perform a little additional installation. Move the uix.tld file into the "WEB-INF" subdirectory of your web application, then add the following lines to your "WEB-INF/web.xml" file:

 <taglib>
   <taglib-uri>http://xmlns.oracle.com/uix/ui</taglib-uri>
   <taglib-location>/WEB-INF/uix.tld</taglib-location>
 </taglib>

(The uix.tld file is currently in the WEB-INF directory of the uix2-src.zip in our development bundle; it may be moved into the main installables .zip.)

In either case, you're free to use any prefix string you want. We've chosen "uix" here.

Limitations of the UIX JSP library

The JSP tag library is missing a number of features of uiXML. In some cases, that functionality just hasn't been implemented yet, but the JSP Tag technology is fundamentally limited in some ways that simply don't allow for features supported by our XML code.

No default namespace

XML supports the concept of a default namespace for elements:

 <ui:form ...>
   <ui:contents>
     <!-- OK, enough with "ui:"; let's give ourselves a
           default namespace -->
     <stackLayout xmlns="http://xmlns.oracle.com/uix/ui">
       <contents>
         <textInput .../>

This saves a great deal of typing in XML files, but unfortunately JSPs do not support it. You'll need to use the prefix on all elements:

 <ui:form ...>
   <uix:contents>
     <uix:stackLayout>
       <uix:contents>
         <uix:textInput .../>

Data binding

In uiXML, we use a "data:" prefix on attributes to define compact data bindings:

 <styledText data:text="foo@bar"/>

JSPs do not allow for this syntax. As an alternative, we append a suffix of Binding to each attribute name:

 <uix:styledText textBinding="foo@bar"/>

As with uiXML, data-binding is allowed for attributes that can't be set directly by a single string, like table data:

 <uix:table tableDataBinding="foo@bar"/>

Also, uiXML lets you register DataObjects by both a namespace and "local" name (if this is unfamiliar territory, you might review the Data Binding chapter). Because JSPs do not support namespaces in any real sense, UIX JSPs do not support this. All DataObjects should be registered with a namespace of the empty string ("", not null).

Finally, UIX JSPs do not support the <boundAttribute> element. See below for how to work around this limitation.

<uix:contents> is optional

In uiXML, the <contents> element is used to wrap all the indexed children of a UINode. This extra element greatly reduces potential ambiguities in our syntax, and improves our tool's ability to provide quality code insight. What's more, the architecture of our system means that these extra elements have a negligible impact on parse-time performance - and since the results of parsing are cached, absolutely no impact on performance or memory use once the file has been parsed once.

JSP tags, however, are individually transformed into Java code, then into Java .class files. Each added tag is extra Java code, so each tag results in a larger .class files that take longer to execute and requires more memory to keep loaded. It's even possible - without trying very hard - to run into the fixed limits on method sizes in Java. Consequently, we've had to look for shortcuts to reduce the number of tags needed for user interfaces, and one of the simplest fixes was making <uix:contents> optional in nearly all cases.

There is an important exception. Some elements serve as either a "named child" tag and a UINode tag depending on the context, so they need <uix:contents> to disambiguate their meaning. For example, the <uix:separator> element typically provides a horizontal separator line:

 <uix:form>
    <uix:textInput .../>
    <uix:separator/>
    <uix:textInput .../>
 </uix:form>

However, when used in a <uix:flowLayout>, then the <uix:separator> element instead acts as a wrapper - the elements inside of <uix:separator> will each be stamped out between each pair of elements in the flow layout. For example, the following UIX generates the text "a between b between c":

 <uix:flowLayout>
    <uix:separator>
      <uix:styledText text=" between "/>
    </uix:separator>
    <uix:text text="a"/>
    <uix:text text="b"/>
    <uix:text text="c"/>
 </uix:flowLayout>

If you need a <uix:separator> of that first meaning inside a <uix:flowLayout>, you'll need to use <uix:contents>:

 <uix:flowLayout>
    <uix:contents>
      <uix:text text="a"/>
      <uix:separator/>
      <uix:text text="b"/>
    </uix:contents>
 </uix:flowLayout>

Here's a list of elements that sometimes require <uix:contents>, and a list of the parents for each that will trigger this situation:

Element name Parent names
<uix:separator> <uix:flowLayout>, <uix:stackLayout>, <uix:styledList>
<uix:contentFooter> <uix:pageLayout>

Templates are not supported

uiXML supports a templating technology that lets you define new user interface elements at runtime without writing any code or recompiling any classes. JSP tags, however, require a new Java class for each tag, and also require a statically defined set of attributes. Consequently, the template technology is not supported inside UIX JSP. (But see the <uix:xml> tag.)

Developers who have built templates can actually make those elements available to UIX JSP developers. However, they will need to manually write JSP Tag classes and a JSP TLD file; see the JSP specification for more information on these classes.

HTML namespaced elements

uiXML supports the use of XML in a pseudo-HTML namespace. These elements can be mixed freely into regular uiXML content, and can even participate in data binding:

 <stackLayout>
   <contents>
     <html:p data:class="class@source">
       <textInput ...>
     </html:p>
   </contents>
 </stackLayout>      

This feature is not available in UIX JSPs; use the <uix:rawText> element instead.

Setting DataObjects and DataObjectLists

As described above, JSP tags only allow for a fixed and static set of attributes. However, the uiXML syntax for DataObjects and DataObjectLists inherently requires an arbitrary set of attributes:

 <table>
   <tableData>
     <row a="1" foo="true" style="OraErrorText" destination="..."/>
     <row b="17" foo="false" style="OraErrorText" destination="..."/>
      ...
   </tableData>
    ...

Consequently, we do not support setting DataObject our DataObjectList attributes declaratively in UIX JSPs. They can be databound, as in uiXML; also, see Scriptable variables for a workaround for this limitation of JSPs.

There is currently a single exception: we do support the <uix:tableFormat> element, which is a specific type of DataObject.

Declarative DataProviders

UIX JSP does not currently support the <provider> element of uiXML; see Scriptable variables for a workaround. One exception is the <uix:bundle> element; see below.

Declarative event handling

UIX JSPs are used entirely for rendering; they contain no support for built-in event handling. We encourage developers using JSPs to consider the UIX Controller as a "head servlet" that forwards to JSPs for rendering, but we do not plan on providing JSP tags for implementing any event handling directly inside JSPs.

In addition, the "ctrl:" attributes and elements are not available in UIX JSPs.

BC4J JSP tags

The UIX BC4J XML tags are not currently available in JSP form. The JDeveloper team will provide a set of tags that can be used in their place.

"textAndAccessKey" and "promptAndAccessKey"

These shortcuts allow uiXML to set the text and prompt of a button with one attribute. They are not yet supported in UIX JSP.

Added features of UIX JSP

The <uix:renderingContext> tag

In uiXML, we create a RenderingContext automatically for each page, and provide Java APIs to configure that context. In UIX JSPs, the context needs to be created automatically on that page; to allow configuration of this context, it supports the following attributes:

This element must surround the content that uses the RenderingContext. It can be omitted, in which case we will fall back on a default RenderingContext.

Example:

 <uix:renderingContext configuration="YourConfigName"
                           id="rContext">
   <% 
       // And add a data provider with Java code
       rContext.addDataProvider(new FixedDataProvider(.....));
    %>
   <uix:stackLayout> ....
 </uix:renderingContext>

The <uix:xml> Tag

Because of the limitations inherent in the JSP technology, we've provided a <uix:xml> tag that lets you embed uiXML directly in your JSP, even mixed in between UIX JSP tags.

Example:

 <uix:header text="A header">
   <uix:styledText text="A message"/>
   <uix:xml>
     <dataScope xmlns="http://xmlns.oracle.com/uix/ui"
                 xmlns:demo="http://example.org">
       <provider>
         <data name="demo:foo">
           <method .../>
         </data>
       </provider>
       <contents>
         <messageTextInput  data:text="text@demo:foo" .../>
          ...
       </contents>
     </dataScope>
   </uix:xml>
 </uix:header>

Note that each block of uiXML does need to define all the needed XML namespaces up front. Also, it is not possible to use UIX JSP tags inside the XML. However, you're free to use scriptlets and include directives inside your XML:

   <% ResourceBundle bundle = ResourceBundle.getBundle(...); %>
   <uix:xml>
     <stackLayout xmlns="http://xmlns.oracle.com/uix/ui"> 
       <contents>
         <%@ include file="sample.uix" %>
         <!-- Get the text from a ResourceBundle.  Note that
               you'd be much better off using a<dataScope> and
              <bundle> data provider - for one thing, you'd
               be able to cache the parsing results (see below) -->
         <button text="<%=bundle.getString("buttonText")%>"/>
       </contents>
     </stackLayout>
   </uix:xml>
 </uix:header>

(It is not legal to use <jsp:include> inside of <uix:xml>; for the reason, see section 5.4.5 of the JSP 1.1 specification. The JSP standard tag library effort plans to define a JSP tag that will work around this limitation of JSPs.)

Parsing uiXML is rather fast, but applications needing top performance will find it useful to cache the results. This avoids reparsing the XML on each request. To support caching, developers can set "scope" and "var" attributes which will store the results of the XML parse. The "scope" variable must be one of "page", "request" (the default), "session", or "application". The "var" attribute should be a value unique for that scope. When a cached version is found, the content of the <uix:xml> tag will be skipped over instead of being reparsed. The <uix:xml> tag does not support any scriptable variables. In this way, and in its choice of "var" and "scope", it matches the current design of the JSP Standard Tag Library.

There is a "gotcha" with this caching: when cached at "application" or "session" level, the cache results are not automatically discarded when the JSP is changed and reloaded. So, we'd recommend only enabling caching when you're done developing a page. In addition, code that uses scriptlets - like the bundle.getString(...) example above - cannot take advantage of caching for obvious reasons.

<uix:xml> has two major limitations relative to uiXML: it supports only elements and attributes in the UIX Components namespace ("http://xmlns.oracle.com/uix/ui") and the pseudo-HTML namespace ("http://www.w3.org/TR/REC-html40"), and does not yet support templates. Both of these limitations will be removed in future releases.

Built-in data bindings

To simplify databinding with UIX JSP, we automatically register four data providers on the RenderingContext to get objects stored on the servlet objects. The first three data objects are named "servletContext", "httpSession", and "servletRequest", and correspond to the "application", "session", and "request" scopes. The fourth data object is named "pageContext". Instead of corresponding directly to "page" scope, it will actually search all four scopes, starting at "page", then "request", followed by "session", and finally "application". (For developers familiar with the JSP Java API, this corresponds to PageContext.findAttribute())

Example:


 <%-- Set up some attributes --%>
 <% application.setAttribute("someText", "Bar"); %>
 <% request.setAttribute("someText", "Foo"); %>
 <% session.setAttribute("nls",
        new BundleDataObject(ResourceBundle.getBundle("MyResources",
                                                      locale))); %>

 <!-- Get some text out of the page context;  this will
       search up to (and eventually find) "Foo", and not
       get to the "Bar" stored at the application level  -->
 <uix:styledText textBinding="someText@pageContext"/>

 <!-- Get a key off of a ResourceBundle that's stored at the session
       level -->
 <uix:styledText textBinding="aBundleKey@nls@servletContext"/>

These data bindings are also available to <uix:xml> blocks.

Scriptable variables

All UIX JSP tags that define UINodes use the "id" attribute to define scriptable variables. For example, if you create a <uix:table> tag and set the "id" attribute to "myTable", there will be a TableBean variable named "myTable":

 <uix:table id="myTable">
   <% 
       myTable.setTableData(new ArrayDataSet(.....));
    %>
    ...
 </uix:table>

These variables are only accessible from scriptlets inside the tag.

Scriptable variables can be used to work around the limitation described in the Declarative DataProviders section that UIX JSP does not currently support the <provider> element of uiXML ; for example, by using a scriptable variable, data providers can be set on a <uix:dataScope>:

 <uix:dataScope id="myScope">
   <%

       DataObject data = YourDataDemo.getYourData();
       TableDataProvider provider = new TableDataProvider();
       // associate dataObject with namespace and name
       // all DataObjects in UIX JSP should be registered
       // with a namespace of the empty string ("", not null).
       provider.put("","bar", data);
       // set the data provider on <uix:dataScope> using the variable myScope
       myScope.setProvider(provider);
    %>
    ...
 </uix:dataScope>

Runtime Expressions

All UIX JSP variables can be computed with inline Java code:

 <uix:labeledFieldLayout columns="<%= 1 + 1 %>" >
     ...

Whether the ability to mix in arbitrary Java code is a feature or a problem is left as a philosophical question.

<uix:buildTree> and <uix:ref>

The <uix:buildTree> and <uix:ref> tags let you build UIX component trees in one location and reuse that tree in another. These tags can also let you create a tree once and repeatedly reuse that tree.

<uix:buildTree> takes two parameters: "nodeID", which is required, and "scope", which is optional. "nodeID" will be used to look up the tree later, and "scope" defines how long to keep the tree available. Just as with <uix:xml>, "scope" can be one of "page", "request", "session", or "application". And, as with <uix:xml>, if there's already a tree available with that identifier at that scope, <uix:buildTree> will do nothing and save you the cost of rebuilding the tree. However, unlike <uix:xml>, <uix:buildTree> never directly renders the tree you build. Instead, it only stores the tree.

The tag that will result in a tree being rendered is <uix:ref>. This tag must be empty, and supports only a single attribute: "refID". Typically, this will match a "nodeID" of an earlier <uix:buildTree>:

 <uix:buildTree nodeID="boilerplate">
   <uix:styledText text="Some boilerplate text"/>
 </uix:buildTree>

 <uix:stackLayout>
   <uix:styledText text="Some text"/>
   <uix:ref refID="boilerplate"/>
   <uix:styledText text="Some more text"/>
   <uix:ref refID="boilerplate"/>
 </uix:stackLayout>

You can also use <uix:ref> to refer to a UINode built directly in Java code:

<%
    StyledTextBean bean = new StyledTextBean("Boilerplate text");
    request.setAttribute("bean", bean);
 %>

<uix:ref refID="bean"/>

Other Differences Between uiXML and UIX JSP

<uix:document> and More

uiXML usually knows when it's being called on to write an entire page, and when it's only writing a piece of a page. So it can be clever in a few ways about cleaning up your page, making sure that the stylesheet has been added, the right <HTML> tag is added, and so forth. uiXML also gives you programmatic hooks for manipulating the RenderingContext, like setting the Configuration object.

UIX JSP tags can't be quite so assured of their environment, so you'll have to code a little bit differently. In general, your pages should take advantage of both the <uix:renderingContext> and <uix:document> tags. You'll use the former as the root of your entire UI content, then put <uix:document> immediately inside. Most of your pages should look like the following example:

 <uix:renderingContext>
   <uix:document>
     <uix:metaContainer>
       <%-- If you need to add any "META" tags, they go inside -->
       <%-- of<uix:head> -->
       <uix:head title="The title of your page"/>
     </uix:metaContainer>

     <%-- And here's the content of your page -->
     <uix:pageLayout>
        ...
     </uix:pageLayout>

   </uix:document>
 </uix:renderingContext>

If you've been using UIX JSPs, you may be a bit surprised to not see <uix:styleSheet> in this example. The <uix:head> tag automatically adds the stylesheet so you don't need to.

If you need to set the Configuration, use the "configuration" attribute of <uix:renderingContext>. For any other properties, set the "id" of <uix:renderingContext>. This will give you access to a scriptable variable of type ServletRenderingContext:

 <uix:renderingContext id="rContext" configuration="myConfig">
   <%-- Now we'll call a few methods --%>
   <% rContext.setURLEncoder(...); 
          rContext.addDataProvider(...); %>
    ...
 </uix:renderingContext>

Including UIX JSP content

It's frequently useful for one UIX JSP to include another, but we do not support the simple use of <jsp:include>. If compile-time, static includes are sufficient, you can get away with <%@ include file="..."%>. For dynamic includes of one UIX tree into another, you'll want to use <uix:include node="foo.jsp"/>:


  <uix:tableLayout>
    <uix:rowLayout>
      <uix:include node="myCellFormat.jsp"/>
    </uix:rowLayout>
  </uix:tableLayout>

UIX JSP also supports a "nodeBinding" attribute on <uix:include> to access UINodes either created in Java code or stored using <uix:buildTree>.

Localization of Text

uiXML supports automatic localization of text with the <bundle> element, which ties a ResourceBundle into the generic data binding architecture as a DataProvider. Even though UIX JSP generally does not support declarative DataProviders, it does support a <uix:bundle> tag. The syntax is somewhat different, though.

The <uix:bundle> tag can only be used immediately inside of a <uix:renderingContext> element. It's an empty element that supports two attributes, "class" and "name", both of which are required. "class" should be the full class name of the resource bundle, while "name" is the name of the data object:


<uix:renderingContext id="rc">
<uix:bundle name="nls"
             class="yourPackage.YourResourceBundleName"/>
 ...

     <uix:link textBinding="someText@nls" 
                destination="http://www.oracle.com"/>
 ...
</uix:renderingContext>

You can use as many <uix:bundle> elements as you want in a page, though each will of course need its own "name". UIX will automatically choose the correct version of the resource bundle based on the current Locale for the page. (To override UIX's default choice of a Locale, use scriptable variables and the setLocaleContext() method available on ServletRenderingContext.)

Attribute escaping

uiXML requires the text in attributes to follow the rules of XML. For example, quotes must be escaped as "&quot;". Less-than signs ("<") must be written as "&lt;". Ampersands ("&") must be written as "&amp;".

UIX JSP has few rules at all, so these characters do not need to be escaped - though the values of attributes in your raw HTML do have to be escaped. One exception to this rule is the double-quote, which does have to be escaped. Strangely, it's escaped using Java conventions, not HTML or XML - so a double-quote must be preceeded by a backslash:

 <button text="Press \"Here\"">

Handling of raw text

Both uiXML and UIX JSPs support a <rawText> element that lets you insert raw HTML into your documents. uiXML is XML - which means that the content has to be well-formed XML. Developers must either manually escape their text (e.g., change < into &lt;) or use a CDATA section:

<rawText><![CDATA[
Here's some HTML:<a href="http://www.oracle.com">Oracle</a>
and it can go <b>on and on and on</b>...
]]></rawText>

UIX JSPs don't require their contents to be well-formed at all. Again, whether this is a feature or problem is for you to decide, but it means that you don't need a CDATA section when using UIX JSPs:

<uix:rawText>
Here's some HTML: <a href="http://www.oracle.com">Oracle</a>
and it can go <b>on and on and on</b>...
</uix:rawText>