Monday, March 23, 2009

Using Bean Info for Custom Droplets

Overview

Writing a BeanInfo class for a custom droplet has several advantages for your droplet's users
Components of your droplet will appear in the by module view in the DCC browser
The DCC will display the input, output and oparam parameters for your users in the JHTML editor
The DCC will enforce type checking for your parameters
The custom description from your droplet will appear in the component browser

Example 1 : TimeOfDay

The TimeOfDay is a droplet which renders one of three parameters based on the current time, morning, afternoon or evening. The code for TimeOfDay.java is given below. A BeanInfo file ALWAYS has the same name as the bean file, with the addition of 'BeanInfo'. So in our case the bean info java file is TimeOfDayBeanInfo.java.
This example has an optional calendar parameter and the three oparam. There are no output parameters.
Notice that the calendar parameter is typed to java.lang.Calendar while the oparams are defined by atg.servlet.DynamoServlet.

TimeOfDay.javapackage imagescript.atg.droplets;
import javax.servlet.*; // ServletException
import atg.servlet.*; // DynamoServlet
import java.io.*; // IOException
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Calendar;
public class TimeOfDay extends DynamoServlet
{
public TimeOfDay() {}
public void service(DynamoHttpServletRequest req,
DynamoHttpServletResponse res)
throws IOException, ServletException
{
Calendar c = null;
try
{
c = (Calendar)req.getObjectParameter("calendar");
}
catch(ClassCastException e)
{
throw new ServletException(e);
}
if(c == null)
{
c = new GregorianCalendar();
}
int nHour = c.get(Calendar.HOUR_OF_DAY);
if(nHour < 12)
{
req.serviceLocalParameter("Morning", req, res);
}
else if(nHour < 18)
{
req.serviceLocalParameter("Afternoon", req, res);
}
else
{
req.serviceLocalParameter("Evening", req, res);
}
}
}
TimeOfDayBeanInfo.javapackage imagescript.atg.droplets;
import java.beans.*;
import atg.servlet.DynamoServlet;
import atg.droplet.DropletBeanInfo;
import atg.droplet.ParamDescriptor;
public class TimeOfDayBeanInfo extends DropletBeanInfo
{
private final static ParamDescriptor[] sParamDescriptors =
{
new ParamDescriptor("calendar", "Optional: calendar to base the choice on",
java.util.Calendar.class, true, true),
new ParamDescriptor("Morning", "Rendered before noon",
DynamoServlet.class, false, true),
new ParamDescriptor("Afternoon", "Rendered after noon but before 6pm",
DynamoServlet.class, false, true),
new ParamDescriptor("Evening", "Rendered after 6pm",
DynamoServlet.class, false, true)
};
private final static BeanDescriptor sBeanDescriptor =
createBeanDescriptor(TimeOfDay.class, null,
"This servlet renders one of the three "
+"oparams depending on the time of day",
sParamDescriptors,
"ATGSFDroplets");
public BeanDescriptor getBeanDescriptor() {
return sBeanDescriptor;
}
}

Example 2 : output parameters

To define output parameters for an oparams, pass in an array of ParamDescriptors respresenting the output parameters into the ParamDescriptor constructor for the oparam.
The BannerMenu class implements a simple menu which is configured via the DCC, some of the required code is missing from this page for readability, but the essence of the droplet can be gleaned from the source below. For each menu item an oparam is rendered and the href and label output parameters are set.

In the example below, the array sOutputDescriptors defines the href and label output parameters which are available in the currentItem and item oparams. This relationship is expressed by supplying the sOutputDescriptors array to the ParamDescriptor constructor for each of the oparams. You can create different arrays for individual oparams in the same manner.

