Droplets are the backbone of front-end content for all ATG applications.  A droplet allows dynamic content to be easily weaved into JavaServer Pages (JSPs).  Because droplets are easy to insert into JSPs, developers without Java knowledge can handle the rendering of dynamic content.

Out of the box, ATG comes with a large selection of droplets for most common tasks like iterations, repository lookups, page linking etc.  When these droplets don’t fit the requirement, customizations are necessary.  Fortunately, custom droplets are very easy to write. The focus of this post is to walk through the steps involved in creating a custom droplet.

The sample droplet will simply say hello to the user on the page using the user’s profile to retrieve their name if it is set.  To begin, I’ll give a high level design, followed by a walk through of each important element in the droplet code for this.  You can find the complete droplet code below.  Add the Java file that comprises that code into the com.test.droplet package and the properties file into /test/droplet for everything to work correctly.

package com.test.droplet;

import atg.core.util.StringUtils;

import atg.servlet.DynamoHttpServletRequest;

import atg.servlet.DynamoHttpServletResponse;

import atg.servlet.DynamoServlet;

import atg.userprofiling.Profile;

import javax.servlet.ServletException;

import java.io.IOException;

import java.text.MessageFormat;

public class SayHelloDroplet extends DynamoServlet {

//input parameters

private static final String PARAM_PROFILE = “profile”;

private static final String PARAM_CURRENT_PAGE = “currentPage”;

//output parameters

private static final String PARAM_MESSAGE = “message”;

private static final String PARAM_ERROR_MESSAGE = “errorMsg”;

//open parameters

private static final String OPARAM_OUTPUT = “output”;

private static final String OPARAM_ERROR = “error”;

@Override

public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

Profile profile = (Profile) pRequest.getObjectParameter(PARAM_PROFILE);

if(profile == null) {

// render error

pRequest.setParameter(PARAM_ERROR_MESSAGE, “The passed in Profile was null.”);

pRequest.serviceParameter(OPARAM_ERROR, pRequest, pResponse);

} else {

String name = (String) profile.getPropertyValue(“firstName”);

if(StringUtils.isBlank(name)) {

name = profile.getRepositoryId();

}

String currentPage = pRequest.getParameter(PARAM_CURRENT_PAGE);

// render output

if(StringUtils.isBlank(currentPage)) {

pRequest.setParameter(PARAM_MESSAGE, MessageFormat.format(“Hello, {0}.”, name));

} else {

pRequest.setParameter(PARAM_MESSAGE, MessageFormat.format(“Hello, {0}, thanks for visiting {1}.”, name, currentPage));

}

pRequest.serviceParameter(OPARAM_OUTPUT, pRequest, pResponse);

}

}

}

High Level Design

There are two sides to examine when trying to comprehend how droplets work.  First, there’s the ATG API side, where we’re actually writing a class to do a custom action.  That part isn’t bad, so we’ll be focusing on the JSP side of things where understanding of droplet syntax is important.  Droplets are declared in the following way:

 

<dsp:droplet name=”/path/to/MyDroplet”>

<dsp:param name=”foo” value=”bar”/>

<dsp:oparam name=”output”>

<dsp:valueof param=”myOutputParam”/>

</dsp:oparam>

<dsp:oparam name=”error”>

<dsp:valueof param=”myErrorParam”/>

</dsp:oparam>

</dsp:droplet>

This sample droplet can be split into a few different elements:

  • Declaration – Every droplet starts with a dsp:droplet tag and a name attribute corresponding to the Nucleus path of the droplet.
  • Input Parameters (optional) – Specified as the first children of the droplet tag using the dsp:param tag.  These are values passed into the droplet that are required for the execution of the particular droplet.
  • Open Parameters – Identified using dsp:oparam tags, these can be thought of as paths the program can flow.  Depending on what happens inside the droplet, one or many open parameters will be serviced.
  • Output Parameters – Values set in the droplet that are passed back to the JSP.  These are set in the JSP as page parameters.

Basic Steps to Writing

Droplets can be confusing at first, but they are extremely simple.  There is a common process that does not change for each droplet.  Here are the simplified steps to writing a droplet:

1. Create a Java class extending atg.servlet.DynamoServlet and overriding the service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throw ServletException, IOException method.

public class SayHelloDroplet extends DynamoServlet

2. Create a matching ATG component for the class.  The scope of the component should be global.

$class=com.test.droplet.SayHelloDroplet

$scope=global

$description=Prints hello to the user

3. Declare the droplet in the JSP

<dsp:page>

    <h1>Sample Droplet</h1>

    <dsp:droplet name=”/test/droplet/SayHelloDroplet”>

        <dsp:param name=”profile” bean=”/atg/userprofiling/Profile”/>

        <dsp:param name=”currentPage” value=”SampleDroplet.jsp”/>

        <dsp:oparam name=”output”>

            <dsp:valueof param=”message”/>

        </dsp:oparam>

        <dsp:oparam name=”error”>

            Error: <dsp:valueof param=”errorMsg”/>

        </dsp:oparam>

    </dsp:droplet>

</dsp:page>

Input Parameters

Input parameters are an optional, but usually used, part of droplets.  They are the way to pass primitives or objects into the droplet.  In the example, the Profile object is the only input parameter.  Input parameters are passed to the droplet using the dsp:param tag from the dsp tag library using one of three variations:

  • Using the value tag to add a raw (or expression language) value: <dsp:param name=”myParam” value=”my value”/>
  • Using the paramtag to pass a page parameter by name: <dsp:param name=”myParam” param=”somePageParam”/>
  • Using the bean tag to use the value of an ATG component as in the example
  • : <dsp:param name=”profile” bean=”/atg/userprofiling/Profile”/>.

