UIX Developer's Guide |
![]() Contents |
![]() Previous |
![]() Next |
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:
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.
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 .../>
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.
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:contentFooter> |
<uix:pageLayout> |
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.
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.
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
.
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.
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.
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.
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
<uix:renderingContext>
tagIn 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:
"id"
: when defined, a
ServletRenderingContext
scriptable
variable will be introduced named by this attribute (see below
for an example)
"configuration"
: defines the name
of the Configuration
object this
rendering context will use. The Configuration
object must have been previously created and registered.
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>
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.
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.
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>
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.
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"/>
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>
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>
.
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
.)
uiXML requires the text in attributes to follow the rules of XML. For example, quotes must be escaped as """. Less-than signs ("<") must be written as "<". Ampersands ("&") must be written as "&".
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\"">
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 <
) 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>