Alert Source Gear Example - Messenger
Note: This document is presented in follow-along form so that you can
re-create the example by following the steps. If you try this and there's a
problem or a missing step, please send me and email with the details : stujones
@ atg.com
Design Overview
The Messenger gear allows a user to send a string message and a URL as an
alert to the community or to the community leader.
The Messenger Gear has a single shared content view in addition to
a full instanceConfig.
The messages will be dispatched by the gear and picked up by a scenario. The
scenario will dispatch an alert to either the community leader or the community
as a whole, depending on the target information included in the message.
Gear Modes
| Gear Mode |
Display Mode |
URL |
| content |
shared |
/html/shared_content.jsp |
| instanceConfig |
full |
/html/full_instance_config.jsp |
shared_content.jsp
A form to allow the user to specify and send the Alert.
The user can specify a message, an info URL and whether this is a community
wide alert message or just for the community leader.
If the alert is
successfully send a status message is included in the gear.
full_instance_config.jsp
A form to allow the community admin to show or hide alert messages from this
gear in the Alert Gear.
The default will be to show the alert messages in the Alert Gear.
Alert Details
The Messenger gear will only send one alert type MessengerMessage with the
class and JMS type of atg.edu.gears.messenger.MessengerMessage
The atg.edu.gears.messenger.MessengerMessage class will extend atg.portal.alert.GearMessage
expose the following additional properties:
| Message Properties |
| messageString |
string |
required |
A string text message provided by the user |
| infoURL |
string |
optional |
A URL entered by the user to support the message |
| targetType |
string |
required |
One of 'leader' or 'community' |
| sourceProfileName |
string |
required |
The display name of the user who sends the message |
| sourceProfileId |
string |
required |
The profile id of the user who sends the message |
Scenario Info
We'll need a dispatch scenario to handle the alerts : MessengerAlertDispatcher
The MessengerAlertDispatcher scenario will rely on an extension to the
scenario grammar which will add a custom event of type 'Messenger Message'.
The 'Messenger Message' event will have a targetType property
which will either be 'leader' or 'community' and based on this
value the scenario will send and Alert to either the whole community or just the
community leader using the Send Alert action provided by the portal
framework.
Final Configuration
The Messenger gear instance will be added to a community page along with an
Alert gear instance. The Messenger gear will be configured to send messages. The
Alert gear will be configured to show both community and user messages.
Thus when the user sends a community wide message, it will show up in the
Alert gear in the community messages section. If the user is the community
leader, leader messages will show up in the user messages section.
Please note; because alert processing occurs asynchronously (off-thread) the
alerts may not immediately appear in the alert gear, but they should show up in
a matter of minutes at the most.
Implementation Overview
The gear modes will be implemented as jsp pages using
the paf tag library.
In the content mode, the actual message dispatching will be achieved using a request scoped bean
of type atg.edu.gears.messenger.DispatchFormProcessor which will send the
message via the GearMessagePublisher .
DispatchFormProcessor will extract the message properties from the page
using the jsp set property (*) tag. Then will dispatch the message when sendMessage() is called later in the page.
Deployment Overview
J2EE - Configuration
The Messenger gear will be deployed in the Training.messenger module inside
of messenger-app.war.
It will use the context root of /gear/messenger and we'll need the paf tag
library to interact with the portal framework. The dsp and core tag libraries
will come in handy too.
Basically you can copy the configuration of the Portal.contacts gear
application, it's all standard portal app.
Create your application first before you go on to start writing the beans and
jsp pages

