Enumerable Objects
These objects provide convenient access to commonly used information. Their content can be accessed with the dot notation, and they can be iterated-through using data-sly-list or data-sly-repeat
Java-backed Objects
Each of the following objects is backed by the corresponding Java object.
The most useful variables in the table below are highlighted in bold.
Variable Name Description
component com.day.cq.wcm.api.components.Component
componentContext com.day.cq.wcm.api.components.ComponentContext
currentDesign com.day.cq.wcm.api.designer.Design
currentNode javax.jcr.Node
currentPage com.day.cq.wcm.api.Page
currentSession javax.servlet.http.HttpSession
currentStyle com.day.cq.wcm.api.designer.Style
designer com.day.cq.wcm.api.designer.Designer
editContext com.day.cq.wcm.api.components.EditContext
log org.slf4j.Logger
out java.io.PrintWriter
pageManager com.day.cq.wcm.api.PageManager
reader java.io.BufferedReader
request org.apache.sling.api.SlingHttpServletRequest
resolver org.apache.sling.api.resource.ResourceResolver
resource org.apache.sling.api.resource.Resource
resourceDesign com.day.cq.wcm.api.designer.Design
resourcePage com.day.cq.wcm.api.Page
response org.apache.sling.api.SlingHttpServletResponse
sling org.apache.sling.api.scripting.SlingScriptHelper
slyWcmHelper com.adobe.cq.sightly.WCMScriptHelper
wcmmode com.adobe.cq.sightly.SightlyWCMMode
xssAPI com.adobe.granite.xss.XSSAPI
JavaScript-backed Objects
There are also objects available that are backed by JavaScript. However, as of AEM 6.2 these objects are still experimental and it is better to use the Java-backed objects, which allow them to do the same.
HTL Java Use-API
The HTML Template Language (HTL) Java Use-API enables an HTL file to access helper methods in a custom Java class. This allows all complex business logic to be encapsulated in the Java code, while the HTL code deals only with direct markup production.
A Simple Example
We'll start with an HTL component that does not have a use-class. It consists of a single file,
/apps/my-example/components/info.html
/apps/my-example/component/info/info.html
<div>
<h1>${properties.title}</h1>
<p>${properties.description}</p>
</div>
We also add some content for this component to render at
/content/my-example/ : http://localhost:4502/content/my-example.json
{
"sling:resourceType": "my-example/component/info",
"title": "My Example",
"description": "This Is Some Example Content."
}
When this content is accessed, the HTL file is executed. Within the HTL code, we use the context object properties to access the current resource's title and description and display them. The output HTML will be:
view-source:http://localhost:4502/content/my-example.html
<div>
<h1>My Example</h1>
<p>This Is Some Example Content.</p>
</div>
Adding a Use-Class
The info the component, as it stands, does not need a use-class to perform its (very simple) function. There are cases, however, where you need to do things that cannot be done in HTL and so you need a use-class. But keep in mind the following:
A use-class should only be used when something cannot be done in HTL alone.
For example, suppose that you want the info component to display the title and description properties of the resource, but all in lowercase. Since HTL does not have a method for lowercasing strings, you will need a use-class. We can do this by adding a Java use-class and changing the
info.html as follows:
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
private String lowerCaseTitle;
private String lowerCaseDescription;
@Override
public void activate() throws Exception {
lowerCaseTitle = getProperties().get("title", "").toLowerCase();
lowerCaseDescription = getProperties().get("description", "").toLowerCase();
}
public String getLowerCaseTitle() {
return lowerCaseTitle;
}
public String getLowerCaseDescription() {
return lowerCaseDescription;
}
}
In the following sections, we walk through the different parts of the code.
Local vs Bundle Java Class
The Java use-class can be installed in two ways:
local or bundle. This example uses a local install.
In a local install, the Java source file is placed alongside the HTL file, in the same repository folder. The source is automatically compiled on demand. No separate compilation or packaging step is required.
In a bundle install, the Java class must be compiled and deployed within an OSGi bundle using the standard AEM bundle deployment mechanism (see Bundled Java Class ).
A local Java use-class is recommended when the use-class is specific to the component in question.
A bundle Java use-class is recommended when the Java code implements a service that is accessed from multiple HTL components.
Java package is repository path
When a local install is used, the package name of the use-class must match that of the repository folder location, with any hyphens in the path replaced by underscores in the package name.
In this case, Info.java is located at /apps/my-example/components/info so the package is apps.my_example.components.info:
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
package apps.my_example.components.info;
These objects provide convenient access to commonly used information. Their content can be accessed with the dot notation, and they can be iterated-through using data-sly-list or data-sly-repeat
Java-backed Objects
Each of the following objects is backed by the corresponding Java object.
The most useful variables in the table below are highlighted in bold.
Variable Name Description
component com.day.cq.wcm.api.components.Component
componentContext com.day.cq.wcm.api.components.ComponentContext
currentDesign com.day.cq.wcm.api.designer.Design
currentNode javax.jcr.Node
currentPage com.day.cq.wcm.api.Page
currentSession javax.servlet.http.HttpSession
currentStyle com.day.cq.wcm.api.designer.Style
designer com.day.cq.wcm.api.designer.Designer
editContext com.day.cq.wcm.api.components.EditContext
log org.slf4j.Logger
out java.io.PrintWriter
pageManager com.day.cq.wcm.api.PageManager
reader java.io.BufferedReader
request org.apache.sling.api.SlingHttpServletRequest
resolver org.apache.sling.api.resource.ResourceResolver
resource org.apache.sling.api.resource.Resource
resourceDesign com.day.cq.wcm.api.designer.Design
resourcePage com.day.cq.wcm.api.Page
response org.apache.sling.api.SlingHttpServletResponse
sling org.apache.sling.api.scripting.SlingScriptHelper
slyWcmHelper com.adobe.cq.sightly.WCMScriptHelper
wcmmode com.adobe.cq.sightly.SightlyWCMMode
xssAPI com.adobe.granite.xss.XSSAPI
JavaScript-backed Objects
There are also objects available that are backed by JavaScript. However, as of AEM 6.2 these objects are still experimental and it is better to use the Java-backed objects, which allow them to do the same.
HTL Java Use-API
The HTML Template Language (HTL) Java Use-API enables an HTL file to access helper methods in a custom Java class. This allows all complex business logic to be encapsulated in the Java code, while the HTL code deals only with direct markup production.
A Simple Example
We'll start with an HTL component that does not have a use-class. It consists of a single file,
/apps/my-example/components/info.html
/apps/my-example/component/info/info.html
<div>
<h1>${properties.title}</h1>
<p>${properties.description}</p>
</div>
We also add some content for this component to render at
/content/my-example/ : http://localhost:4502/content/my-example.json
{
"sling:resourceType": "my-example/component/info",
"title": "My Example",
"description": "This Is Some Example Content."
}
When this content is accessed, the HTL file is executed. Within the HTL code, we use the context object properties to access the current resource's title and description and display them. The output HTML will be:
view-source:http://localhost:4502/content/my-example.html
<div>
<h1>My Example</h1>
<p>This Is Some Example Content.</p>
</div>
Adding a Use-Class
The info the component, as it stands, does not need a use-class to perform its (very simple) function. There are cases, however, where you need to do things that cannot be done in HTL and so you need a use-class. But keep in mind the following:
A use-class should only be used when something cannot be done in HTL alone.
For example, suppose that you want the info component to display the title and description properties of the resource, but all in lowercase. Since HTL does not have a method for lowercasing strings, you will need a use-class. We can do this by adding a Java use-class and changing the
info.html as follows:
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
private String lowerCaseTitle;
private String lowerCaseDescription;
@Override
public void activate() throws Exception {
lowerCaseTitle = getProperties().get("title", "").toLowerCase();
lowerCaseDescription = getProperties().get("description", "").toLowerCase();
}
public String getLowerCaseTitle() {
return lowerCaseTitle;
}
public String getLowerCaseDescription() {
return lowerCaseDescription;
}
}
In the following sections, we walk through the different parts of the code.
Local vs Bundle Java Class
The Java use-class can be installed in two ways:
local or bundle. This example uses a local install.
In a local install, the Java source file is placed alongside the HTL file, in the same repository folder. The source is automatically compiled on demand. No separate compilation or packaging step is required.
In a bundle install, the Java class must be compiled and deployed within an OSGi bundle using the standard AEM bundle deployment mechanism (see Bundled Java Class ).
A local Java use-class is recommended when the use-class is specific to the component in question.
A bundle Java use-class is recommended when the Java code implements a service that is accessed from multiple HTL components.
Java package is repository path
When a local install is used, the package name of the use-class must match that of the repository folder location, with any hyphens in the path replaced by underscores in the package name.
In this case, Info.java is located at /apps/my-example/components/info so the package is apps.my_example.components.info:
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
...
}
Using hyphens in the names of repository items is a recommended practice in AEM development. However, hyphens are illegal within Java package names. For this reason, all hyphens in the repository path must be converted to underscores in the package name.
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
Using hyphens in the names of repository items is a recommended practice in AEM development. However, hyphens are illegal within Java package names. For this reason, all hyphens in the repository path must be converted to underscores in the package name.
- Extending
- WCMUsePojo
/apps/my-example/component/info/Info.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
...
}
Initializing the class
When the use-class is extended from
WCMUsePojo, initialization is performed by overriding the
activate method: /apps/my-example/component/info/Info.java
...
Initializing the class
When the use-class is extended from
WCMUsePojo, initialization is performed by overriding the
activate method: /apps/my-example/component/info/Info.java
...
public class Info extends WCMUsePojo {
private String lowerCaseTitle;
private String lowerCaseDescription;
@Override
public void activate() throws Exception {
lowerCaseTitle = getProperties().get("title", "").toLowerCase();
lowerCaseDescription = getProperties().get("description", "").toLowerCase();
}
...
}
Context
Typically, the activate method is used to precompute and store (in member variables) the values needed in your HTL code, based on the current context (the current request and resource, for example).
The WCMUsePojo class provides access to the same set of context objects as are available within an HTL file (see Global Objects ).
In a class that extends WCMUsePojo, context objects can be accessed
by name using <T> T get(String name, Class<T> type)
Alternatively, commonly used context objects can be accessed directly by the appropriate convenience method :
PageManager getPageManager()
Page getCurrentPage()
Page getResourcePage()
ValueMap getPageProperties()
ValueMap getProperties()
Designer getDesigner()
Design getCurrentDesign()
Style getCurrentStyle()
Component getComponent()
ValueMap getInheritedProperties()
Resource getResource()
ResourceResolver getResourceResolver()
SlingHttpServletRequest getRequest()
SlingHttpServletResponse getResponse()
SlingScriptHelper getSlingScriptHelper()
Getter methods
Once the use-class has initialized, the HTL file is run. During this stage, HTL will typically pull in the state of various member variables of the use-class and render them for presentation.
To provide access to these values from within the HTL file you must define custom getter methods in the use-class
according to the following naming convention :
A method of the form getXyz will expose within the HTL file an object property called xyz
Context
Typically, the activate method is used to precompute and store (in member variables) the values needed in your HTL code, based on the current context (the current request and resource, for example).
The WCMUsePojo class provides access to the same set of context objects as are available within an HTL file (see Global Objects ).
In a class that extends WCMUsePojo, context objects can be accessed
by name using <T> T get(String name, Class<T> type)
Alternatively, commonly used context objects can be accessed directly by the appropriate convenience method :
PageManager getPageManager()
Page getCurrentPage()
Page getResourcePage()
ValueMap getPageProperties()
ValueMap getProperties()
Designer getDesigner()
Design getCurrentDesign()
Style getCurrentStyle()
Component getComponent()
ValueMap getInheritedProperties()
Resource getResource()
ResourceResolver getResourceResolver()
SlingHttpServletRequest getRequest()
SlingHttpServletResponse getResponse()
SlingScriptHelper getSlingScriptHelper()
Getter methods
Once the use-class has initialized, the HTL file is run. During this stage, HTL will typically pull in the state of various member variables of the use-class and render them for presentation.
To provide access to these values from within the HTL file you must define custom getter methods in the use-class
according to the following naming convention :
A method of the form getXyz will expose within the HTL file an object property called xyz
For example, in the following example, the methods
getTitle and getDescription result in the object properties title and description becoming accessible within the context of the HTL file:
getTitle and getDescription result in the object properties title and description becoming accessible within the context of the HTL file:
/apps/my-example/component/info/Info.java
...
...
public class Info extends WCMUsePojo {
...
public String getLowerCaseTitle() {
return lowerCaseTitle;
}
public String getLowerCaseDescription() {
return lowerCaseDescription;
}
}
data-sly-use attribute
The data-sly-use the attribute is used to initialize the use-class within your HTL code. In our example, the data-sly-use the attribute declares that we want to use the class Info. We can use just the local name of the class because we are using a local install (having placed the Java source file is in the same folder as the HTL file). If we were using a bundle install we would have to specify the fully qualified classname (See Use-class Bundle Install ).
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
data-sly-use attribute
The data-sly-use the attribute is used to initialize the use-class within your HTL code. In our example, the data-sly-use the attribute declares that we want to use the class Info. We can use just the local name of the class because we are using a local install (having placed the Java source file is in the same folder as the HTL file). If we were using a bundle install we would have to specify the fully qualified classname (See Use-class Bundle Install ).
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Local identifier The identifier 'info' (after the dot in data-sly-use.info ) is used within the HTL file to identify the class. The scope of this identifier is global within the file after it has been declared. It is not limited to the element that contains the data-sly-use statement.
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
Local identifier The identifier 'info' (after the dot in data-sly-use.info ) is used within the HTL file to identify the class. The scope of this identifier is global within the file after it has been declared. It is not limited to the element that contains the data-sly-use statement.
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Getting properties identifier info is then used to access the object properties title and description that was exposed through the getter methods Info.getTitle and Info.getDescription.
Getting properties identifier info is then used to access the object properties title and description that was exposed through the getter methods Info.getTitle and Info.getDescription.
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info">
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Output Now, when we access
/content/my-example.html it will return the following HTML:
view-source:http://localhost:4502/content/my-example.html
<div>
Output Now, when we access
/content/my-example.html it will return the following HTML:
view-source:http://localhost:4502/content/my-example.html
<div>
<h1>my example</h1>
<p>this is some example content.</p>
</div>
Beyond The Basics
In this section we'll introduce some further features that go beyond the simple example above:
Beyond The Basics
In this section we'll introduce some further features that go beyond the simple example above:
- Passing parameters to a use-class.
- Bundled Java use-class.
- Alternatives to WCMUsePojo
- Passing Parameters
<div data-sly-use.info="${'Info' @ text='Some text'}">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
<p>${info.upperCaseText}</p>
</div>
Here we are passing a parameter called text. The use-class then uppercases the string we retrieve and display the result with info.upperCaseText. Here is the adjusted use-class: /apps/my-example/component/info/Info.java
Here we are passing a parameter called text. The use-class then uppercases the string we retrieve and display the result with info.upperCaseText. Here is the adjusted use-class: /apps/my-example/component/info/Info.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
...
private String reverseText;
@Override
public void activate() throws Exception {
...
String text = get("text", String.class);
reverseText = new StringBuffer(text).reverse().toString();
}
public String getReverseText()
{
return reverseText;
}
...
}
The parameter is accessed through the WCMUsePojo method
<T> T get(String paramName, Class<T> type)
In our case, the statement get("text", String.class)
The string is then reversed and exposed via the method
getReverseText() Only Pass Parameters from data-sly-template
While the above example is technically correct, it actually does not make much sense to pass a value from HTL to initialize a use-class, when the value in question is available in the execution context of the HTL code (or, trivially, the value is static, as above). The reason is that the use-class will always have access to the same execution context as the HTL code. This brings up an important point of best practice:
Passing a parameter to a use-class should only be done when the use-class is used in a data-sly-template file which itself is called from another HTL file with parameters that need to be passed on.
For example, let's create a separate data-sly-template file alongside our existing example. We will call the new file extra.html. It contains a
data-sly-template block called extra:
The parameter is accessed through the WCMUsePojo method
<T> T get(String paramName, Class<T> type)
In our case, the statement get("text", String.class)
The string is then reversed and exposed via the method
getReverseText() Only Pass Parameters from data-sly-template
While the above example is technically correct, it actually does not make much sense to pass a value from HTL to initialize a use-class, when the value in question is available in the execution context of the HTL code (or, trivially, the value is static, as above). The reason is that the use-class will always have access to the same execution context as the HTL code. This brings up an important point of best practice:
Passing a parameter to a use-class should only be done when the use-class is used in a data-sly-template file which itself is called from another HTL file with parameters that need to be passed on.
For example, let's create a separate data-sly-template file alongside our existing example. We will call the new file extra.html. It contains a
data-sly-template block called extra:
/apps/my-example/component/info/extra.html
<template data-sly-template.extra="${@ text}" data-sly-use.extraHelper="${'ExtraHelper' @ text=text}">
<template data-sly-template.extra="${@ text}" data-sly-use.extraHelper="${'ExtraHelper' @ text=text}">
<p>${extraHelper.reversedText}</p>
</template>
The template extra takes a single parameter, text. It then initializes the Java use-class ExtraHelper with the local name extraHelper and passes it the value of the template parameter text as the use-class parameter text.
The body of the template gets the property extraHelper.reversedText (which, under the hood, actually calls ExtraHelper.getReversedText() ) and displays that value.
We also adapt our existing info.html to use this new template:
/apps/my-example/component/info/info.html
The template extra takes a single parameter, text. It then initializes the Java use-class ExtraHelper with the local name extraHelper and passes it the value of the template parameter text as the use-class parameter text.
The body of the template gets the property extraHelper.reversedText (which, under the hood, actually calls ExtraHelper.getReversedText() ) and displays that value.
We also adapt our existing info.html to use this new template:
/apps/my-example/component/info/info.html
<div data-sly-use.info="Info"
data-sly-use.extra="extra.html">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
<div data-sly-call="${extra.extra @ text=properties.description}">
</div>
</div>
The file info.html now contains two data-sly-use statements, the original one that imports the Info Java use-class and a new one that imports the template file under the local name extra.
Note that we could have placed the template block inside the info.html file to avoid the second data-sly-use, but a separate template file is more common and more reusable.
The Info class is employed as before, calling its getter methods
getLowerCaseTitle() and getLowerCaseDescription() through their corresponding HTL properties info.lowerCaseTitle and info.lowerCaseDescription. Then we perform a
data-sly-call to the template extra and pass it the value properties.description as the parameter text. The Java use-class Info.java is changed to handle the new text parameter:
/apps/my-example/component/info/ExtraHelper.java
The file info.html now contains two data-sly-use statements, the original one that imports the Info Java use-class and a new one that imports the template file under the local name extra.
Note that we could have placed the template block inside the info.html file to avoid the second data-sly-use, but a separate template file is more common and more reusable.
The Info class is employed as before, calling its getter methods
getLowerCaseTitle() and getLowerCaseDescription() through their corresponding HTL properties info.lowerCaseTitle and info.lowerCaseDescription. Then we perform a
data-sly-call to the template extra and pass it the value properties.description as the parameter text. The Java use-class Info.java is changed to handle the new text parameter:
/apps/my-example/component/info/ExtraHelper.java
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class ExtraHelper extends WCMUsePojo {
private String reversedText;
...
@Override
public void activate() throws Exception {
String text = get("text", String.class);
reversedText = new StringBuilder(text).reverse().toString();
...
}
public String getReversedText() {
return reversedText;
}
}
The text parameter is retrieved with get("text", String.class), the value is reversed and made available as the HTL object reversedText through the getter
getReversedText() .
Bundled Java Class
With a bundle use-class, the class must be compiled, packaged, and deployed in AEM using the standard OSGi bundle deployment mechanism. In contrast with a local install, the use-class package declaration should be named normally:
/apps/my-example/component/info/Info.java
The text parameter is retrieved with get("text", String.class), the value is reversed and made available as the HTL object reversedText through the getter
getReversedText() .
Bundled Java Class
With a bundle use-class, the class must be compiled, packaged, and deployed in AEM using the standard OSGi bundle deployment mechanism. In contrast with a local install, the use-class package declaration should be named normally:
/apps/my-example/component/info/Info.java
package org.example.app.components;
<div data-sly-use.info="org.example.app.components.info.Info">
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
...
}
and, the data-sly-use statement must reference the fully qualified class name, as opposed to just the local class name: /apps/my-example/component/info/info.html
and, the data-sly-use statement must reference the fully qualified class name, as opposed to just the local class name: /apps/my-example/component/info/info.html
<div data-sly-use.info="org.example.app.components.info.Info">
<h1>${info.title}</h1>
<p>${info.description}</p>
</div>
Alternatives to WCMUsePojo
The most common way to create a Java use-class is to extend
WCMUsePojo. However, there are a number of other options. To understand these variants it helps to understand how the HTL data-sly-use statement works under the hood. Suppose you have the following data-sly-use statement: <div data-sly-use. localName =" UseClass ">
The system processes the statement as follows:
(1) If there exists a local file UseClass.java in the same directory as the HTL file, try to compile and load that class. If successful go to (2).
Otherwise, interpret UseClass as a fully qualified class name and try to load it from the OSGi environment. If successful go to (2).
Otherwise, interpret UseClass as a path to an HTL or JavaScript file and load that file. If successful goto (4).
(2) Try to adapt the current Resource to UseClass. If successful, go to (3).
Otherwise, try to adapt to the current Request to UseClass. If successful, go to (3).
Otherwise, try to instantiate UseClass with a zero-argument constructor. If successful, go to (3).
(3)Within HTL, bind the newly adapted or created object to the name localName. If UseClass implements io.sightly.java.api.Use then call the
init method, passing the current execution context (in the form of a
javax.scripting.Bindings object).
(4) If UseClass is a path to an HTL file containing a data-sly-template, prepare the template.
Otherwise, if UseClass is a path to a JavaScript use-class, prepare the use-class (see JavaScript Use-API ).
A few significant points about the above description:
Any class that is adaptable from Resource, adaptable from Request, or that has a zero-argument constructor can be a use-class. The class does not have to extend WCMUsePojo or even implement Use.
However, if the use-class does implement Use, then its init the method will automatically be called with the current context, allowing you to place initialization code there that depends on that context.
A use-class that extends WCMUsePojo is just a special case of implementing Use. It provides the convenience context methods and its
activate the method is automatically called from Use.init.
Directly Implement Interface Use
While the most common way to create a use-class is to extend
WCMUsePojo, it is also possible to directly implement the
[io.sightly.java.api.Use](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/io/sightly/java/api/Use.html) interface itself.
The Use the interface defines only one method:
[public void init(javax.script.Bindings bindings)](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/io/sightly/java/api/Use#init(javax.script.Bindings))
The init the method will be called on initialization of the class with a
Bindings an object that holds all the context objects and any parameters passed into the use-class. All additional functionality (such as the equivalent of
WCMUsePojo.getProperties() ) must be implemented explicitly using the
[javax.script.Bindings](http://docs.oracle.com/javase/7/docs/api/javax/script/Bindings.html) object.
Alternatives to WCMUsePojo
The most common way to create a Java use-class is to extend
WCMUsePojo. However, there are a number of other options. To understand these variants it helps to understand how the HTL data-sly-use statement works under the hood. Suppose you have the following data-sly-use statement: <div data-sly-use. localName =" UseClass ">
The system processes the statement as follows:
(1) If there exists a local file UseClass.java in the same directory as the HTL file, try to compile and load that class. If successful go to (2).
Otherwise, interpret UseClass as a fully qualified class name and try to load it from the OSGi environment. If successful go to (2).
Otherwise, interpret UseClass as a path to an HTL or JavaScript file and load that file. If successful goto (4).
(2) Try to adapt the current Resource to UseClass. If successful, go to (3).
Otherwise, try to adapt to the current Request to UseClass. If successful, go to (3).
Otherwise, try to instantiate UseClass with a zero-argument constructor. If successful, go to (3).
(3)Within HTL, bind the newly adapted or created object to the name localName. If UseClass implements io.sightly.java.api.Use then call the
init method, passing the current execution context (in the form of a
javax.scripting.Bindings object).
(4) If UseClass is a path to an HTL file containing a data-sly-template, prepare the template.
Otherwise, if UseClass is a path to a JavaScript use-class, prepare the use-class (see JavaScript Use-API ).
A few significant points about the above description:
Any class that is adaptable from Resource, adaptable from Request, or that has a zero-argument constructor can be a use-class. The class does not have to extend WCMUsePojo or even implement Use.
However, if the use-class does implement Use, then its init the method will automatically be called with the current context, allowing you to place initialization code there that depends on that context.
A use-class that extends WCMUsePojo is just a special case of implementing Use. It provides the convenience context methods and its
activate the method is automatically called from Use.init.
Directly Implement Interface Use
While the most common way to create a use-class is to extend
WCMUsePojo, it is also possible to directly implement the
[io.sightly.java.api.Use](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/io/sightly/java/api/Use.html) interface itself.
The Use the interface defines only one method:
[public void init(javax.script.Bindings bindings)](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/io/sightly/java/api/Use#init(javax.script.Bindings))
The init the method will be called on initialization of the class with a
Bindings an object that holds all the context objects and any parameters passed into the use-class. All additional functionality (such as the equivalent of
WCMUsePojo.getProperties() ) must be implemented explicitly using the
[javax.script.Bindings](http://docs.oracle.com/javase/7/docs/api/javax/script/Bindings.html) object.
For example:
Info.java
import io.sightly.java.api.Use;
import io.sightly.java.api.Use;
public class MyComponent implements Use {
...
@Override
public void init(Bindings bindings) {
// All standard objects/binding are available
Resource resource = (Resource)bindings.get("resource");
ValueMap properties = (ValueMap)bindings.get("properties");
...
// Parameters passed to the use-class are also available
String param1 = (String) bindings.get("param1");
}
...
}
The main case for implementing the Use interface yourself instead of extending
WCMUsePojo is when you wish to use a subclass of an already existing class as the use-class.
Adaptable from Resource
Another option is to use a helper class that is adaptable from
org.apache.sling.api.resource.Resource .
Let's say you need to write an HTL script that displays the mimetype of a DAM asset. In this case, you know that when your HTL script is called, it will be within the context of a
A resource that wraps a JCR
Node with nodetype
dam:Asset.
You know that a dam: Asset node has a structure like this:
Repository Structure
{ "content": {
The main case for implementing the Use interface yourself instead of extending
WCMUsePojo is when you wish to use a subclass of an already existing class as the use-class.
Adaptable from Resource
Another option is to use a helper class that is adaptable from
org.apache.sling.api.resource.Resource .
Let's say you need to write an HTL script that displays the mimetype of a DAM asset. In this case, you know that when your HTL script is called, it will be within the context of a
A resource that wraps a JCR
Node with nodetype
dam:Asset.
You know that a dam: Asset node has a structure like this:
Repository Structure
{ "content": {
"dam": {
"geometrixx": {
"portraits": {
"jane_doe.jpg": {
...
"jcr:content": {
...
"metadata": {
...
},
"renditions": {
...
"original": {
...
"jcr:content": {
"jcr:primaryType": "nt:resource",
"jcr:lastModifiedBy": "admin",
"jcr:mimeType": "image/jpeg",
"jcr:lastModified": "Fri Jun 13 2014 15:27:39 GMT+0200",
"jcr:data": ...,
"jcr:uuid": "22e3c598-4fa8-4c5d-8b47-8aecfb5de399"
}
},
"cq5dam.thumbnail.319.319.png": {
...
},
"cq5dam.thumbnail.48.48.png": {
...
},
"cq5dam.thumbnail.140.100.png": {
...
}
}
}
}
}
}
}
}
Here we show the asset (a JPEG image) that comes with a default install of AEM as part of the example project geometrixx. The asset is called
jane_doe.jpg and its mimetype is image/jpeg.
To access the asset from within HTL, you can declare
[com.day.cq.dam.api.Asset](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/com/adobe/granite/asset/api/Asset.html) as the class in the
data-sly-use statement: and then use a get method of An asset to retrieve the desired information.
Here we show the asset (a JPEG image) that comes with a default install of AEM as part of the example project geometrixx. The asset is called
jane_doe.jpg and its mimetype is image/jpeg.
To access the asset from within HTL, you can declare
[com.day.cq.dam.api.Asset](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/com/adobe/granite/asset/api/Asset.html) as the class in the
data-sly-use statement: and then use a get method of An asset to retrieve the desired information.
For example mimetype.html
<div data-sly-use.asset="com.day.cq.dam.api.Asset">
<div data-sly-use.asset="com.day.cq.dam.api.Asset">
<p>${asset.mimeType}</p>
</div>
The data-sly-use statement directs HTL to adapt the current Resource to an
Asset and give it the local name asset. It then calls the getMimeType method of Asset using the HTL getter shorthand: asset.mimeType. Adaptable from Request. It is also possible to employ as a use-class any class that is adaptable from
[org.apache.sling.api.SlingHttpServletRequest](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/org/apache/sling/api/SlingHttpServletRequest.html)
As with the above case of a use-class adaptable from Resource, a use-class adaptable from SlingHttpServletRequest can be specified in the data-sly-use statement. Upon execution the current request will be adapted to the class given and the resulting object will be made available within HTL.
The data-sly-use statement directs HTL to adapt the current Resource to an
Asset and give it the local name asset. It then calls the getMimeType method of Asset using the HTL getter shorthand: asset.mimeType. Adaptable from Request. It is also possible to employ as a use-class any class that is adaptable from
[org.apache.sling.api.SlingHttpServletRequest](https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/org/apache/sling/api/SlingHttpServletRequest.html)
As with the above case of a use-class adaptable from Resource, a use-class adaptable from SlingHttpServletRequest can be specified in the data-sly-use statement. Upon execution the current request will be adapted to the class given and the resulting object will be made available within HTL.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.