The controller is designed to render a Map<QualifiedName, String> as an HTTP URL according to its routing table, but to integrate it for easy usage in WebUI Framework of GateIn, you need some more components:
PortalURL
plays a similar role at the portal level. Its main role is to abstract the creation of an URL for a resource managed by the portal.
public abstract class PortalURL<R, U extends PortalURL<R, U>>
{
...}
The PortalURL
declaration may seem a bit strange at first sight with two generic types: U
and R
.
The R
generic type represents the type of the resource managed by the portal.
The U
generic type is also described as self bound generic type. This design pattern allows a class to return subtypes of itself in the class declaring the generic type. Java Enums are based on this principle (class Enum<E extends Enum<E>>
).
A portal URL has various methods but certainly the most important method is the toString()
method that generates an URL targeting to the resource. The remaining methods are getter
and setter
used to mutate the URL configuration, those options will affect the URL representation when it is generated.
resource: The mandatory resource associated with the URL.
locale: The optional locale used in the URL allowing the creation of bookmarkable URL containing a language.
confirm: The optional confirmation message displayed by the portal in the context of the portal UI.
ajax: The Ajax option allowing an ajax invocation of the URL.
PortalURL
objects are obtained from RequestContext
instance, such as the PortalRequestContext
, or the PortletRequestContext
. Usually, those are obtained thanks to the getCurrentInstance
method of the RequestContext
class:
RequestContext ctx = RequestContext.getCurrentInstance();
PortalURL
is created via the createURL
method that takes an input as a resource type. The resource type is usually a constant and type-safe object that allows retrieving the PortalURL
subclasses:
RequestContext ctx = RequestContext.getCurrentInstance();
PortalURL<R, U> url = ctx.createURL(type);
In reality, you will use a concrete type constant and have instead more concrete code like:
RequestContext ctx = RequestContext.getCurrentInstance();
NodeURL url = ctx.createURL(NodeURL.TYPE);
The NodeURL.TYPE
is actually declared as new ResourceType<NavigationResource, NodeURL>()
that can be described as a type-literal
object emulated by a Java anonymous inner class. Such literal was introduced by Neil Gafter as Super Type Token and popularized by Google Guice as Type Literal. It is an interesting way to create a literal representing a kind of Java type.
The NodeURL
class is one of the subclasses of PortalURL
that is specialized in navigation node resources:
public class NodeURL extends PortalURL<NavigationResource, NodeURL>
{
...
}
The NodeURL
class does not carry any generic types of its super class, which means that a NodeURL
is type-safe and you do not have to worry about generic types.
Using a NodeURL
is pretty straightforward:
NodeURL url = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
url.setResource(new NavigationResource("portal", "classic, "home"));
String s = url.toString();
The NodeURL
subclass contains the specialized setter
methods to make its usage even easier:
UserNode node = ...;
NodeURL url = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
url.setNode(node);
String s = url.toString();
The ComponentURL
subclass is another specialization of PortalURL
that allows the creation of WebUI components URLs. ComponentURL
is commonly used to trigger WebUI events from client side:
<% def componentURL = uicomponent.event(...); /*or uicomponent.url(...) */ %> <a href=$componentURL>Click me</a>
Normally, you should not have to deal with it as the WebUI framework has already an abstraction for managing URL known as URLBuilder
. The URLBuilder
implementation delegates URL creation to ComponentURL
objects.
Portlet URLs API implementation delegates to the portal ComponentURL
(via the portlet container SPI). It is possible to control the language in the URL from a PortletURL
object by setting the gtn:lang
property:
When the property value is set to a value returned by the Locale#toString()
method for locale objects having a non null language value and a null variant value, the URL generated by the PortletURL#toString()
method will contain the locale in the URL.
When the property value is set to an empty string, the generated URL will not contain a language. If the incoming URL was carrying a language, this language will be erased.
When the property value is not set, it will not affect the generated URL.
PortletURL url = resp.createRenderURL();
url.setProperty("gtn:lang", "fr");
writer.print("<a href='" + url + "'>French</a>");
This internal API is used to create URL works as usual and delegates to the PortletURL
API when the framework is executed in a portlet, and delegates to a ComponentURL
API when the framework is executed in the portal context. The API has been modified to take in account the language in URL with two properties on the builder:
locale: A locale for setting on the URL.
removeLocale: A boolean for removing the locale present on the URL.
In a Groovy template, the mechanism to create an URL is the same as the way of APIs above, however a splash of integration has been done to make creation of NodeURL simpler. A closure is bound under the nodeurl
name and is available for invocation anytime. It will simply create a NodeURL object and return it:
UserNode node = ...;
NodeURL url = nodeurl();
url.setNode(node);
String s = url.toString();
The nodeurl
closure is bound to Groovy template in WebuiBindingContext
.
// Closure nodeurl()
put("nodeurl", new Closure(this)
{
@Override
public Object call(Object[] args)
{
return context.createURL(NodeURL.TYPE);
}
});