Class and Resource File Location
Compiled java components which are only used by the jsp pages in our gears can go in the
classes folder underneath the web apps WEB-INF. In my case that's:
{Dynamo5.6.1}\Training\messenger\j2ee-apps\messenger\messenger-app.war\WEB-INF\classes\package\package\...
Any java classes or resource bundles used by the Dynamo framework,
specifically the JMS or the scenario manager must go in the app-server's
CLASSPATH. On Dynamo the cleanest way to do this is to add a folder underneath
the module folder and modify the META-INF\MANIFEST.MF file to tell Dynamo
to add that directory to the CLASSPATH
Manifest-Version: 1.0
ATG-Config-Path: config/
ATG-Class-Path: classes/
ATG-Required: DAS
ATG-Client-Update-Directory: 5.6.1
ATG-Client-Class-Path: classes/
Now because the scenario editor runs inside the ACC which is an RMI client
application, the scenario extensions also need to be available to the ACC. This
is achieved using the two ATG-Client-XXX directives in the MANIFEST.MF file.
We'll need two main java files; DispatchFormHandler.java and MessengerMessage.java
The DispatchFormHandler.java is only for this
application so it's .class file can go in the WEB-INF\ classes folder. The
MessengerMessage.java
will need to be available for the scenario manager, the alerts system and the
JMS implementation and so it's .class file must go in the global
CLASSPATH;
{Dynamo5.6.1}\Training\messenger\classes\package\package\...To keep things simple for me I'm going to keep the java and the class files
together and compile them in place using javac without the -d
option.
The Gear Manifest File
Being sensible you'll copy one from an existing gear that supports alerts.
Might I suggest the discussion gear's manifest file along with a nice Chianti?
Then modify it to fit the needs of your gear.
The gear manifest for the Messenger gear declares the two gear modes along
with the alert we want to send and the instance parameter 'globalAlertMode'.
globalAlertMode is used by the framework to control whether alerts are
enabled or no for a given gear, so you'll want to make sure you include this.
The message type in the alert tag is the JMSType we'll be using for our alert
in the JMS. Again to keep things simple I'd suggest making this the same as your
message class name.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE portal-manifest PUBLIC "-//Art Technology Group, Inc.//DTD Portal Manifest//EN" "http://www.atg.com/dtds/portal/framework/portal_manifest_1.0.dtd">
<portal-manifest name="Messenger" version="1.0"
author="Stuart Jones">
<gear-definitions>
<gear-definition name="Messenger" version="1.0"
author="Stuart Jones">
<description>A gear to dispatch
messages as alerts</description>
<servlet-context>/gear/messenger</servlet-context>
<dimensions>
<dimension name="height">noPreference</dimension>
<dimension
name="width">narrow</dimension>
</dimensions>
<gear-modes>
<gear-mode name="content">
<display-modes>
<display-mode
name="shared">
<device-output
name="html">/html/shared_content.jsp</device-output>
</display-mode>
</display-modes>
</gear-mode>
<gear-mode name="instanceConfig">
<display-modes>
<display-mode
name="full">
<device-output
name="html">/html/full_instance_config.jsp</device-output>
</display-mode>
</display-modes>
</gear-mode>
</gear-modes>
<instance-parameters>
<parameter name="globalAlertMode" >
<default-value>
yes_locked
</default-value>
</parameter>
</instance-parameters>
<alerts>
<alert-message name="MessengerMessage">
<message-type>atg.edu.gears.messenger.MessengerMessage</message-type>
<default-value>yes_locked</default-value>
<resource-bundle>atg.edu.gears.messenger.MessengerMessageResources</resource-bundle>
</alert-message>
</alerts>
</gear-definition>
</gear-definitions>
</portal-manifest>
The Java Code
MessengerMessage.java - The alert message bean
A simple bean which extends atg.portal.alert.GearMessage. The main thing to
watch for here is that the constructor calls the GearMessage constructor AND set
the message type. If you miss this it won't work at all! :)
package atg.edu.gears.messenger;
import atg.portal.alert.*; // GearMessagePublisher and GearMessage
import atg.portal.framework.*; // GearEnv
public class MessengerMessage extends GearMessage
{
private String mMessageString;
private String mInfoURL;
private String mTargetType;
private String mSourceProfileId;
private String mSourceProfileName;
public MessengerMessage () { }
public MessengerMessage (GearEnvironment pGearEnv,
String pMessageString,
String pInfoURL,
String pTargetType,
String pSourceProfileId,
String pSourceProfileName)
{
super(pGearEnv, "atg.edu.gears.messenger.MessengerMessage");
mMessageString = pMessageString;
mInfoURL = pInfoURL;
mTargetType = pTargetType;
mSourceProfileId = pSourceProfileId;
mSourceProfileName = pSourceProfileName;
}
public String getSourceProfileId() { return mSourceProfileId; }
public void setSourceProfileId(String p)
{
mSourceProfileId = p;
}
public String getSourceProfileName() { return mSourceProfileName; }
public void setSourceProfileName(String p)
{
mSourceProfileName = p;
}
public String getMessageString() { return mMessageString; }
public void setMessageString(String p)
{
mMessageString = p;
}
public String getInfoURL() { return mInfoURL; }
public void setInfoURL(String p)
{
mInfoURL = p;
}
public String getTargetType() { return mTargetType; }
public void setTargetType(String p)
{
mTargetType = p;
}
}
DispatchFormHandler.java - the 'form handler
A bean with a bit of smarts. Used as a request scoped bean from the jsp
page.
First the bean collects the form submission data in properties using the
jsp:setProperty tag.
Then a call to the sendMessage() method will dispatch the alert message as
long as the gear instance parameters have been otherwise configured, see the
getAlertsEnabledForThisInstance method for more information on that.
A bit of JNDI smarts is needed to find the GearMessagePublisher and I've
added some simple logging capabilities to trace what is happening.
package atg.edu.gears.messenger;
import java.util.Date; // date/time for loggind
import javax.naming.*; // JNDI lookup
import atg.portal.alert.*; // GearMessagePublisher and GearMessage
import atg.portal.framework.*;
public class DispatchFormProcessor
{
// Properties (usually from form post to send the alert message)
private String mMessageString;
private String mInfoURL;
private String mTargetType;
private String mResultInfo;
// Location of the GearMessagePublisher
private String mPublisherName = "dynamo:/atg/portal/alert/GearMessagePublisher";
// Cache of publisher
private GearMessagePublisher mPublisher = null;
// Debug channel controller
private static boolean sLogDebug = true; // false;
public DispatchFormProcessor () { log("Constructor");}
public String getMessageString() { return mMessageString; }
public void setMessageString(String p)
{
log("setMessageString(" + p + ")");
mMessageString = p;
}
public String getInfoURL() { return mInfoURL; }
public void setInfoURL(String p)
{
log("setInfoURL(" + p + ")");
mInfoURL = p;
}
public String getTargetType() { return mTargetType; }
public void setTargetType(String p)
{
log("setTargetType(" + p + ")");
mTargetType = p;
}
public String getPublisherName() { return mPublisherName; }
public void setPublisherName(String p)
{
log("setPublisherName(" + p + ")");
mPublisherName = p;
}
public String getResultInfo() { return mResultInfo; }
public boolean sendMessage(GearEnvironment gearEnv, String profileId, String profileName)
{
boolean bResult = false;
mResultInfo = "";
if(getAlertsEnabledForThisInstance(gearEnv))
{
try
{
getPublisher().writeMessage(createAlertMessage(gearEnv, profileId, profileName));
mResultInfo = "Alert message sent succesfully";
bResult = true;
}
catch(Exception e)
{
mResultInfo = e.getClass().getName() + " : " + e.getMessage();
}
}
else
{
mResultInfo = "Alert message not sent, alerts disabled in instance config";
bResult = true; // not an error really since the messages are explicitly disabled
}
log(mResultInfo);
return bResult;
}
////////////////////////////////////////////////////////
// Utilities
//
private boolean getAlertsEnabledForThisInstance(GearEnvironment gearEnv)
{
boolean bResult = true;
// globalAlertMode
//
// We specified this instance parameter in the gear manifest and
// it's set for us in the paf:handleAlertConfig, but if no-one has used
// that that ie: the instance config page has not been visited
// the parameter is still unset and the default value from the
// manifest (Stored are read back from the gear definition's instance
// parameters list)
// So I'm using the logic that we want to send the messages by default
// and yes_locked was the default value I specified in the gear manifest
//
// So if it's no then we won't send the messages
//
String value = gearEnv.getGearInstanceParameter("globalAlertMode");
log("Reading 'globalAlertMode' setting : " + value);
if((value != null) && value.equals("no"))
{
bResult = false; // disable the event sending since no-one is lsit
log("Disabling alert sending for this gear");
}
return bResult;
}
private GearMessage createAlertMessage(GearEnvironment env, String sourceProfileId, String sourceProfileName)
{
MessengerMessage result = new MessengerMessage(env,
getMessageString(),
getInfoURL(),
getTargetType(),
sourceProfileId,
sourceProfileName);
return result;
}
private GearMessagePublisher getPublisher()
{
ensurePublisher();
return mPublisher;
}
private boolean ensurePublisher()
{
boolean bResult = false;
if(mPublisher == null)
{
log("Looking up publisher (JNDI) at '" + getPublisherName() + "'");
try
{
InitialContext ctx = new InitialContext();
mPublisher = (GearMessagePublisher) ctx.lookup(getPublisherName());
}
catch(Exception e)
{
log("Exception during lookup " + e.getMessage());
}
}
bResult = (mPublisher != null);
return bResult;
}
private void log(String s)
{
if(sLogDebug)
{
Date d = new Date();
String prefix = getClass().getName() + " : " + d.toString() + " : ";
System.out.println(prefix + s);
}
}
}
The JSP Pages
Safely placed in the html folder of the messenger-app.war folder. You can edit
these files using the ACC's new jsp editor available in the J2EE Tools section
and under the 'Pages and Components' option 'J2EE Pages'.