On the Java side of things, input parameters are commonly accessed using two methods.  If the parameter being passed in is a String, use pRequest.getParameter(String pParamName).  In the example, the currentPage parameter is passed in and resolved:

String currentPage = pRequest.getParameter(PARAM_CURRENT_PAGE);

Also note, primitive values are usually passed in this way.  They are resolved using Integer.valueOf(String pValue), Boolean.valueOf(String pValue) etc.

If the input parameter passed in is an object, use pRequest.getObjectParameter(String pValue) to resolve the parameter.  In the example, the user’s Profile was retrieved this way:

Profile profile = (Profile) pRequest.getObjectParameter(PARAM_PROFILE);

Output Parameters

After resolving all relevant parameters in the droplet, some backend processing is done.   Make sure all the business logic is removed from the service method and placed into a helper method or class.  After this processing, something can be returned back to the page.  Keep in mind that output parameters are optional.  In this example, an output parameter is used to display the message or error message.  The droplet however could be used to control flow of the JSP.  An example of this is the out of the box Switch droplet that renders different parameters depending on which value the passed in object had.

To set output parameters, use the pRequest.setParameter(String pParameterName, Object pValue) method.  There isn’t anything difficult about setting output parameters.  Three different parameters are set in the example droplet:

// error message

pRequest.setParameter(PARAM_ERROR_MESSAGE, “The passed in Profile was null.”);

// missing currentPage

pRequest.setParameter(PARAM_MESSAGE, MessageFormat.format(“Hello, {0}.”, name));

// has current page

pRequest.setParameter(PARAM_MESSAGE, MessageFormat.format(“Hello, {0}, thanks for visiting {1}.”, name, currentPage));

Output parameters can be retrieved using any tag of choice in the JSP.  Commonly if the parameter will be used later, it is set as a page parameter:

<dsp:getvalueof param=”url” var=”someUrl”/>

Above, is a common piece of code in the ATG SiteLinkDroplet.  The code takes the ‘url’ parameter set in the droplet and sets it in a ‘someUrl’ variable accessible outside of the droplet.

Parameters can also be accessed using dsp:valueof as in the example below.  For any tags nested within the droplet, their param attribute can point to the parameter set in the droplet.

Error: <dsp:valueof param=”errorMsg”/>

Open Parameters

Open parameters are executed one or many times during the droplet’s processing.  The Java code backing the droplet will determine which to show and when.  In the example, the error open parameter was serviced when the Profile passed in was null and the output parameter was shown when processing was successful.

Open parameters are indicated in the droplet by using dsp:oparam tags as shown below.

<dsp:droplet name=”/test/droplet/SayHelloDroplet”>

        <dsp:param name=”profile” bean=”/atg/userprofiling/Profile”/>

        <dsp:param name=”currentPage” value=”SampleDroplet.jsp”/>

        <dsp:oparam name=”output”>

            <dsp:valueof param=”message”/>

        </dsp:oparam>

        <dsp:oparam name=”error”>

            Error: <dsp:valueof param=”errorMsg”/>

        </dsp:oparam>

    </dsp:droplet>

To service an open parameter, call the pRequest.serviceParameter(String pOpenParamName, pRequest, pResponse) method.  Remember, all parameters must be set before calling this method!

pRequest.serviceParameter(OPARAM_ERROR, pRequest, pResponse);

or

pRequest.serviceParameter(OPARAM_OUTPUT, pRequest, pResponse);

Side note:

It may be useful to display the same parameter multiple times in the same droplet.  For example, you might have the task of iterating over a set of items in an order.  This could be done by passing the collection back to the JSP, then using a ForEach droplet to loop through it.  A cleaner approach is to simply loop through the collection in the droplet, rendering an open parameter for each iteration.

Droplet Naming Conventions

If you browse through the out of the box droplets, an unsaid naming convention is followed.  Since out of the box droplets are used heavily, any custom droplets should follow the same naming guidelines.

Input parameter names are usually unique to the function of the droplet.  There are just a few input parameter names reused throughout the out of the box framework:

  • array – Used in droplets like ForEach for when a collection is passed into the droplet.
  • howMany – Used in droplets like ForEach for specifying how many iterations are required

Output parameters also have some common names:

  • element – For droplets that return an object, this is the standard way of naming
  • index – 0-based current iteration count
  • count – 1-based current iteration count
  • errorMsg – An error message

Open parameters can be named custom, but usually they have one of the following names:

  • output – This is the most common open parameter name.  Use this for when the droplet’s processing went as expected.
  • empty – Used when a lookup used in the backend, or a value was empty.
  • error – Used to communicate an error.
  • outputStart – Some out of the box droplets use this as a place to put code before the output parameter
  • outputEnd – Some out of the box droplets use this as a place to put code after the output parameter

It is a great idea to stick with the out of the box naming conventions for open parameters.

Conclusion

The droplet example provided here will print out one of three messages.  If the passed in Profile is null, an error message is displayed.  If the user doesn’t have a first name set, their profile ID is used in place.  Depending on if the currentPage parameter has been set, the correct message is displayed.

Sample DropletHello, 5200000, thanks for visiting SampleDroplet.jsp

Droplets are a strong feature to the front-end of ATG applications.  Using droplets in JSPs provides the ability to easily and dynamically generate content for users.  ATG comes out of the box with a big selection of droplets, but when those aren’t enough it is very easy to write a custom droplet.  Custom droplets are particularly easy to implement because the API isn’t complicated.

The only advanced features not covered here are using the ParameterName class to set parameters for slightly faster performance and the concept of a local parameter versus a standard parameter.  These topics are covered in detail in the ATG Programming Manual.