Pages

Tuesday, May 28, 2013

CQ5/AEM how to create and use a custom taglib - part 3 use your tag

If you have not already completed part II, click here

The final step is to use your tag.

In the component of your choice, add the following to a jspx file:


<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns="http://www.w3.org/1999/xhtml"
          xmlns:jsp="http://java.sun.com/JSP/Page"
          xmlns:btes="http://btes.com.au/tagexample"
          version="2.1">
    <jsp:directive.include file="/apps/cqblueprints-example/components/global.jspx"/>
    <p>No tag left behind!</p>
    <btes:customTag content="Custom tag engaged" isHeading="true"/>
</jsp:root>

Now you should see the text "Custom tag engaged" rendered out as a heading. If you change the isHeading boolean to false, you should see it render as a paragraph.

Note that code complete should be fully functional with this example.

CQ5/AEM how to create and use a custom taglib - part 2 create and set up your TLD

If you have not already completed part I, click here.

The next step is to created your .tld directory.

In the taglib project, you will see under src/main/resources, that you have a META-INF directory.

In this directory, create a file named ProjectTaglib.tld

Add the following to this file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" version="2.1">
    <tlib-version>5.4.0-SNAPSHOT</tlib-version>
    <short-name>btes</short-name>
    <uri>http://btes.com.au/tagexample</uri>
    <tag>
        <name>customTag</name>
        <tag-class>au.com.btes.tagexample.CustomTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
  <name>content</name>
  <required>true</required>
</attribute>
<attribute>
  <name>isHeading</name>
  <required>true</required>
</attribute>
    </tag>
</taglib>

For Part III, click here



CQ5/AEM how to create and use a custom taglib - part 1 create a custom tag.

The Problem

You want to create a custom taglib, and to have code complete in your target JSP file.

The Solution

In your taglib project, Add a new file called TestHeading.java, and include the following code:



package au.com.btes.tagexample;

import java.io.IOException;

import javax.servlet.jsp.JspException;

import com.cqblueprints.taglib.CqSimpleTagSupport;

/**
 * Example custom tag to show either content wrapped within a heading, or content wrapped within
 * a paragraph
 * @author bportier
 *
 */
public class CustomTag extends CqSimpleTagSupport {
private String content;
private boolean isHeading;

@Override
public void doTag() throws JspException, IOException {
String tagString="";

if(isHeading) {
tagString="h2";
}
else {
tagString="p";
}
String message="";
message=message.concat("<").concat(tagString).concat(">");
message=message.concat(content);
message=message.concat("</").concat(tagString).concat(">");
getJspWriter().write(message);
}

public String getContent(){
return content;
}

/**
* Defines the content that the tag will display
* @param content
*/
public void setContent(String content){
this.content=content;
}

public boolean getIsHeading(){
return isHeading;
}

/**
* Defines whether to display a heading (true) or a paragraph (false)
* @param isHeading
*/
public void setIsHeading(boolean isHeading){
this.isHeading=isHeading;
}
}



This has now created your custom tag.



CQ5/AEM how to get JSTL Code complete

The Problem

After including <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> into your JSP, there is still no code complete for JSTL code, such as <c:set> or <c:out>

The Solution

You need to have the JSTL standard.jar library included in your project libraries.

If you are not using maven, you can download the 1.2 JSTL package from http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

If you are using maven, include the following in your relevant pom files:


<dependencies>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>

Friday, May 17, 2013

CQ5/AEM GOTCHYA - Why you should set all @Reference variables to null

What you should do

When writing sling servelets, all @Reference variables should be set to null

Why

We experienced an issue where when changing pom, reference was still being kept between updates. It seems that if your running servelets have injected an @Reference variable, if a change causes the @Reference variable to not successfully be able to be injected, it will only happen when the instance has been destroyed.

This is confusing as it makes it hard to narrow down which change has caused an @Reference variable to no longer be injected.

The Problem

When using CQ Blueprints, we were getting a strange error coming up when a project was checked out by a new developer, but it was running on everyone elses machines.


Failed to execute goal com.squeakysand.jsp:jsptld-maven-plugin:0.4.0:generate (default) on project taglib: Execution default of goal com.squeakysand.jsp:jsptld-maven-plugin:0.4.0:generate failed: cannot generate report -> [Help 1]

The Solution

The problem was that the taglib project could not be generated, because at that stage of the project, we had no taglibs to include yet, and we deleted the GoodbyeWorld tag and Activator class. Hence, there was nothing to build in the project, and the target directory was left empty, which caused all dependant projects to not be able to compile.

Hence, if the project was built once with at least the Activator class left in, the target build would be created, and there would be no error, only on new machines.

So, if you leave at least the Activator class, or add a dummy tag/activator for the tag, your project should build successfully.