full_instance_config.jsp - Instance config for alert preferences
<!-- instanceConfig for Messenger Gear -->
<%@ taglib uri="/core-taglib" prefix="core" %>
<%@ taglib uri="/paf-taglib" prefix="paf" %>
<%@ taglib uri="/dsp" prefix="dsp" %>
<dsp:page>
<paf:InitializeGearEnvironment id="gearEnv">
<%
String origURI=gearEnv.getOriginalRequestURI();
String gearID=gearEnv.getGear().getId();
String pageID = request.getParameter("paf_page_id");
String pageURL = request.getParameter("paf_page_url");
String communityID = request.getParameter("paf_community_id");
String gearName=gearEnv.getGear().getName(response.getLocale());
String editGearURL = "";
String communityGearsURL = "";
%>
<core:CreateUrl id="returnURL" url="community_gears.jsp">
<core:UrlParam param="paf_community_id" value='<%= request.getParameter("paf_community_id") %>'/>
<core:UrlParam param="paf_page_id" value='<%= request.getParameter("paf_page_id") %>'/>
<core:UrlParam param="paf_page_url" value='<%= request.getParameter("paf_page_url") %>'/>
<% communityGearsURL = returnURL.getNewUrl(); %>
</core:CreateUrl>
<core:CreateUrl id="returnURL" url="community_edit_gear_details.jsp">
<core:UrlParam param="paf_community_id" value='<%= request.getParameter("paf_community_id") %>'/>
<core:UrlParam param="paf_page_id" value='<%= request.getParameter("paf_page_id") %>'/>
<core:UrlParam param="paf_page_url" value='<%= request.getParameter("paf_page_url") %>'/>
<% editGearURL = returnURL.getNewUrl(); %>
</core:CreateUrl>
<jsp:useBean id="alertFormInput" scope="request" class="atg.portal.admin.AlertConfigBean">
<jsp:setProperty name="alertFormInput" property="*"/>
</jsp:useBean>
<!-- handle the form if it was filled in -->
<core:If value="<%= alertFormInput.getHandleForm() %>">
<paf:handleAlertConfig id="alertConfResult" formData="<%= alertFormInput %>" gearEnv="<%= gearEnv %>">
<core:ExclusiveIf>
<core:If value="<%= alertConfResult.getSuccess() %>" >
<core:Redirect url="<%= editGearURL %>"/>
</core:If>
<%-- if not, display errors --%>
<core:DefaultCase>
<%=alertConfResult.getErrorMessage()%>
</core:DefaultCase>
</core:ExclusiveIf>
</paf:handleAlertConfig>
</core:If>
<core:CreateUrl id="formURL" url="<%= origURI%>">
<form ACTION="<%= formURL.getNewUrl() %>" METHOD="POST">
</core:CreateUrl>
<%--
Sets form encoding to the same as the encoding of this response.
This hidden field will let the form processing code know what the character encoding of the POSTed data is.
--%>
<input type="hidden" name="_dyncharset" value="<%= response.getCharacterEncoding() %>">
<input type="hidden" name="handleForm" value="true">
<input type="hidden" name="atg.paf.RedirectNoIncludeURL" value="messenger-url">
<input type="hidden" name="paf_gear_id" value="<%= gearID %>">
<input type="hidden" name="paf_dm" value="full">
<input type="hidden" name="paf_gm" value="instanceConfig">
<input type="hidden" name="paf_page_id" value="<%= pageID %>"/>
<input type="hidden" name="paf_page_url" value="<%= pageURL %>"/>
<input type="hidden" name="paf__url" value="<%= pageURL %>"/>
<input type="hidden" name="paf_community_id" value="<%= communityID %>"/>
<table CELLSPACING="0" width="60%" cellpadding="2" border="1">
<tr>
<td width='150' align="left">
<a href="<%=communityGearsURL%>" style="text-decoration:none">Back to community gears</a><br>
</td>
<td width='150' align="left">
<a href="<%=editGearURL%>" style="text-decoration:none">Back to edit gear</a><br>
</td>
</tr>
<tr>
<td colspan='2' align="left">
<font class="large_bold">Alert Preferences Configuration <%= gearName %></font>
</td>
</tr>
<% String globalAlertMode = gearEnv.getGearInstanceParameter("globalAlertMode"); %>
<tr>
<td colspan='2' align="left">
<core:exclusiveIf>
<core:if value='<%= globalAlertMode.equals("yes_locked") %>'>
<input type="radio" name="gearAlertPref" value="yes_locked" checked><font class="small" color="#000000"> Show messages from this gear (yes_locked)</font>
</core:if>
<core:defaultCase>
<input type="radio" name="gearAlertPref" value="yes_locked"><font class="small" color="#000000"> Show messages from this gear(yes_locked)</font>
</core:defaultCase>
</core:exclusiveIf>
</td>
</tr>
<tr>
<td colspan='2' align="left">
<core:exclusiveIf>
<core:if value='<%= globalAlertMode.equals("no") %>'>
<input type="radio" name="gearAlertPref" value="no" checked><font class="small" color="#000000"> Hide messages from this gear and don't send any more (no)</font>
</core:if>
<core:defaultCase>
<input type="radio" name="gearAlertPref" value="no"><font class="small" color="#000000"> Hide messages from this gear and don't send any more (no)</font>
</core:defaultCase>
</core:exclusiveIf>
</td>
</tr>
<tr>
<td colspan='2' align="left">
<INPUT type="submit" value="update"> </td>
</tr>
</table>
</form>
</paf:InitializeGearEnvironment>
</dsp:page>
<!-- end of instanceConfig for Messenger Gear -->
shared_content.jsp - Form to send off alert messages
<!-- shared content mode for Messenger Gear -->
<%@ taglib uri="/core-taglib" prefix="core" %>
<%@ taglib uri="/paf-taglib" prefix="paf" %>
<%@ taglib uri="/dsp" prefix="dsp" %>
<paf:includeOnly/>
<dsp:page>
<dsp:importbean bean="/atg/userprofiling/Profile"/>
<paf:InitializeGearEnvironment id="gearEnv">
<%
// Gather environment settings
String origURI=gearEnv.getOriginalRequestURI();
String activeGearID = request.getParameter("paf_gear_id");
String gearID=gearEnv.getGear().getId();
boolean bIAmActiveGear = gearID.equals(activeGearID);
String highlightTextColor = "000000";
String highlightBGColor = "cccccc";
String defaultTargetType = "leader";
String defaultInfoURL = "http://www.atg.com/";
String defaultMessageString = "Hello World";
String sourceProfileName = "Hello"; // Default for form display
String sourceProfileId = "";
%>
<%-- Extract profile bean values --%>
<dsp:getvalueof id="DSPsourceProfileName" idtype="java.lang.String" bean="Profile.itemDisplayName">
<% sourceProfileName = DSPsourceProfileName; %>
</dsp:getvalueof>
<dsp:getvalueof id="DSPsourceProfileId" idtype="java.lang.String" bean="Profile.repositoryId">
<% sourceProfileId = DSPsourceProfileId; %>
</dsp:getvalueof>
<%-- if form submitted, process the input --%>
<core:If value='<%= bIAmActiveGear %>'>
<%-- Get the form parameters --%>
<jsp:useBean id="myDispatchFormProcessor" scope="request" class="atg.edu.gears.messenger.DispatchFormProcessor">
<jsp:setProperty name="myDispatchFormProcessor" property="*"/>
<% myDispatchFormProcessor.sendMessage(gearEnv, sourceProfileId, sourceProfileName);
defaultTargetType = myDispatchFormProcessor.getTargetType();
defaultInfoURL = myDispatchFormProcessor.getInfoURL();
defaultMessageString = myDispatchFormProcessor.getMessageString();
%>
<p><font color='<%= highlightTextColor %>'><%= myDispatchFormProcessor.getResultInfo() %></font></p>
</jsp:useBean><%-- DispatchFormProcessor --%>
</core:If>
<p>
<form method='post' action='<%= origURI%>'>
<table border="1" cellspacing="0">
<tr>
<td colspan="2" valign="top" align="left"><b><%= sourceProfileName %>, send an alert</b></td>
</tr>
<tr>
<td valign="top" align="left">To</td>
<td valign="top" align="left">
<input type="radio" value="community" <%= defaultTargetType.equals("community") ? "checked" : "" %> name="targetType">Whole community
<p><input type="radio" value="leader" <%= defaultTargetType.equals("leader") ? "checked" : "" %> name="targetType">Community leader</p>
</td>
</tr>
<tr>
<td valign="top" align="left">URL</td>
<td valign="top" align="left"><input type="text" name="infoURL" size="36" value="<%= defaultInfoURL %>"></td>
</tr>
<tr>
<td valign="top" align="left">Message:</td>
<td valign="top" align="left"><textarea rows="5" name="messageString" cols="30"><%= defaultMessageString %></textarea></td>
</tr>
<tr>
<td valign="top" align="left">
<input type='hidden' name='paf_gear_id' value='<%= gearID %>'/>
<input type="hidden" name="_dyncharset" value="<%= response.getCharacterEncoding() %>">
</td>
<td valign="top" align="left"><input type="submit" name="<%= gearID %>_submit" value="Send!"></td>
</tr>
</table>
</form>
</paf:InitializeGearEnvironment>
</dsp:page>
<!-- end of shared content mode for Messenger Gear -->
Alert Registration
The alert listed in the gear manifest file, it relies on a resource file
to describe how the alert should be displayed to the users.
The file is in the global classpath so for me that's:
C:\ATG\Dynamo5.6.1\Training\messenger\classes\atg\edu\gears\messenger
MessengerMessageResources.properties
# These resources should be localized.
atg_flags=i18n,l10n
#
# Web displayable string that is used for the alert notification. The
# place holders are replaced by properties retrieved from the message bean.
#
alertDisplayString={0} (id:{6}) sent you the following message from the {1} gear in the {2} community.<BR>Check out <A HREF="{3}">{3}</A> for more information!<BR><BLOCKQUOTE>{4}</BLOCKQUOTE>
#
# Properties that are used to format the unformatted alertDisplayString above.
# Delimited by a comma without any spaces.
#
alertPropertyNames=sourceProfileName,gearName,communityName,infoURL,messageString,sourceProfileId
#
# The email template file that will be used to create email content
# for the targeted email. Should be located in $DYNAMO_HOME/doc
#
alertEmailTemplate=/Training/email/MessengerMessageEmail.jhtml
Scenario Server Integration Work
NOTE: The scenario integration work belongs in the config / classes folders of the Messenger
module so make sure that's where you put all these files!
JMS Message Registry
Adding the new MessengerMessage to the JMS message registry allows JMS
clients to find out the class of the message from the JMS type. The addition is accomplished by
adding a dynamoMessagingSystem.xml file to the modules config layer. You can use
resource bundles here to localize the labels, I'll skip that for now.
<?xml version="1.0" encoding="utf-8"?>
<dynamo-message-system>
<!-- message registry definitions -->
<message-registry>
<message-family>
<message-family-name>
messenger-gear
</message-family-name>
<message-type>
<jms-type>
atg.edu.gears.messenger.MessengerMessage
</jms-type>
<message-class>
atg.edu.gears.messenger.MessengerMessage
</message-class>
<message-context>
session
</message-context>
<display-name>
MessengerMessage
</display-name>
<description>
Message sent out by the Messenger Gear to be sent out as an alert.
</description>
</message-type>
</message-family>
</message-registry>
</dynamo-message-system>
Scenario Manager Grammar Extension
This task allows the ScenarioManager to present our Alert message to the user
as an 'Event' in the scenario manager. It's a little fiddly but is mostly copy
and paste, either from the calendar gear or from here (lucky you!)
ScenarioManager.xml
Register the grammar extension class with the ScenarioManager. The portions
you need to change for your application are shown in bold
<?xml version="1.0" encoding="ISO-8859-1" ?>
<scenario-manager-configuration>
<grammar-registry>
<grammar-extension-class>
atg.edu.gears.messenger.MessengerGrammarExtension
</grammar-extension-class>
</grammar-registry>
</scenario-manager-configuration>
MessengerGrammarExtension.java
Locates our grammar extension xml file and is in the global CLASSPATH. The
portions you need to change for your application are shown in bold
package atg.edu.gears.messenger;
import atg.ui.scenario.expression.DefaultGrammarExtension;
public class MessengerGrammarExtension extends DefaultGrammarExtension
{
public MessengerGrammarExtension()
{
super("atg.edu.gears.messenger.messenger-expression-grammar");
}
}
messenger-expression-grammar.xml
Describes our event names for the scenario server, this file is placed in the classpath, next to the
MessengerGrammarExtension class in this case. The portions you need to change
for your application are shown in bold. Things can get much more
complicated than this, for example we might add conditional sequence items for
our new event.
For more details check out Chapter 19 of the Personalization
Programming Guide, Configuring the ATG Expression Editor.
<?xml version="1.0" encoding="utf-8"?>
<?xcl-stylesheet resource="atg/ui/expreditor/xcl/grammar.xsl"?>
<context serializable="true">
<include template="atg.portal.scenario.expression.expression-grammar"/>
<sequence id="event-message-atg.edu.gears.messenger.MessengerMessage">
<attribute name="icon">
<icon path="atg/ui/scenario/images/generic-event.gif"/></attribute>
<attribute name="eventType" value="atg.edu.gears.messenger.MessengerMessage"/>
<attribute name="eventContext" value="request"/>
<xml-template>
<event-name>atg.edu.gears.messenger.MessengerMessage</event-name>
</xml-template>
<token><description>Messenger Message</description></token>
<rule name="portal-event-filter"/>
</sequence>
</context>
The Dispatch Scenario
NOTE: These need to be in the gear's module's config layer, so when you are working in the ACC be sure to set the Update Layer to the
Messenger gear's module's config folder!!
NOTE: If the scenario editor won't fire up and you get class not found
errors check that your files are compiled, correctly named, are in the
appropriate classes folder and that the that
ATG-Client-Class-Path: classes/
entry is correct in your modules MANIFEST.MF file.
In this case depending on the value of the targetType property of the MessengerMessage
bean we'll dispatch the alert to either the community leader or to the community
as a whole.

