HTL Java Use-API htl-java-use-api
The HTL Java Use-API enables an HTL file to access helper methods in a custom Java class.
Use Case use-case
The HTL Java Use-API enables an HTL file to access helper methods in a custom Java class through data-sly-use
. This method allows all complex business logic to be encapsulated in the Java code, while the HTL code deals only with direct markup production.
A Java Use-API object can be a simple POJO, instantiated by a particular implementation through the POJO’s default constructor.
The Use-API POJOs can also expose a public method, called init, with the following signature:
/**
* Initializes the Use bean.
*
* @param bindings All bindings available to the HTL scripts.
**/
public void init(javax.script.Bindings bindings);
The bindings
map can contain objects that provide context to the currently run HTL script that the Use-API object can use for its processing.
A Simple Example a-simple-example
This example illustrates the usage of the Use-API.
Start with an HTL component, called info,
that does not have a use-class. It consists of a single file, /apps/my-example/components/info.html
<div>
<h1>${properties.title}</h1>
<p>${properties.description}</p>
</div>
Add some content for this component to render at /content/my-example/
:
{
"sling:resourceType": "my-example/component/info",
"title": "My Example",
"description": "This Is Some Example Content."
}
When this content is accessed, the HTL file is run. Within the HTL code, the context object properties
is used to access the current resource’s title
and description
and display them. The output file /content/my-example.html
is the following:
<div>
<h1>My Example</h1>
<p>This Is Some Example Content.</p>
</div>
Adding a Use-Class adding-a-use-class
The info
component as it stands does not need a use-class to perform its 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:
For example, suppose that you want the info
component to display the title
and description
properties of the resource, but all in lowercase. Because HTL does not have a method for lowercasing strings, you can add a Java use-class and change /apps/my-example/component/info/info.html
as follows:
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Additionally, /apps/my-example/component/info/Info.java
is created.
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;
}
}
Please see the Java docs for com.adobe.cq.sightly.WCMUsePojo
for more details.
Now, let’s look at the different parts of the code.
Local vs. Bundle Java Class local-vs-bundle-java-class
The Java use-class can be installed in two ways:
- Local - 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.
- Bundle - In a bundle install, the Java class must be compiled and deployed within an OSGi bundle using the standard AEM bundle deployment mechanism (see the section Bundled Java Class).
To know which method to use when, keep these two points in mind:
- 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.
This example uses a local install.
Java Package is Repository Path java-package-is-repository-path
When using a local install, the package name of the use-class must match the repository folder location. Underscores in the package name replace any hyphens in the path.
In this case Info.java
is located at /apps/my-example/components/info
so the package is apps.my_example.components.info
:
package apps.my_example.components.info;
import com.adobe.cq.sightly.WCMUsePojo;
public class Info extends WCMUsePojo {
...
}
Extending WCMUsePojo
extending-wcmusepojo
While there are a number of ways of incorporating a Java class with HTL, the simplest is to extend the WCMUsePojo
class. For this example /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 initializing-the-class
When the use-class is extended from WCMUsePojo
, initialization is performed by overriding the activate
method, in this case in /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 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 the document Global Objects.)
In a class extending WCMUsePojo
, you can access context objects using their names:
<T> T get(String name, Class<T> type)
Alternatively, you can access commonly used context objects directly using the appropriate convenience method listed in this table.
Getter Methods getter-methods
Once the use-class has initialized, the HTL file is run. During this stage, HTL typically pulls in the state of various member variables of the use-class and renders 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
exposes within the HTL file that an object property calledxyz
.
In the following example file /apps/my-example/component/info/Info.java
, the methods getTitle
and getDescription
result in the object properties title
and description
becoming accessible within the context of the HTL file.
...
public class Info extends WCMUsePojo {
...
public String getLowerCaseTitle() {
return lowerCaseTitle;
}
public String getLowerCaseDescription() {
return lowerCaseDescription;
}
}
data-sly-use
Attribute data-sly-use-attribute
The data-sly-use
attribute is used to initialize the use-class within your HTL code. In the example, the data-sly-use
attribute declares that the class Info
is used. You can use just the local name of the class because you are using a local install (having placed the Java source file in the same folder as the HTL file). If you were using a bundle install, you would have to specify the fully qualified class name.
Note the usage in this /apps/my-example/component/info/info.html
example.
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Local Identifier 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.
Note the usage in this /apps/my-example/component/info/info.html
example.
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Getting Properties getting-properties
The identifier info
is then used to access the object properties title
and description
that were exposed through the getter methods Info.getTitle
and Info.getDescription
.
Note the usage in this /apps/my-example/component/info/info.html
example.
<div data-sly-use.info="Info">
<h1>${info.lowerCaseTitle}</h1>
<p>${info.lowerCaseDescription}</p>
</div>
Output output
Now, when /content/my-example.html
is accessed, it returns the following /content/my-example.html
file.
<div>
<h1>my example</h1>
<p>this is some example content.</p>
</div>
Beyond the Basics beyond-the-basics
This section introduces some additional features that go beyond the example described previously.
- Passing parameters to a use-class
- Bundled Java use-class
Passing Parameters passing-parameters
Parameters can be passed to a use-class upon initialization.
For details, please refer to the Sling HTL Scripting Engine documentation.
Bundled Java Class bundled-java-class
With a bundled 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 as in this /apps/my-example/component/info/Info.java
example.
package org.example.app.components;
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 as in this /apps/my-example/component/info/info.html
example.
<div data-sly-use.info="org.example.app.components.info.Info">
<h1>${info.title}</h1>
<p>${info.description}</p>
</div>