BannerMenu.javapackage imagescript.atg.droplets;
import atg.servlet.DynamoServlet;
import atg.servlet.*;
import atg.nucleus.naming.ParameterName;
import javax.servlet.*;
import java.io.*;
public class BannerMenu extends DynamoServlet
{
// input
public final static ParameterName URL
= ParameterName.getParameterName("currentPage");
public final static ParameterName TRANSIENT
= ParameterName.getParameterName("isTransient");
// output
public final static ParameterName HREF
= ParameterName.getParameterName("href");
public final static ParameterName LABEL
= ParameterName.getParameterName("label");
// Oparams
public final static ParameterName ITEM
= ParameterName.getParameterName("item");
public final static ParameterName CURRENTITEM
= ParameterName.getParameterName("currentItem");
public void service(DynamoHttpServletRequest pReq,
DynamoHttpServletResponse pRes)
throws ServletException, IOException
{
try
{
if((mItems != null) && (mItems.length > 0))
{
String strURL = pReq.getParameter(URL);
if(strURL != null)
{
int i = strURL.lastIndexOf("/");
strURL = strURL.substring(i);
}
if(isLoggingDebug())
{
logDebug("Base URL:" + strURL);
}
String s = pReq.getParameter(TRANSIENT);
if(s == null)
{
throw new ServletException(
"TRANSIENT must be specified (Profile.transient)");
}
boolean bMember = !(new Boolean(s)).booleanValue();
if(isLoggingDebug())
{
logDebug("Member?:" + bMember);
}
for(int i=0; i < mItems.length; i++)
{
boolean bRender = false;
if(bMember && mItems[i].getForMembers().booleanValue())
{
bRender = true;
}
else if(!bMember && mItems[i].getForNonMembers().booleanValue())
{
bRender = true;
}
if(bRender)
{
pReq.setParameter(HREF.getName(), new String(mItems[i].getURL()));
pReq.setParameter(LABEL.getName(), new String(mItems[i].getLabel()));
if((strURL != null) && strURL.endsWith(mItems[i].getURL()))
{
pReq.serviceLocalParameter(CURRENTITEM,pReq,pRes);
}
else
{
pReq.serviceLocalParameter(ITEM,pReq,pRes);
}
}
else
{
if(isLoggingDebug())
{
logDebug("Skipping " + mItems[i].getLabel());
}
}
}
}
else
{
if(isLoggingInfo())
{
logInfo("No items in BannerMenu");
}
}
}
catch (Exception e)
{
if(isLoggingError())
{
logError(e);
}
}
}
BannerMenuItem[] mItems;
public void setItems(BannerMenuItem[] p) { mItems = p; }
public BannerMenuItem[] getItems(){ return mItems; }
public BannerMenu() {
}
}
BannerMenuBeanInfo.javapackage imagescript.atg.droplets;
import java.beans.*;
import atg.servlet.DynamoServlet;
import atg.droplet.DropletBeanInfo;
import atg.droplet.ParamDescriptor;
public class BannerMenuBeanInfo extends DropletBeanInfo
{
private final static ParamDescriptor[] sOutputDescriptors =
{
new ParamDescriptor("href", "The URL link for the menu item",
String.class, false, false),
new ParamDescriptor("label",
"The text associated with the menu item "
+"(label or image link it's your choice)",
String.class, false, false)
};
private final static ParamDescriptor[] sParamDescriptors =
{
new ParamDescriptor("currentPage",
"The current page URL; usually from `request.getRequestURI()`",
String.class, false, true),
new ParamDescriptor("isTransient",
"The isTransient value from the Profile; bean:Profile.transient",
Boolean.class, false, true),
new ParamDescriptor("item", "Rendered for a menu item",
DynamoServlet.class, false, true, sOutputDescriptors),
new ParamDescriptor("currentItem",
"Rendered for a menu item matching "
+"the supplied currentPage param",
DynamoServlet.class, false, true, sOutputDescriptors)
};
private final static BeanDescriptor sBeanDescriptor =
createBeanDescriptor(BannerMenu.class,
null,
"This servlet renders menu items with a special case "
+"for the menu item of the current page",
sParamDescriptors,
"ATGSFDroplets");
public BeanDescriptor getBeanDescriptor() {
return sBeanDescriptor;
}
}

No comments:

Post a Comment