Don't forget to enable your scenario!
Review
Files on Disk
This is what I have at this point under my messenger module folder, check the
location of your class files and that you have the scenario in this layer.
You
might need to move the dispatch scenario's .sdl file from the localconfig
layer.
C:\ATG\Dynamo5.6.1\Training\messenger

Test the Gear in a Community
To be on the safe side stop Dynamo and restart it with your module on the command line
something like:
bin\startDynamo -m Portal.demoportal Training.messenger
Now use the portal administration UI to install the Messenger Gear by
uploading the messenger-gear-manifest.xml file. Ensure there are no errors!
Create a new Test community using the portal admin UI.
Add a community leader and log is as them
Add the Messenger Gear and the Alert Gear to an new empty page

Check the configuration of both gears to make sure that
- The Messenger gear's 'Alert Gear Preference' is set to yes_locked,
this will use your new instanceConfig mode:

- The Alert gear is instanceConfig enables community and user alerts,
you can disable aggregated community alerts for this test. The instance
config of the Alert Gear should look something like this:

View the community page and send two messages, one to the community and one
to the community leader. Check that they show up in the alerts gear.
Check the ATG log for errors and that your DispatchFormProcessor is logging,
(you can turn this off when you have everything working)
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : Constructor
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : setMessageString(Hello World)
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : setInfoURL(http://www.atg.com/)
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : setTargetType(leader)
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : Reading 'globalAlertMode' setting : yes_locked
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : Looking up publisher (JNDI) at 'dynamo:/atg/portal/alert/GearMessagePublisher'
DispatchFormProcessor : Thu Apr 04 15:56:12 PST 2002 : Alert message sent succesfully
Logged in as the community leader this is what we should see
 |
The community wide message shows up here |
| The community leader message shows up here |
|