1.
What are the areas you have worked on in
ATG?
2. What
is a Nucleus?
Nucleus is the ATG
container for components, provides a hierarchical name space each component has a
unique full name so that pages and other components reference it, creates and
initializes component instance on request Decouples code from configuration and
manages component scope.
Any Java object with an empty constructor can
act as a Component in Nucleus,
so writing a new Nucleus component is as easy as writing a Java class. Nucleus
components are standard JavaBeans, each with an accompanying .properties file,
storing configuration values Nucleus sets the configured values on each new
instance of a component. There can be many instances of a component. In
each case, the configured values in the .properties file become the initial
values for properties of the “live” component. After initialization, the
live values may change, depending on usage of the particular property.
Nucleus is Oracle
ATG Web Commerce’s component model for building applications from JavaBeans.
Nucleus lets you assemble applications through simple configuration files that
specify what components are used by the application, what parameters are used
to initialize those components, and how those components hook up to each other.
Nucleus by itself
provides no application-specific functions. The JavaBean components implement
all of an application’s functionality. Nucleus is the mechanism that gives
those components a place to live, and a way for those components to find each
other.
A Nucleus serves two purposes:
·
It is the root of a
NameContext hierarchy, and
·
It implements the
policies for resolving names in the hierarchy.
Running
Nucleus
To use ATG platform functionality, a Web
application needs to start Nucleus by invoking
NucleusServlet
. This servlet does
not need to have any paths mapped to it, but must have the load-on-startup
flag set to 1 so
that it runs before any other ATG component. The web.xml
file in atg_bootstrap.war
includes the
following lines:<servlet>
<servlet-name>NucleusServlet</servlet-name>
<servlet-class>atg.nucleus.servlet.NucleusServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The
NucleusServlet
creates an instance
of Nucleus and sets it as an attribute of the web application. The Nucleus
instance can be retrieved using the Nucleus.getGlobalNucleus()
method.
Note: When you declare
servlets in
web.xml
, you can use
optional load-on-startup
tags to determine
the order the servlets are called. If you do not use these tags, the servlets
are called in the order that they appear in web.xml
. Because NucleusServlet
must run first, its load-on-startup
value must be 1, as
in the example above.
Starting a Nucleus Component
When
you start up an application, Nucleus reads the configuration path, which is a
list of directories to use to find configuration files. Within one of those
directories is a file called Nucleus.properties that contains the name of the
first component to create. In the standard ATG platform configuration, the
start of the Nucleus.properties file looks like
this:
$class=atg.nucleus.Nucleus
initialServiceName=/Initial
initialServiceName=/Initial
You
can view the properties of the Nucleus component by opening the / component in
the ATG Control Center Components by Path window. The initialServiceName property
instructs Nucleus to configure and start up its initial service using Initial.properties, which in the
standard ATG platform configuration looks like this:
$class=atg.nucleus.InitialService
initialServices=\
/atg/Initial,\
VMSystem,\
/atg/dynamo/StartServers
3.
Difference between dsp: include and
jsp:include?
Dsp imports all objects of type class also, where as
jsp imports only primitive types.
Jsp includes are dynamic where as dsp include are for
data which is smaller than 64 kb.
ATG created the DSP tag library as a mechanism for accessing all data types, including those that exist in ATG’s Nucleus framework. Other functions provided by these tags manage transactions and determine how data is rendered in a JSP. It’s best to use tags from the DSP tag library only for tasks that involve Dynamo Application Framework (DAF) resources. Dsp tag support for the passing of object parameters between pages. In particular, use dsp:include rather than jsp:include, and use dsp:param rather than jsp:param.
ATG created the DSP tag library as a mechanism for accessing all data types, including those that exist in ATG’s Nucleus framework. Other functions provided by these tags manage transactions and determine how data is rendered in a JSP. It’s best to use tags from the DSP tag library only for tasks that involve Dynamo Application Framework (DAF) resources. Dsp tag support for the passing of object parameters between pages. In particular, use dsp:include rather than jsp:include, and use dsp:param rather than jsp:param.
4.
What is Formhandlers?
Form handlers evaluate the validity of form data before
it is submitted, check for errors, and determine what action to take—for
example, submit the data, direct the user to a different page, and display an
error message. Often when you use a form handler, the form input fields are
associated with properties of the form handler rather than the component you
ultimately want to modify. For example, your form might include this tag:
<dsp:input type="text"
bean="MyFormHandler.age"/>
When the form is submitted, a method of MyFormHandler
associated with the age property is invoked. Depending on how this method is
written, it might validate the data and then set the value of Person1.age, or
use the data to fill in a record in a database.
A form handler class must include one or more handler
methods. A handler method is typically invoked when the user clicks the submit
button, and handles the processing of the form. Depending on the purpose of the
form handler, it can have several different handler methods that each perform a
different operation. For example, a form handler that works with user profiles
might have separate handler methods for creating the profile, modifying the
profile, and logging the user in.
Following are the tasks assigned to Form Handlers by
ATG :
·
Validate data before it is submitted.
·
Detect missing information and display
appropriate messages to the user.
·
Direct users to different pages depending
on form submission results.
·
Read and write database or repository data.
Subclassing
ATG Form Handlers
Oracle ATG Web
Commerce form handler classes all implement the interface
atg.droplet.DropletFormHandler
. Three form handler
base classes implement this interface:
EmptyFormHandler
atg.droplet.EmptyFormHandler
implements the DropletFormHandler
interface and
provides empty implementations of the methods in this interface.
GenericFormHandler
atg.droplet.GenericFormHandler
extends EmptyFormHandler
. It provides
simple implementations of DropletFormHandler
interface methods
and adds basic error handling logic. If errors occur in processing a form that
uses GenericFormHandler
, the errors are
saved and exposed as properties of the form handler component.
TransactionalFormHandler
atg.droplet.TransactionalFormHandler
extends atg.droplet.GenericFormHandler
; it treats the
form processing operation as a transaction. Although this form handler methods
are processed discretely, their results are saved simultaneously. The
transaction management occurs in the beforeGet
and afterGet
methods. This
establishes the transaction before any of properties are set or handler methods
are called, rather than in the handler methods themselves.
Handler
Methods
The
handleX
method is passed
the request and response objects that encapsulate the request.public boolean handleX (atg.servlet.DynamoHttpServletRequest request,
atg.servlet.DynamoHttpServletResponse response) throws IOException, ServletException
Handler Method Returns
The handler method
returns a Boolean value, which indicates whether to continue processing the
rest of the page after the handler is finished:
Return
value
|
Action
|
false |
No
further values are processed process after the handler is called, and the
rest of the page is not served. For example, a handler that redirects the
user to another page should return
false . |
true |
Normal
processing of the remaining values continues, and the page specified by the
form’s
action attribute is
served. |
As mentioned
earlier, Oracle ATG Web Commerce form handlers typically implement the
interface
DropletFormHandler
. This interface
has the following methods, which are called at specific points as the form is
processed:
Method
|
When
called:
|
beforeSet |
Before
any
setX methods are
called |
afterSet |
After
all
setX methods are
called |
beforeGet |
Before
any input tags that reference this component are rendered
|
afterGet |
After
page rendering is complete, before the socket is closed
|
handleFormException |
If
an exception occurs when trying to call the
setX method of a form |
The
beforeGet
and afterGet
methods are called
only when the page is rendered, not when the form is submitted. The beforeSet
and afterSet
methods are called
only when the form is submitted, not when the page is rendered. It is possible
to have all four of these methods called on the same page.
OOTB FormHandlers
ATG provides hundreds of readymade form handlers for
performing all sorts of tasks, like
·
updating a customer
profile(CommerceProfileFormHandler),
·
managing your shopping
cart(CartModifierFormHandler),
·
checking out(ExpressCheckoutFormHandler),
or
·
interacting with a
repository(RepositoryFormHandler).
Following are the form handler component properties to
handle form errors/exceptions:
·
formError --> Boolean that is set to
true if any errors occur during form processing.
·
formExceptions --> A vector of the exceptions that occur
during form processing. If your form
handler is session-scoped, clear the formExceptions property after you display
errors to the user.
·
propertyExceptions --> A read-only property that returns a
Dictionary of subproperties, one for each property set by the form. For each
property that generates an exception, a corresponding subproperty in the
propertyExceptions Dictionary contains that exception
Use the checkFormRedirect(String pSuccessURL, String
pFailureURL, DynamoHttpServletRequest pRequest, DynamoHttpServletResponse
pResponse) method of GenericFormHandler to redirect to a url from the
formhandler on a success/error cases. A handler that redirects the user to
another page should return false.
The atg.droplet.GenericFormHandler class (and any
subclass of GenericFormHandler you write) includes a handleCancel method for
implementing Cancel buttons in forms. This method redirects to the URL
specified in the form handler’s cancelURL property.
When a dsp:setvalue tag is rendered for a form handler
property, it invokes the setX and handleX methods of the form handler (if the
methods exists).
A form handler component should be either request-
scoped or session-scoped. When your form handler spans several pages, such as
in a multi-page registration process, you want the session-scoped form handler.
It is especially important to clear error messages to ensure they do not appear
in other forms where they are not relevant.
5.
What is Droplet?
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.
Create a matching ATG component for the
class. The scope of the component should be global.
SayHelloDroplet.properties
$class=com.test.droplet.SayHelloDroplet
$scope=global
$description=Prints
hello to the user
SayHelloDroplet.java
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);
}
}
}
sampleDroplet.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”/>.
Output
Parameters
To set output parameters, use the
pRequest.setParameter(String pParameterName, Object pValue) method.
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.
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);
or you can use request.serviceLocalParameter("output", request, response);
Local
Parameters
You might want to create parameters that are visible
only locally to an ATG servlet bean.
In that case, use the getLocalParameter(String
paramName) and serviceLocalParameter(String paramName, ServletRequest,
ServletResponse) methods.
These methods return only values that are defined in
the current frame for this invocation of the ATGservlet bean. This includes
parameters passed to the ATG servlet bean between the open and close
dsp:droplet tags and parameters defined at the top level of the called ATG
servlet bean.
For example:
<dsp:param
name="notLocalForA" value="x"/>
<dsp:droplet
name="A">
<dsp:param
name="localForA" value="y"/>
</dsp:droplet>
In this example notLocalForA is not local for the ATG
servlet bean A, and localForA is local.
6.
Signature of all class, method related to
Formhandlers/Droplet?
See
Formhandlerand Droplet’s’s QA.
7.
What is Component?
Components in ATG are a public java class with
appropriate properties with set/get methods. Additionally a component comes
with .properties file that specify the class name and the scope and also any
default values. The properties file also contains any dependency injections of
other components. This .properties file must be placed under CONFIGPATH of the
ATG.
The name of the component is the full path name of the
.properties file under the configpath starting with a “/”. For example,
/com/vam/firstbean. CONFIGPATH variable is computed dynamically during startup
based on the modules started, their order of startup and based on the entry in
the MANIFEST.MF file of every module started.
Use of components gives following advantages.
•
Code reusability
•
Reduced development time
•
Container independent
•
Entire application behavior can be changed
by modifying one/some of the components.
Note:
In ATG, a component have one of the 3 scopes i.e. Global, Session, Request.
Create / Modify Components
We can create / modify component
and configure initial properties by
–
Using the eclipse ATG component
browser plug-in.
–
Using ATG Control Center (ACC)
browser.
–
Manually by editing the
.properties file.
Using any of the above approach,
we can browse components, set properties (single and multi-value), link /
unlink components.
Public
Constructor with No Arguments
Nucleus can create
a component automatically from a properties file only if the component class is
declared public and it implements a public constructor with no arguments.
Any Java class with a constructor that takes no
arguments can be instantiated as a Nucleus component, which gives you a wide
degree of latitude when you create component classes. However, these classes
should implement certain interfaces that give components access to a number of
Nucleus capabilities, such as automatic creation, configuration, and
notifications.
The easiest way to implement these interfaces is to
subclass atg.nucleus.GenericService, which implements all interfaces described
in the following sections. However, your class might already extend some other
class, thereby preventing you from extending GenericService. In this case, your
class must implement the necessary interfaces.
Creating a
HelloWorld component: That just appears in DynAdmin
HelloWorldComponent.java
package com.buddha.components;
import atg.nucleus.GenericService;
import atg.nucleus.ServiceException;
public class HelloWorldComponent extends GenericService {
public String firstStr = "Dummy Value"; /* This value will be overwritten */
public String getFirstStr() {
return firstStr;
}
public void setFirstStr(String firstStr) {
this.firstStr = firstStr;
}
@Override
public void doStartService() throws ServiceException {
super.doStartService();
System.out.println("Hello ATG Component!");
}
@Override
public void doStopService() throws ServiceException {
super.doStopService();
System.out.println("Hello ATG Component! Stops now!");
}
}
Manifest.MF
Manifest-Version: 1.0
ATG-Required: DafEar.Admin
ATG-Config-Path: config/
ATG-Class-Path: ./bin/
HelloWorldComponent.properties
$class=com.buddha.components.HelloWorldComponent
firstStr=HelloWorld
Build the
project and copy the project folder into ${DYNAMO_ROOT} and run the following
command to generate an ear file of your project and deploy it in your jboss
server.
runAssembler.bat -jboss HelloWorld.ear -m EXP_HelloATGComponentWorld
Navigate to Dyn/Admin and search for the component
HelloWorldComponent
and click on the
component listed in the search results.
You can observe the log as something like this
21:53:00,485 INFO [stdout]
(http-/0.0.0.0:8080-1:ipaddr=127.0.0.1;path=/dyn/admin/nucleus//com/buddha/components/HelloWorldComponent;sessionid=gT4bmHj5WKs1Rf85GN0Z+9Qu)
Hello ATG Component! This line is generated because of the sysout in our
doStartService();
8.
What is Scope of Component?
An application component can be set to one of the
following scopes:
•
Global: Component is shared among all
users.
•
Session: Separate instances of the
component are provided to each user.
•
Request: Separate instances of the
component are provided to each active request.
•
Window: Separate instances of the component
are provided to each browser window.
A request-scoped component may have properties that
point to objects of any scope. Dynamo correctly connects the request-scoped
component to the appropriate component for that request.
On the other hand, global and session-scoped components
should not have pointers to request-scoped components. This is because
request-scoped components are constantly being created, destroyed, and shuffled
around between requests. It is a very bad idea for anything other than another
request-scoped object to hold onto a pointer for a request-scoped object.
Session
Management
There is a very useful out of the box component named
GenericSessionManager in ATG. GenericSessionManager component helps you to
track down all session scope objects and it’s state.
The GenericSessionManager is an incredibly useful way
to explore the values on a given session's profile. View a list of active sessions in your
instance, and then drill a profile's namespace to see what's been set.
a.
You can access the GenericSessionManager
from the URI given below. (This is part of the ATG dyn admin component browser)
b.
Once you click on the view button, Session
Manager will list out all the active sessions with in the application server.
9.
OOTB FormHandlers for Cart, Checkout, Profile?
Form
Handler for Cart:
A customer adds an item to their shopping cart using
CartModifierFormHandler, the submit button on the form submits to the
handleAddItemToOrder method. Before any computation is done, the
handleAddItemToOrder method invokes the preAddItemToOrder method. Additionally,
after all computation is complete but before returning any information, the
handleAddItemToOrder method invokes the postAddItemToOrder method.
By default these preXXX and postXXX methods have no
functionality. They are provided so you can easily extend the form handlers to
support additional functionality. However, be aware that these methods do not
take any input parameters.
public class
CartModifierFormHandler extends PurchaseProcessFormHandler
This formhandler is used to modify a ShoppingCart by
adding items to it, deleting items from it, modifying the quantities of items
in it, and preparing it for the checkout process.
Understanding
the CartModifierFormHandler
The CartModifierFormHandler is used to add items to and
remove items from an Order, modify the quantity of items in the Order, and
prepare the Order for the checkout process.
CartModifierFormHandler is an instance of class
atg.commerce.order.purchase.CartModifierFormHandler; it is located in Nucleus
at /atg/commerce/order/purchase/CartModifierFormHandler.
Many of the methods (described below) in
CartModifierFormHandler call OrderManager.updateOrder() to save the Order in
its present state to the Order Repository. For information on
OrderManager.updateOrder() and the updateOrder pipeline that it executes
Form
Handler for Checkout:
The form handlers in /atg/commerce/order/purchase
(CartModifierFormHandler, ShippingGroupFormHandler, PaymentGroupFormHandler,
CommitOrderFormHandler, and ExpressCheckoutFormHandler) are the ones you should
use to build your checkout process.
public class
ExpressCheckoutFormHandler extends PurchaseProcessFormHandle
The ExpressCheckoutFormHAndler is used to expedite the
checking out of an Order. This supports creating a maximum of one Profile
derived HardgoodShippingGroup and one Profile derived CreditCard, followed by
committing the Order. If the ExpressCheckoutFormHandler.PaymentGroupNeeded
property is true then a CreditCard PaymentGroup will automatically be taken
from the Profile. If false, then the user may supply the CreditCard information
in a form through the ExpressCheckoutFormHandler.PaymentGroup property. If the
ExpressCheckoutFormHandler.ShippingGroupNeeded property is true then a
HardgoodShippingGroup will automatically be taken from the Profile. If false,
then the user may supply the HardgoodShippingGroup information in a form
through the ExpressCheckoutFormHandler.ShippingGroup property. If the
ExpressCheckoutFormHandler.CommitOrder property is true, then the ExpressCheckoutFormHandler.ExpressCheckout
handler will commit the Order. Set to false in order to display a confirmation
page before committing the Order.
Preparing
a Simple Order for Checkout
If your site supports the use of only a single
HardgoodShippingGroup and a single CreditCard for a given Order, you can manage
and expedite the pre-checkout process for Orders using the
ExpressCheckoutFormHandler (class
atg.commerce.order.purchase.ExpressCheckoutFormHandler).
ExpressCheckoutFormHandler supports the use of a single Profile-derived
HardgoodShippingGroup and a single Profile-derived CreditCard.
ATG Commerce provides an instance of
ExpressCheckoutFormHandler, which is located in Nucleus at
/atg/commerce/order/purchase/ExpressCheckoutFormHandler.
Methods:
•
handleExpressCheckout
•
runRepricingProcess
•
commitOrder
Form
Handler for Profile:
A ProfileFormHandler
component can be request- or session-scoped. The default scope is request: each
time a user accesses a page with a profile form, the ATG platform creates an
instance of the ProfileFormHandler that uses the configured values of the
component’s properties.
A ProfileFormHandler
component can be request- or session-scoped. The default scope is request: each
time a user accesses a page with a profile form, the ATG platform creates an
instance of the ProfileFormHandler that uses the configured values of the
component’s properties.
This class provides a convenient form handler for operating on the
current user's profile. It can be used to add new profiles, edit the current
profile, login (switch profiles based on login name and password) and logout.
ProfileFormHandler Submit Operations
The ProfileFormHandler supports
the following operations that can be specified for form submission:
Operation
|
Function
|
cancel |
Cancels
any changes the user has made to values in the form but has not yet
submitted.
|
changePassword |
Changes
the password property of the profile to the new value entered by the user.
|
clear |
Clears
the
value Dictionary. |
create |
Creates
a permanent profile and sets the profile properties to the values entered in
the form.
|
delete |
Deletes
the current profile.
|
login |
Uses
the
login and password values entered by
the user to associate the correct profile with that user. |
logout |
Resets
the profile to a new anonymous profile and optionally expires the current
session.
|
update |
Modifies
the properties of the current profile.
|
For example, when a user logs
into a site, a form can invoke the login operation as follows:
<dsp:input bean="ProfileFormHandler.login" type="submit" value="Submit"/>
Each operation is associated
with a handler method.
Profile
Form Handler Extensions
The commerce DCS module sets the class of the
/atg/userprofiling/ProfileFormHandler component as follows:
$class=atg.commerce.profile.CommerceProfileFormHandler
Note:
This class extends the ScenarioProfileFormHandler which in turn extends the
ProfileFormHandler.
The Oracle ATG Web Commerce profile form handler
(atg.commerce.profile.CommerceProfileFormHandler) is a subclass of
atg.userprofiling.ProfileFormHandler. It performs operations specific to
Commerce. For example, an anonymous user can accumulate promotions in their
activePromotions attribute. During login, the anonymous user’s active
promotions are copied into the list of active promotions of the persistent
user. During the registration and login process, any shopping carts (Orders)
created before logging in are changed to be persistent.
If the user’s persistent profile contains any old
shopping carts (Orders in an incomplete state), these shopping carts are loaded
into the user’s session. After log in, the PricingModelHolder component is
reinitialized to cache all the promotions that the persistent user has
accumulated during previous sessions. These operations are performed by
overriding the addPropertiesOnLogin, postCreateUser and postLoginUser methods from
the ProfileFormHandler.
public class
CommerceProfileFormHandler extends ScenarioProfileFormHandler
This form handler is a subclass of the DPS
ProfileFormHandler to perform some operations that are specific to Commerce.
The additional functionality includes:
•
During a login operation the active
promotions from the anonymous user are copied into the list of active
promotions of the persistent user.
•
After the login operation is finished the
session-scope PricingModelHolder is reinitialized to cache all the promotions
that the persistent user has accumulated.
•
During the registration and login process
any shopping carts (i.e. Orders) which were created while they were anonymous
(and thus not persistent) are changed to be persistent.
•
If the user logs in any old shopping carts
(i.e. Orders in an INCOMPLETE state) are loaded into the user's session.
public class
ScenarioProfileFormHandler extends ProfileFormHandler implements
atg.scenario.ScenarioConstants, atg.scenario.targeting.SlotConstants
This form handler subclasses the DPS ProfileFormHandler
and performs operations that are specific to the DSS layer.
Specifically, when a user logs in, if the session's
transient user has any associated scenario instances, they are copied over to
the persistent user's profile, provided that:
•
the logged-in user does not possess an
existing instance of that scenario/segment, OR
•
the scenario/segment permits multiple
instances per individual
This functionality allows scenarios to be continued
across the login boundary.
In addition, when a user logs in and the session's
transient user has persistent slot instances, they are copied over to the
persistent user's profile, provided that:
•
the logged-in user does not possess an
existing instance of that persistent slot
This functionality also allows persistent slots to be
continued across the login boundary.
10. Describe most commonly used
FormHandlers in ATG.
Here are some of the commonly used
FormHandlers, although ATG provides many out
of the box FormHandlers and even we can write our own custom FormHandlers by
extending GenericFormHandler class provided by ATG.
CartModifierFormHandler -- This formhandler
is used to modify a ShoppingCart by adding items to it, deleting items from it,
modifying the quantities of items in it, and preparing it for the checkout
process.
ExpressCheckoutFormHandler -- The
ExpressCheckoutFormHAndler is used to expedite the checking out of an Order.
This supports creating a maximum of one Profile derived HardgoodShippingGroup
and one Profile derived CreditCard, followed by committing the Order.
SaveOrderFormHandler -- The
SaveOrderFormHandler is used to save the user's current Order based on a
descriptive name that the user specifies. A new empty Order is then made the
user's current shopping cart. If a descriptive name for the Order is not
specified, then one is created based on the user's Locale and date and time.
ShippingGroupFormHandler -- The
ShippingGroupFormHandler is used to associate ShippingGroups with the various Order
pieces. This component is used during the Order checkout process, and any Order
successfully processed by the ShippingGroupFormHandler is ready for the next
checkout phase, which may be Payment.
PaymentGroupFormHandler -- The
PaymentGroupFormHandler is used to associate PaymentGroups with the various
Order pieces. This component is used during the Order checkout process, and any
Order successfully processed by the PaymentGroupFormHandler is ready for the
next checkout phase, which may be confirmation.
CommitOderFormHandler -- The
CommitOrderFormHandler is used to submit the Order for final confirmation. This
calls the OrderManager's processOrder method. If there are no errors with
processing the Order, then the current Order in the user's ShoppingCart will be
set to null and the submitted Order will become the ShoppingCart's last Order.
CancelOderFormHandler -- The
CancelOrderFormHandler is used to cancel the user's current Order, which
deletes the Order from the ShoppingCart.
RepositoryFromHandler -- Saves repository
data to a database.
ProfileFormHandler -- Connects forms
with user profiles stored in a profile repository.
SearchFormHandler -- Specifies
properties available to a search engine.
SimpleSQLFormHandler -- Works with form data that is stored in a SQL
database.
11. Formhandlers
structures/hierarchy?
Subclassing
ATG Form Handlers
Oracle ATG Web
Commerce form handler classes all implement the interface
atg.droplet.DropletFormHandler
. Three form handler
base classes implement this interface:
EmptyFormHandler
atg.droplet.EmptyFormHandler
implements the DropletFormHandler
interface and
provides empty implementations of the methods in this interface.
GenericFormHandler
atg.droplet.GenericFormHandler
extends EmptyFormHandler
. It provides
simple implementations of DropletFormHandler
interface methods
and adds basic error handling logic. If errors occur in processing a form that
uses GenericFormHandler
, the errors are
saved and exposed as properties of the form handler component.
TransactionalFormHandler
atg.droplet.TransactionalFormHandler
extends atg.droplet.GenericFormHandler
; it treats the
form processing operation as a transaction. Although this form handler methods
are processed discretely, their results are saved simultaneously. The
transaction management occurs in the beforeGet
and afterGet
methods. This
establishes the transaction before any of properties are set or handler methods
are called, rather than in the handler methods themselves.
Transactions in Repository Form Handlers
A form
handler that can manipulate repository items should ensure that all operations
that occur in a handler method call are committed in a single transaction.
Committing all operations simultaneously helps ensure data integrity. A
repository or database transaction is completed successfully or not at all;
partially committed data is rolled back if an error occurs mid-transaction.
The
RepositoryFormHandler
and TransactionalRepositoryFormHandler
classes ensure atomic transactions in this
way. If you subclass either class without overriding the handler methods, your
subclass handles transactions properly. If you override any handler methods, or
add new handler methods, you must make sure that these methods handle
transactions properly.
Note: A form handler starts and ends a
transaction only when no other active transactions are in progress. If a
transaction is in progress, the form handler returns a status for each
operation it attempts and permits the transaction to continue after the form
handler itself finishes processing.
To
create a form handler that works with repository items while a transaction is
in progress:
a. Create
a form handler that subclasses RepositoryFormHandler or TransactionalRepositoryFormHandler,
depending on your requirements. The source code for both form handlers is
provided in
<ATG10dir>/DAS/src/Java/atg/repository/servlet
Both form handlers create a transaction if one is not already in
progress and provide the status of all operations performed by the form handler
while the transaction is in place. The two form handlers mainly differ in the
transaction lifespan.
b. Create
methods on your new form handler that are transaction-aware
Note: RepositoryFormHandler and
TransactionalRepositoryFormHandler are useful for manipulating repository
items. The form handler class atg.droplet.TransactionFormHandler supports
transactions and lets you work with the JDBC directly.
RepositoryFormHandler
atg.repository.servlet.RepositoryFormHandler is a base
form handler that provides tools for creating, modifying, and deleting items
stored in an SQL repository.
In the RepositoryFormhandler, the transaction is
governed entirely by the submit handler method, meaning the transaction starts
when a submit handler method is invoked and ends when it completes execution.
Transaction status is reported for the data validation and the data commit
operations.
TransactionalRepositoryFormHandler
The
atg.repository.servlet.TransactionalRepositoryFormHandler
, a subclass
of the RepositoryFormhandler
,
provides enhanced transaction support by broadening the scope of the
transaction. This class also defines a few additional properties that are
useful for transaction monitoring. Oracle ATG Web Commerce Adaptive Scenario
Engine does not include any instances of this class.
Transactions
begin when the
beforeSet
method is invoked and end with the afterSet
method. Because a transaction status is
generated for all operations that occur during its execution, a status is
recorded for each the following operations:
•
beforeSet
method execution
• Processing
of all other tags in the JSP (tags that implement submit operations have the
lowest priority on the page)
• Submit
handler method data validation
• Submit
handler method data commit
•
afterSet
method execution
12. What
is Transaction-Aware Methods?
When
you create a form handler that subclasses RepositoryFormHandler or TransactionalRepositoryFormHandler, make
sure that its methods can correspond with the Transaction Manager. There are
two ways to do this:
·
Base
New Handler Methods on handleUpdate Source Code so that you can reuse the transaction code
in it, then modify the rest accordingly.
·
Modify
Existing Handler Methods by
inserting code before or after their execution in the
preX
or postX
methods, respectively.
Base New Handler Methods on handleUpdate Source Code
The
code provided here implements the
handleUpdate
method. Create your own handler methods by
making changes to this code sample and inserting it into your subclassed form
handler:public boolean handleUpdate(DynamoHttpServletRequest pRequest,
DynamoHttpServletResponse pResponse) throws ServletException, IOException {
TransactionDemarcation td = getTransactionDemarcation();
TransactionManager tm = getTransactionManager();
try {
if (tm != null) td.begin(tm, td.REQUIRED);
int status = checkFormError(getUpdateErrorURL(), pRequest, pResponse);
if (status != STATUS_SUCCESS) return status == STATUS_ERROR_STAY;
// update the repository item
preUpdateItem(pRequest, pResponse);
if (!getFormError())
updateItem(pRequest, pResponse);
postUpdateItem(pRequest, pResponse);
// try to redirect on errors
if ((status = checkFormError(getUpdateErrorURL(), pRequest, pResponse))
!= STATUS_SUCCESS)
return status == STATUS_ERROR_STAY;
// try to redirect on success
return checkFormSuccess(getUpdateSuccessURL(), pRequest, pResponse);
}
catch (TransactionDemarcationException e) {
throw new ServletException(e);
}
finally {
try { if (tm != null) td.end(); }
catch (TransactionDemarcationException e) { }
}
}
Modify Existing Handler Methods
The
three existing submit handler methods (
handleCreate
, handleUpdate
, and handleDelete
) each
provide a pair of empty pre
and post
methods where you can add custom code.
It is
likely that you use either the
preX
or the postX
method for a given existing handler method
although you can customize both. For example, consider a subclass ofTransactionalRepositoryFormHandler
where preUpdate
and postUpdate
are used:
a) The
form is rendered, which causes
getX
method to display current values for
properties used in the form.
b) The
user fills in the form and submits it.
c) The
form handler’s
beforeSet
method is invoked. If a transaction is not
currently in progress, the TransactionalRepositoryFormHandler
component creates a one.
d) If tag
converters are used, they are applied to the specified content. Any form
exceptions that occur now or at any point during the form handler execution are
saved to the form handler’s
formException
property.
e) The
setX
method is called, followed by the form
handler’s handleUpdate
method. Severe form exceptions might cause
form processing to stop and the transaction to rollback, before redirecting
users to a different page.
f) The
preUpdateItem
method is invoked. The preX
method for the handleUpdate
method is preUpdateItem
. Serious
errors generated from this operation might also prompt the transaction to
rollback.
g) The
updateItem
method, which is the handleUpdate
method responsible for processing the
content and updating the database, is invoked. Again, this is another operation
that can cause a transaction to rollback when serious errors are detected. At
this point, the changes made by the actions associated with the transaction are
kept private, meaning that they are only visible within the transaction itself.
h) The
postUpdateItem
method is invoked. Again, the transaction
is rolled back if serious errors are detected.
i) The
afterSet
method is invoked. If the transaction was
started by the beforeSet
method, the transaction concludes and the
content it saved to the database is publicly visible.
Use the
preX
method when you want to expand the
constraints for data validation. For example, you might want to check if the
user-entered zip code and country correspond to each other. The countries that
use zip codes require them to be a certain length. The preX
method can verify that a zip code uses the
appropriate format for the country, before saving the zip code and country
values to the database. Any discrepancies produce a form exception and roll
back the transaction.
The
postX
method is useful for verifying user
entered-data after that data has been converted by tag converters. For example,
a form handler that saves credit card information might use a postX
method to handle authorization. After that
credit card number has been formatted correctly and all related information is
updated in the database, the postX
method executes. If the authorization
fails, the transaction is rolled back, the original data refreshed, a form
error exception is thrown, and the user is redirected to a page where the use
can re-enter credit card information.
13. What
is repository?
The ATG Repository API (atg.repository.*) is the
foundation of persistent object storage, user profiling, and content targeting
in ATG products. A repository is a data access layer that defines a generic
representation of a data store.
ATG provides an easy to use and powerful object
relational mapping (ORM) persistence framework. It supports numerous databases,
including Oracle and DB2, as well as popular open source databases such as and
MySQL. It uses reflection primarily to determine the java bean
properties and does not need the developer to code any POJO also.
Repository
The data access layer that defines a generic representation of a
data store. Repositories access the underlying data storage device through a
connector, which translates the request into whatever calls are needed to
access that particular data store. Connectors for relational databases and LDAP
directories are provided out-of-the-box. Connectors use an open, published
interface, so additional custom connectors can be added if necessary.
A repository is a collection of repository items. Each
repository connects to a single data store. But application & subsystems in
Dynamo can use different repositories or share the same repository.
The repository is not the data store itself instead, it is a
collection of JavaBeans whose properties can be found and stored in the data
store. The mission of the repository is to provide a mechanism to retrieve the
data elements and a run-time representation of the available Meta information
about each object.
Following are the main conceptual parts of the Repository API.
·
Repository
Items - Each employee would have a
corresponding repository item. Repository item is corresponding to row in
database table. Repository item is made of properties. These properties correspond roughly to columns of a table
·
Item
Descriptors - An employee item descriptor would
specify all of the properties that an employee repository item could possess.
·
Repository
Queries - An application can build queries that
return the appropriate employee.
Repository
Item
Repository items are like a JavaBeans. Their properties
are determined dynamically at runtime. The properties in a particular
repository item depend on the type of item. One item might represent the user
profile (name, address, phone number) while another may represent the meta-data
associated with a news article (author, keywords, synopsis). Each repository
item is made of properties. These properties store the data that makes up a
repository item. Each property has a name, such as id, firstName, or lastName
etc. In the SQL repository, these properties correspond roughly to columns of a
table. The properties available to a type of repository item are defined in the
repository’s item descriptors.
So the purpose of the Repository interface system is to
provide a unified way for data access. For example, developers can use
targeting rules with the same syntax to find people or content. Each repository
item must have an identifier, which is called a repository ID. The repository
ID must uniquely identify the repository item from all other repository items
of the same type. So each item descriptor must specify the columns that act as
the repository ID (which will usually be the same as the table’s primary key.
If we don’t define an id property in the item descriptor, then the id property
must use the default data-type, which is string.
For example, In the SQL repository, a repository item
often corresponds to a row in a table. In the SQL profile repository, each user
profile is a repository item.
Types
of Repository in ATG
The following Repository models exist in ATG.
a.
SQL
Repositories - use ATG’s Generic SQL Adapter (GSA)
connector to perform a mapping between ATG and data stored in a SQL database.
It can be used to access content, user profiles, application security information,
and more.
b.
LDAP
Repository - Uses the Dynamo LDAP connector to access user data
in an LDAP directory.
c.
Composite
Repository - provides a means for using more than one data store
as the source for a single repository.
d.
Versioned
Repositories - an extension of the GSA used in ATG
Publishing. This is to maintain versions of repository items.
Item
Descriptor
Each repository item type is described by a Repository
item descriptor (which has a one-to-one correlation with RepositoryView). The
item descriptor gives a name to the type, and also describes the properties for
that type. The name of each property is defined in the item descriptor, as well
as the class of the Java object used to represent that type (Integer, String,
etc.). The item descriptors exposed by a repository depend on a combination of
the underlying data store and the configuration of the repository.
For example, In the SQL repository, each database table
might have its own repository item descriptor. Or another alternative might
join multiple tables into a single item descriptor. Also Repositories can
support multiple item descriptors. For example, a SQL repository instance that
supports a commerce application might have different item descriptors
representing users, products, product categories, orders, etc.
An item descriptor implements the
atg.repository.RepositoryItemDescriptor interface and may subclass
atg.repository.ItemDescriptorImpl.
Item-Descriptor Relationships
•
One to One – Represented by ‘auxiliary’
tables.
•
One to Many – Represented by ‘multi’ tables
•
Many to Many – achieved using an
intermediate table.
The multi-column-name attribute ensures that the
ordering of the multivalues are maintained.
The column specified by the multi-column-name attribute
is used for multi-valued properties of data-types array, map, and list and is
not used for sets (which are unordered). For map type properties, the values in
the column specified by the multi-column-name attribute must be a string. For
list or array type properties, these values should be an integer or numeric
type, and must be sequential.
Advantages
ATG Data Anywhere Architecture
offers several advantages over the standard data access methods such
as Java Data Objects (JDO), Enterprise JavaBeans (EJB), and Java Database
Connectivity (JDBC). Among the differences:
Data source
independence
ATG Data Anywhere Architecture
provides access to relational database management systems, LDAP directories,
and file systems using the same interfaces. This insulates application
developers from schema changes and also storage mechanism. Data can even move
from a relational database to an LDAP directory without requiring recoding.
Java Data Objects support data source independence, but it is up to vendors to
provide an LDAP implementation.
Fewer lines of
Java code
Less code leads to faster
time-to-market and reduced maintenance cost. Persistent data types created with
ATG Data Anywhere are described in an XML file, with no Java code required.
Unified view
of all customer interactions
A unified view of customer data
(gathered by web applications, call center applications, and ERP systems) can
be provided without copying data into a central data source. This unified view
of customer data leads to a coherent and consistent customer experience.
Maximum performance
Intelligent caching of data
objects ensures excellent performance and timely, accurate results. The JDO and
EJB standards rely on a vendor implementation of caching that might not be
available.
Simplified
transactional control
The key to overall system
performance is minimizing the impact of transactions while maintaining the
integrity of your data. In addition to full Java Transaction API (JTA) support,
ATG Data Anywhere lets both page developers and software engineers control the
scope of transactions with the same transactional modes—required, supports,
never—used by EJB deployment engineers.
Fine-grained
access control
You can control who has access
to which data at the data type, data object, even down to the individual
property with Access Control Lists (ACLs).
Integration
with ATG product suites
ATG personalization, scenarios,
commerce, portal, and content administration applications all make use of
repositories for data access. A development team is free to use EJBs along side
of ATG technology, but the easiest way to leverage investment in ATG technology
is to follow the example set by the solution sets. The ATG solution sets
satisfy all their data access needs with repositories.
14. How
do you create custom repository?
Now create a property file which specifies the
repository mapping xml file for your RDBMS.
Step 1. Analyse the Requirement.
From Above diagram, following points are
collected.
a) There are two
separate OBJECTS, which can be clubbed together. So now these two Objects
"Author" and "Book" will treated as Items
(<item-descriptor>) under the one repository XML definition file.
b) Identify the each
Property under the each Object. Identify the Data Types of each.
Step 2: Drawing in line repository structure.
Step 3: Creating the XML Definition file(with
minimal required attributes)
File Name: /my/library.xml
<?xml version="1.0" encoding="utf-8"
standalone="no"?>
<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD General SQL Adapter//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>Library Repository</name>
<author>Iranna</author>
</header>
<item-descriptor name="author" display-name="author" >
<table name="AUTHOR_MASTER" type="primary" id-column-name="author_id">
<property name="id" column-name="author_id"/>
<property name="firstName" column-name="first_name"
PUBLIC "-//Art Technology Group, Inc.//DTD General SQL Adapter//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>Library Repository</name>
<author>Iranna</author>
</header>
<item-descriptor name="author" display-name="author" >
<table name="AUTHOR_MASTER" type="primary" id-column-name="author_id">
<property name="id" column-name="author_id"/>
<property name="firstName" column-name="first_name"
display-name="firstName"
data-type="string"/>
<property name="lastName" column-name="last_name"
<property name="lastName" column-name="last_name"
display-name="lastName"
data-type="string"/>
<property name="dob" column-name="dob" display-name="dateOfBirth" data-type="date"/>
<property name="gender" column-name="gender"
<property name="dob" column-name="dob" display-name="dateOfBirth" data-type="date"/>
<property name="gender" column-name="gender"
display-name="gender"
data-type="enumerated">
<attribute name="useCodeForValue" value="true"/>
<option value="Male" code="101"/>
<option value="Female" code="202"/>
<option value="DontSpecify" code="303"/>
</property>
</table>
</item-descriptor>
<item-descriptor name="book" display-name="book" >
<table name="BOOK_MASTER" type="primary" id-column-name="book_id">
<property name="id" column-name="book_id"/>
<property name="name" column-name="name" display-name="name" data-type="string"/>
<property name="description" column-name="description"
<attribute name="useCodeForValue" value="true"/>
<option value="Male" code="101"/>
<option value="Female" code="202"/>
<option value="DontSpecify" code="303"/>
</property>
</table>
</item-descriptor>
<item-descriptor name="book" display-name="book" >
<table name="BOOK_MASTER" type="primary" id-column-name="book_id">
<property name="id" column-name="book_id"/>
<property name="name" column-name="name" display-name="name" data-type="string"/>
<property name="description" column-name="description"
display-name="description"
data-type="big string"/>
<property name="price" column-name="price" display-name="price" data-type="double"/>
<property name="pages" column-name="pages" display-name="pages" data-type="int"/>
<property name="available" column-name="available"
<property name="price" column-name="price" display-name="price" data-type="double"/>
<property name="pages" column-name="pages" display-name="pages" data-type="int"/>
<property name="available" column-name="available"
display-name="available"
data-type="boolean"/>
</table>
</item-descriptor>
</table>
</item-descriptor>
</gsa-template>
Step 4: Creating the Component for XML Definition file.
Path: /my/Library.properties
$class=atg.adapter.gsa.GSARepository
$scope=global
repositoryName=Library
# database access- for making repositry as versioned, use SwitchingDataSource else use JTDataSource
dataSource=/atg/dynamo/service/jdbc/SwitchingDataSource
transactionManager=/atg/dynamo/transaction/TransactionManager
# our XML definitionFile
definitionFiles=/my/library.xml
# XML parsing
XMLToolsFactory=/atg/dynamo/service/xml/XMLToolsFactory
# id generation
idGenerator=/atg/dynamo/service/IdGenerator
transactionManager=/atg/dynamo/transaction/TransactionManager
dataSource=/atg/dynamo/service/jdbc/dataSourceFile
# The “dataSourceFile” is yet another property file where the JDBC
connections and database driver,server name, user, password etc are specified.
Step 5: Registering
the Repository.
The next step is to register our repository with dynamo by
creating /config/atg/registry/ContentRepositories.properties
initialRepositories+=\
/playground/dummyRepository,\
15. What are the cache modes in repository?
The SQL repository supports the
following caching modes:
a. Simple
Caching handles
caches in each server locally; no attempt is made to synchronize updates across
multiple server instances.
b. Locked
Caching uses
read and write locks to synchronize access to items stored by multiple caches.
c. Distributed
TCP Caching uses
TCP to broadcast cache invalidation events to all servers in a cluster.
d. Distributed
JMS Caching uses
JMS to broadcast cache invalidation events to all servers in a cluster.
e. Distributed
Hybrid Caching uses
TCP to send cache invalidation events only to those servers that are known to
cache the target items.
Setting Caching Mode
Caching modes are set at the
item descriptor level, through the
<item-descriptor>
tag’s cache-mode
attribute. The default caching mode is Simple
Caching. To set a different caching mode on an item descriptor, set cache-mode
to one of the following values:
•
simple
•
locked
Disabling Caching
You can disable caching for
items of a specified type, or for specific item properties:
• To set
an item type’s caching mode, set its
<item-descriptor>
tag’s cache-mode
attribute to disabled
.
• To
disable caching for an individual property within an item descriptor, set the
<property>
tag’s cachemode
attribute to disabled
. Each
property’s definition overrides the caching mode set for its item descriptor.
For example:<item-descriptor name="user" cache-mode="simple">
<table name="dps_user">
<property name="password" cache-mode="disabled">
...
</table>
...
Caution: If caching is disabled for an item type or
individual item properties, any code that retrieves that item requires access
to the database, which can noticeably degrade application performance.
Inherited Caching Modes
You can set a property to
inherit the default caching mode by setting its
cache-mode
attribute to inherit
.
Simple Caching
When
caching mode is set to simple, each server maintains its own cache in memory. A
server obtains changes to an item’s persistent state only after the cached
entry for that item is invalidated. This mode is suitable for read-only
repositories such as product catalogs, where changes are confined to a staging
server, and for architectures where only one server handles a given repository
item type.
You can ensure that an item’s cached data is regularly
refreshed by setting its item descriptor’s item-cache-timeout attribute.
Locked Caching
A multi-server application
might require locked caching, where only one ATG instance at a time has write
access to the cached data of a given item type. You can use locked caching to
prevent multiple servers from trying to update the same item simultaneously.
<item-descriptor name="myItem" cache-mode="locked">
Locked caching has the
following prerequisites:
• Item
descriptors that specify locked caching must disable query caching by setting
their
query-cache-size
attribute to 0.
• A
repository with item descriptors that use locked caching must be configured to
use a ClientLockManager component; otherwise, caching is disabled for those
item descriptors. The repository’s
lockManager
property is set to a component of type atg.service.lockmanager.ClientLockManager
.
• At
least one ClientLockManager on each ATG instance where repositories
participate in locked caching must be configured to use a ServerLockManager.
• A ServerLockManager component must be configured to manage the
locks among participating ATG instances.
ClientLockManager
If an SQL repository contains
item descriptors that use locked caching, set the Repository component’s
lockManager
property to a component of typeatg.service.lockmanager.ClientLockManager
. ATG
provides a default ClientLockManager component:/atg/dynamo/service/ClientLockManager
Thus, you can set an SQL Repository’s
lockManager property as follows:
lockManager=/atg/dynamo/service/ClientLockManager
ClientLockManager
properties
A ClientLockManager component
must be configured as follows:
Property
|
Setting
|
useLockServer |
true enables this
component to connect to a ServerLockManager |
lockServerAddress |
Host
address of the ServerLockManager and, if set, the backup ServerLockManager
|
lockServerPort |
The
ports used on the ServerLockManager hosts, listed in the same order as in
lockServerAddress |
For example, given two
ServerLockManagers on hosts
tartini.acme-widgets.com
and corelli.acme-widgets.com
, where
both use port 9010, the ClientLockManager
is configured as follows:$class=atg.service.lockmanager.ClientLockManager
lockServerAddress=tartini.acme-widgets.com,corelli.acme-widgets.com
lockServerPort=9010,9010
useLockServer=true
Note: The
liveconfig
configuration layer always sets useLockServer
to true.
ServerLockManager
The server lock manager
synchronizes locking among various ATG servers, so only one at a time can
modify the same item. At
least one ATG server must be configured to start the
/atg/dynamo/service/ServerLockManager
component on application startup.
To do this, add the
ServerLockManager to the
initialServices
property of /atg/dynamo/service/Initial
in the ServerLockManager server’s
configuration layer. For example:<ATG9dir>/home/localconfig/atg/dynamo/service/Initial.properties
This properties file sets the
initialServices
property as follows:#/home/localconfig/atg/dynamo/service/Initial.properties:
initialServices+=ServerLockManager
ServerLockManager
properties
A ServerLockManager component
is configured with the following properties:
Property
|
Description
|
port |
This
server’s port
|
otherLockServerAddress |
The
other ServerLockManager’s address
|
otherLockServerPort |
The
port of the ServerLockManager specified in
otherLockServerAddress |
otherServerPollInterval |
The
interval in milliseconds that this server waits before polling the server
specified in
otherLockServerAddress |
waitTimeBeforeSwitchingFromBackup |
The
time in milliseconds that this server waits after detecting that the primary
ServerLockManager has failed, before taking over as the primary
ServerLockManager
|
For example, given
ServerLockManagers
tartini.acme-widgets.com
and corelli.acmewidgets.com
running on port 9010, their respective
configurations might look like this:# tartini:9010
$class=atg.service.lockmanager.ServerLockManager
port=9010
otherLockServerAddress=corelli.acme-widgets.com
otherLockServerPort=9010
otherServerPollInterval=2000
waitTimeBeforeSwitchingFromBackup=10000
# corelli:9010
$class=atg.service.lockmanager.ServerLockManager
port=9010
otherLockServerAddress=tartini.acme-widgets.com
otherLockServerPort=9010
otherServerPollInterval=2000
waitTimeBeforeSwitchingFromBackup=10000
Distributed TCP Caching
If an application modifies an
item whose item descriptor specifies distributed TCP caching mode, a cache
invalidation event is broadcast from that ATG instance to all other ATG instances
that use distributed TCP caching. The event message supplies the nature of the
change, the changed item’s type, and repository ID. Receiving repositories
respond by invalidating that cached item.
Distributed TCP caching is
suitable for sites where the following conditions are true:
• Items
of a type that specifies distributed TCP caching are likely to be cached across
most ATG instances in the application.
• Items
are subject to frequent reads.
• Items
are rarely changed, added or deleted.
An item that changes
frequently—say, more than 50 or 100 times per second —is not suitable for
distributed TCP caching mode, because the extra network activity incurred by
cache invalidation messages outweighs caching benefits. Cache invalidation
events are broadcast to all ATG instances that enable distributed caching, even
if they do not cache the invalidated item; as the number of these ATG instances
increases, so too increases the network activity associated with each cache
invalidation event.
Event server components of
class atg.adapter.gsa.event.GSAEventServer send and receive cache invalidation
events over TCP among participating ATG instances.
gsa_subscriber_table maintains routing information for each
item descriptor that uses distributed TCP caching: its repository path, and the
address and port of that repository’s event server.
Distributed JMS Caching
When an item descriptor’s
caching mode is set to
distributedJMS
, all cache invalidation events sent for
items of that type use JMS, which persists cache invalidation event messages in
the SQL database until delivery is complete.
By contrast, Distributed
TCP Caching cannot
guarantee that all servers receive cache invalidation events.
Distributed Hybrid Caching
Distributed hybrid caching
provides intelligent cache invalidation across multiple ATG instances. Unlike
distributed JMS and TCP caching, which broadcast invalidation events to all
participating servers, distributed hybrid caching sends invalidation events
only to servers where the items are cached, which can significantly reduce
network traffic.
Simple versus Distributed Caching
Simple caching mode is
generally sufficient if site users do not require immediate access to recent
item changes. You can use item descriptor attributes
item-expire-timeout
andqueryexpiretimeout
to specify how long items can stay in the
item and query caches, respectively, before they are invalidated. For many
multi-server sites, setting this attribute to a low threshold provides a
reasonable response time to item changes, while avoiding the network overhead
incurred by distributed caching modes—especially Distributed
TCP Cachingand Distributed
JMS Caching.
16. What
is item cache, query cache?
For each item descriptor, an SQL repository generally
maintains two caches:
•
Item Caches
•
Query Caches
Item Caches
Item
caches hold the values of repository items, indexed by repository IDs. Item
caching can be explicitly enabled for each item descriptor. Even if caching is
explicitly disabled, item caching occurs within the scope of each transaction
(see Disabling
Caching).
An item cache entry is invalidated when that
item is updated. The scope of an entry’s invalidation depends on its caching
mode. For example, when an item is changed under simple caching mode, only the
local cache entry is invalidated; other Oracle ATG Web Commerce instances are
not notified. Oracle ATG Web Commerce provides several different Distributed
Caching Modes to invalidate items across multiple instances.
Query Caches
Query
caches hold the repository IDs of items that match given queries. When a query
returns repository items whose item descriptor enables query caching, the
result set is cached as follows:
• The
query cache stores the repository IDs.
• The
item cache stores the corresponding repository items.
Note: Queries that
include derived item properties are never cached.
17. What
is ATG Cache Flushing?
You can flush (invalidate) the caches for an item descriptor or an
entire SQL repository, using the following methods. Note that first, you must
cast youratg.repository.RepositoryItemDescriptor to
an atg.repository.ItemDescriptorImpl. If you are using
distributed cache mode, use the Cache Invalidator, as described in theCache
Invalidation Service section below.
The methods in atg.repository.ItemDescriptorImpl are:
invalidateItemCache()
|
Invalidates
the item caches for this item descriptor.
|
invalidateCaches()
|
Invalidates
both the item and query caches for this item descriptor.
|
removeItemFromCache(String pId)
|
Removes
the specified item from any repository caches
|
These methods also have versions that accept a boolean parameter
that indicates whether the cache should be changed globally, or just for the
local cache. These methods are:
removeItemFromCache(id, boolean pGlobal)
invalidateCaches(boolean pGlobal)
invalidateItemCache(boolean pGlobal)
invalidateCaches(boolean pGlobal)
invalidateItemCache(boolean pGlobal)
If this global parameter is true, the
invalidation occurs across the cluster. Otherwise, the invalidation occurs only
in the local ATG instance.
The removeItemFromCache method, when given
a true value, will use one of two mechanisms to distribute the
invalidation event:
•
If the item descriptor uses distributed cache mode, it uses the
event server to send the invalidation event.
•
Otherwise, it uses the GSAInvalidatorService to
send the event.
The invalidateCaches and invalidateItemCache methods,
when given true for the global parameter, will always use the GSAInvalidatorService. If this
service is not enabled, a warning is logged and the cache is only invalidated
locally.
This method in atg.repository.RepositoryImpl affects
all caches in the repository:
invalidateCaches()
|
Invalidates
all caches in this repository.
|
You can cast your repository to these classes and call these
methods from there. You can both flush items of a specific kind, items and
queries of a specific kind or a specific item with these methods.
For example, here is how you might use the invalidateItemCache() method
to invalidate the item caches for every item descriptor in a repository:
RepositoryImpl rep = getRepository();
String[] descriptorNames = getItemDescriptorNames();
// iterate over all the descriptors
for (int i=0; i<descriptorNames.length; i++) {
String name = descriptorNames[i];
ItemDescriptorImpl d = (ItemDescriptorImpl)rep.getItemDescriptor(name);
d.invalidateItemCache();
}
Flushing Item Caches
Flushing Item Caches
The class
atg.repository.ItemDescriptorImpl
provides three methods that can be called on an item descriptor in
order to flush its cache. Each method provides an overloaded version with a
boolean parameter, where an argument of true
specifies to invoke the method across the
entire cluster; an argument of false
limits the flush operation to the local
repository.
Note: If the item descriptor is set to
distributed hybrid caching, any action on the local repository is propagated to
other ATG instances, whether invoked by the boolean or non-boolean method
version.
In order to use these methods,
atg.repository.RepositoryItemDescriptor
must be cast to atg.repository.ItemDescriptorImpl
.
invalidateItemCache()
Invalidates item caches for this item descriptor:
Invalidates item caches for this item descriptor:
void invalidateItemCache()
void invalidateItemCache(boolean pGlobal)
For example:
RepositoryImpl rep = getRepository();
ItemDescriptorImpl d = (ItemDescriptorImpl)rep.getItemDescriptor("user");
d.invalidateItemCache();
Note: This method’s boolean has no affect on
remote item caches that use distributed TCP caching; it only invalidates the
local item cache.
invalidateCaches()
Invalidates item and query caches for this item descriptor:
Invalidates item and query caches for this item descriptor:
void invalidateCaches()
void invalidateCaches(boolean pGlobal)
removeItemFromCache()
Removes the specified item from the cache:
Removes the specified item from the cache:
void removeItemFromCache(String pId)
void removeItemFromCache(String pId, boolean pGlobal)
void removeItemFromCache(String pId, boolean pGlobal, boolean pRemoveTransientProperties)
Flushing Query Caches
The class
atg.repository.RepositoryViewImpl
provides the method invalidateQueryCache()
, which
clears the query cache:public void invalidateQueryCache()
18. Relationship
in repository? How do you implement M2M relationship?
Item-Descriptor Relationships
•
One to One – Represented by ‘auxiliary’
tables.
•
One to Many – Represented by ‘multi’ tables
•
Many to Many – achieved using an
intermediate table.
The multi-column-name attribute ensures that the
ordering of the multi values are maintained.
Primary Tables
Each
item descriptor must specify one primary table. The primary table is specified
with the
type="primary"
XML attribute in a <table>
tag. The <table>
tag for the primary table sets its id-column-names
attribute to the columns that store the
repository ID. For example:<table name="user" type="primary" id-column-names="id">
properties...
</table>
Auxiliary Tables
You can
handle some data relationships with auxiliary attribute tables. For example,
you can store users and their addresses in two related database tables, as
described in the following piece of an XML repository definition:
<item-descriptor name="user">
<table name="dps_user" type="primary" id-column-names="id">
<property name="login" data-type="string"/>
</table>
<table name="dps_address" type="auxiliary" id-column-names="id">
<property name="address1"/>
<property name="city"/>
<property name="state"/>
<property name="zip"/>
</table>
</item-descriptor>
Each
user has a single address. For the purposes of this example, the user
information is stored in a separate table from the user’s address information.
Note: that if you use auxiliary tables, each
table definition, whether primary or not, must define an
id-column-names
attribute. This attribute defines the column names in the table that
represent the repository ID. This indicates how to join auxiliary tables to the
primary table. The columns in the id-column-names attribute must be listed in
the same order as they are in the id-column-names attribute of the primary
table.
Multi Tables
The following example shows how the XML
repository definition might specify the multi-valued property interests:
<item-descriptor name="user">
<table name="dps_user" id-column-names="id" type="primary">
<property name="login" data-type="string"/>
</table>
<table name="dps_interest" type="multi" id-column-names="id"
multi-column-name="idx">
<property name="interests" column-name="interest" data-type="array"
component-data-type="string"/>
</table>
</item-descriptor>
Some examples
demonstrate a variety of data relationship mappings
Simple One-to-One
This
example maps a repository item to a single table row. It includes just a
primary table, with no joins with other tables.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD Dynamo Security//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>Repository Example Version A</name>
<author>Pat Durante</author>
<description>
This template maps a repository item to a single
table row. Just a primary table...no joins with
other tables. Simplest case.
</description>
</header>
<item-descriptor name="user" default="true">
<table name="usr_tbl" type="primary" id-column-names="id">
<property name="id" data-type="string"/>
<property name="name" column-names="nam_col" data-type="string"/>
<property name="age" column-names="age_col" data-type="int"/>
</table>
</item-descriptor>
</gsa-template>
SQL Statements
drop table usr_tbl;
CREATE TABLE usr_tbl (
id VARCHAR(32) not null,
nam_col VARCHAR(32) null,
age_col INTEGER null,
primary key(id)
);
One-to-One with Auxiliary Table
This
example maps a repository item to a primary table and an auxiliary table (a
one-to-one relationship).
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD Dynamo Security//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>Repository Example Version B</name>
<author>Pat Durante</author>
<description>
This template maps a repository item to a
primary table and an auxiliary table (a one-to-one
relationship.) Each user has a job title and
function.
</description>
</header>
<item-descriptor name="user" default="true">
<table name="usr_tbl" type="primary" id-column-names="id">
<property name="id" data-type="string"/>
<property name="name" column-names="nam_col" data-type="string"/>
<property name="age" column-names="age_col" data-type="int"/>
</table>
<table name="job_tbl" type="auxiliary" id-column-names="id">
<property name="function"/>
<property name="title"/>
</table>
</item-descriptor>
</gsa-template>
SQL Statements
drop table usr_tbl;
drop table job_tbl;
CREATE TABLE usr_tbl (
id VARCHAR(32) not null,
nam_col VARCHAR(32) null,
age_col INTEGER null,
primary key(id)
);
CREATE TABLE job_tbl (
id VARCHAR(32) not null references usr_tbl(id),
function VARCHAR(32) null,
title VARCHAR(32) null,
primary key(id)
);
One-to-Many Mapping to Other Repository Items
This
example maps out a one-to-many relationship between
user
items and address
items. It demonstrates the use of the component-item-type
attribute, which allows one repository item
to contain other repository items. Each user
item can contain many address
items, such as home address, shipping
address, business address.<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD Dynamo Security//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>Repository Mapping Example Version F</name>
<author>Ben Erwin</author>
<description>
This template maps out a one-to-many relationship
between user items and address items. It
demonstrates the use of the component-item-type
attribute (which allows one repository item
to contain other repository items.) Each user
item will contain many address items (home address,
business address, etc.)
</description>
</header>
<item-descriptor name="address">
<table name="addr_tbl" type="primary" id-column-name="addr_id">
<property name="user" column-name="user_id" item-type="user"/>
<property name="street" data-type="string"/>
<property name="city" data-type="string"/>
</table>
</item-descriptor>
<item-descriptor name="user" default="true">
<table name="usr_tbl" type="primary" id-column-name="id">
<property name="id" data-type="string"/>
<property name="name" column-name="nam_col" data-type="string"/>
<property name="age" column-name="age_col" data-type="string"/>
</table>
<table name="addr_tbl" type="multi" id-column-name="user_id">
<property name="addresses" column-name="addr_id" data-type="set"
component-item-type="address"/>
</table>
</item-descriptor>
</gsa-template>
SQL Statements
CREATE TABLE usr_tbl (
id VARCHAR(32) not null,
nam_col VARCHAR(32) null,
age_col VARCHAR(32) null,
primary key(id)
);
CREATE TABLE addr_tbl (
addr_id VARCHAR(32) not null,
user_id VARCHAR(32) null references usr_tbl(id),
street VARCHAR(32) null,
city VARCHAR(32) null,
primary key(addr_id)
);
Many-to-Many
This
example maps out a many-to-many relationship. It defines two item types,
user
and address
. Each
user can have many addresses. Many users may live at the same address.<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD Dynamo Security//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<header>
<name>People Repository Version H</name>
<author>Pat Durante</author>
<description>
This template maps out a many-to-many relationship
between user items and address items. Each user can
have many addresses. Many users may live at the
same address.
</description>
</header>
<item-descriptor name="address">
<table name="addr_tbl" type="primary" id-column-names="address_id">
<property name="street" data-type="string"/>
<property name="city" data-type="string"/>
</table>
<table name="user_address_tbl" type="multi" id-column-names="addr_id">
<property name="users" column-names="user_id" data-type="set"
component-item-type="user"/>
</table>
</item-descriptor>
<item-descriptor name="user" default="true">
<table name="usr_tbl" type="primary" id-column-names="id">
<property name="id" data-type="string"/>
<property name="name" column-names="nam_col" data-type="string"/>
<property name="age" column-names="age_col" data-type="int"/>
</table>
<table name="user_address_tbl" type="multi" id-column-names="user_id">
<property name="addresses" column-names="addr_id" data-type="set"
component-item-type="address"/>
</table>
</item-descriptor>
</gsa-template>
SQL Statements
drop table addr_tbl;
drop table user_address_tbl;
drop table usr_tbl;
CREATE TABLE addr_tbl (
address_id VARCHAR(32) not null,
street VARCHAR(32) null,
city VARCHAR(32) null,
primary key(addr_id)
);
CREATE TABLE user_address_tbl (
addr_id VARCHAR(32) not null references addr_tbl(address_id),
user_id VARCHAR(32) not null references usr_tbl(id),
primary key(addr_id, user_id)
);
CREATE INDEX user_address_tbl_user_idx ON user_address_tbl(user_id);
CREATE TABLE usr_tbl (
id VARCHAR(32) not null,
nam_col VARCHAR(32) null,
age_col INTEGER null,
primary key(id)
);
19. What
is item-expire-timeout, query-expire-timeout and item-cache-timeout?
Cache Timeout
An item descriptor can limit
the lifetime of cached items in two ways:
Force
refreshes of items in the item and query caches
An item descriptor’s
item-expire-timeout
and query-expire-timeout
attributes specify how long items can stay
in the item and query caches, respectively, before they are invalidated. For
example, if the item-expire-timeout
for a cached item is set to 60000
(milliseconds), its data becomes stale
after 60 seconds; and the item must be reloaded from the database when it is
next accessed.
The following
item-descriptor
tag sets attributes item-expire-timeout
and query-expire-timeout
to 180 seconds:<item-descriptor name="order" cache-mode="simple"
item-expire-timeout="180000"
query-expire-timeout="180000">
...
</item-descriptor>
Refresh unused
item cache entries
An item cache entry is regarded
as stale if it is not accessed within the time span specified in its
item-cache-timeout
attribute. A stale item must be reloaded
from the database the next time it is accessed. If set to 0 (the default), the
item can remain indefinitely in the item cache until it is otherwise
invalidated.
The following
item-descriptor
tag sets attribute item-cache-timeout
to 180 seconds:<item-descriptor name="order" cache-mode="simple"
item-cache-timeout="180000">
...
</item-descriptor>
You can use cache timeout
attributes together with simple caching to control the behavior of repository
caches. Cache timeout attributes are useful for caching user data associated
with a particular session. A user session is typically handled by a single ATG
server for as long as the session lasts. If the user session expires and the
user moves to another ATG server, the cached data expires before the user can
log back on to a server that might have previously cached stale data for that
user.
Cache Configuration
The SQL repository maintains separate item caches and
query caches for unrelated item descriptors. Thus, each one can be configured
independently.
Item cache
attributes
You can configure item caches
with the following
<item-descriptor>
attributes:
Attribute
|
Description
|
item-cache-size |
The
maximum number of items of this type to store in the item cache. When this
maximum is exceeded, the oldest items are removed from the cache.
Note: Within an
inheritance tree, the last-read item descriptor’s
item-cache-size setting applies
to all item descriptors within the inheritance tree. In order to ensure the
desired item cache size, be sure to assign the same item-cache-size to all related
item descriptors
Default:
1000
|
item-expire-timeout |
The
maximum time in milliseconds that an entry can remain in the item cache
before its content becomes stale. After turning stale, the item cache entry
is reloaded from the database the next time it is accessed. See Cache
Timeout for more
information.
Default
0 (items remain cached indefinitely or until invalidated)
|
item-cache-timeout |
The
time in milliseconds that an item cache entry can remain unused before its
content becomes stale. After turning stale, the item cache entry is reloaded
from the database the next time it is accessed. See Cache
Timeout for more
information.
Default:
0 (items remain cached indefinitely or until invalidated)
|
Query cache
attributes
You can configure query caches
with the following
<item-descriptor>
attributes:
Attribute
|
Description
|
query-cache-size |
The
maximum number of queries for items of this type to store in the query cache.
When this maximum is exceeded, the oldest queries are removed from the cache.
Default:
0
|
query-expire-timeout |
The
maximum time in milliseconds that an entry can remain in the query cache
before its content becomes stale. After turning stale, the result set is
reloaded from the database the next time the entry is accessed. See Cache
Timeout for more
information.
Default:
0 (items remain cached indefinitely or until invalidated)
|
20. What
is Property Descriptor, Derived Property?
Property
Descriptor:
Suppose we have an item-descriptor “contact” in which
we are storing firstName,lastName and title and we need to concatenate these three values while displaying in the
front end.To implement this,
•
getPropertyValue method of
RepositoryPropertyDescriptor needs to be
overridden to implement the logic.
•
In the repository definition,the value of
property-type attribute of
displayContactName property which is a transient property is the Qualified class path of the implementation
class.
<item-descriptor name="contact" display-property="displayContactName">
<property name="displayContactName" data-type="string"
property-type="com.contact.ContactDisplayName" queryable="false" />
<table name="CONTACT_INFO" id-column-names="CONTACT_ID" type="primary">
<property name="firstName" column-name="FNAME"
data-type="string" required="true" />
<property name="lastName" column-name="LNAME" required="true" />
<property name="title" column-name="TITLE" required="true" />
</table>
</item-descriptor>
public class ContactDisplayName extends
RepositoryPropertyDescriptor {
@Override
public Object
getPropertyValue(RepositoryItemImpl pItem, Object pValue) {
//pItem
is nothing but contact repository item
StringBuilder
displayName = new StringBuilder();
//getting
the title repository value
String
title =
//getting
the firstName repository value
String
fname = (String) pItem.getPropertyValue("firstName");
//getting
the lastName repository value
String
lname = (String) pItem.getPropertyValue("lastName");
displayName
= displayName.append((String) pItem.getPropertyValue("title").
append
(".").append( (String)
pItem.getPropertyValue("firstName")).append(" ").
append((String)
pItem.getPropertyValue("lastName"))
return
displayName.toString();
}
}
See Another Example for Property Descriptor:
Derived
Property
In an SQL repository, you can
use derived properties. This feature enables one repository item to derive
property values from another repository item or from another property in the
same repository item. To illustrate: some data models are organized in a tree
structure where certain property values are passed down from other properties.
For example, an organization might have divisions, departments, and employees,
organized in a tree structure. A repository represents this tree structure with
division
, department
, and employee
item
descriptors. Each of these item descriptors might define a property called spendingLimit
. A
business rule might specify that an employee’s spending limit comes from their
department if it is not set for that employee. If the spending limit is not set
for the department it should be derived from the spending limit for the
division.
This derived property relationship
is represented in a repository definition file as follows:
<item-descriptor name="employee">
<property name="department" item-type="department"/>
<property name="empSpendingLimit" data-type="int"/>
<property name="spendingLimit" writable="false">
<derivation>
<expression>empSpendingLimit</expression>
<expression>department.spendingLimit</expression>
</derivation>
</property>
</item-descriptor>
<item-descriptor name="department">
<property name="division" item-type="division"/>
<property name="deptSpendingLimit" data-type="int"/>
<property name="spendingLimit" writable="false">
<derivation>
<expression>deptSpendingLimit</expression>
<expression>division.divSpendingLimit</expression>
</derivation>
</property>
</item-descriptor>
<item-descriptor name="division">
<property name="division" item-type="division"/>
<property name="divSpendingLimit" data-type="int"/>
</item-descriptor>
Note:
When it is requested, the value of empSpendingLimit
is returned if it is non-null; otherwise, department.spendingLimit
is returned.
Derived properties can use multiple levels of subproperties. So
the spending limit example might derive the employee’s spending limit as
follows:
<item-descriptor name="employee">
<property name="department" item-type="department"/>
<property name="spendingLimit" data-type="int" writable="false">
<derivation>
<expression>department.employeeDefaultInfo.spendingLimit</expression>
</derivation>
</property>
</item-descriptor>
<item-descriptor name="department">
<property name="employeeDefaultInfo" item-type="employeeInfo"/>
<property name="deptSpendingLimit" data-type="int"/>
</item-descriptor>
<item-descriptor name="employeeInfo">
<property name="spendingLimit" data-type="int" writable="false"/>
<property name="officeLocation" data-type="string"/>
</item-descriptor>
21. What
is Request handling pipeline? Types of pipeline?
One of the most important tasks for an Oracle ATG Web
Commerce server is handling HTTP requests. The Oracle ATG Web Commerce server
extends the basic web server model with various Nucleus services that implement
the
Servlet
interface, and
which are linked in order to process HTTP requests. Each servlet performs a
specialized function on a request, then relays the request—sometimes in
modified form—to the next servlet in the chain. While each servlet performs a
unique service, it often relies on changes that previous servlets made to the
request. This chain of servlets is called a request handling pipeline.
There are
two request-handling pipelines used by Dynamo.
·
DAF Servlet
Pipeline - It is used to handle the JSP request.
·
DAS Servlet
pipeline - It is used to handle JHTML request.
Starting the Request-Handling Pipeline
The second resource called by
the Web container executes the request-handling pipeline. The resource you
specify here depends on the type of pages you author:
·
For JSPs, specify the
PageFilter
filter.
·
For JHTML pages, specify the
DynamoProxyServlet
servlet.
Both
PageFilter
and DynamoProxyServlet
call an instance of DynamoHandler
, which
is the first servlet in the pipeline. DynamoHandler
generates
a DynamoHTTPServletRequest
(called
the Dynamo request) that wraps the generic HTTPServletRequest
so that servlets are able to read
information on the request as well as modify the request itself. A matching DynamoHTTPServletResponse
is also generated. DynamoHandler
passes the Dynamo request/response pair to
the next servlet in the request-handling pipeline. This pipeline is a series of
servlets that share dynamic information about the request and response with the
Nucleus framework in order to render the requested page.
Although
DynamoHandler
chiefly does the same thing in both
pipelines, a different version of it is used for each request type.
·
PageFilter
calls /atg/dynamo/servlet/dafpipeline
/DynamoHandler
to start the DAF servlet pipeline for JSP
requests.
·
DynamoProxyServlet
calls /atg/dynamo/servlet/pipeline/DynamoHandler
to start the DAS servlet pipeline for JHTML
requests.
The main difference between the
DAS and DAF servlet pipelines is that the DAS servlet pipeline automatically
compiles the page from JHTML to Java, whereas the DAF servlet pipeline relies
on the application server to handle the complete page compilation process.
Sites that use
JSPs: PageFilter
When your site uses JSPs,
include
PageFilter
in web.xml
:
·
Insert the filter name and class name in enclosing
<filter>
tags.
·
Map the filter to either a directory holding JSPs or the
.jsp
extension. This information is included in
enclosing <filtermapping>
tags.
This example shows the code you
should include in
web.xml
:<filter>
<filter-name>PageFilter</filter-name>
<filter-class>atg.filter.dspjsp.PageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PageFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
Sites that use
JHTML Pages: DynamoProxyServlet
To use
DynamoProxyServlet
in web.xml
:
·
Insert the servlet name, class, and execution order in enclosing
<servlet>
tags. The order of execution should be 2,
so that DynamoProxyServlet
runs just afterNucleusServlet
.
·
Map this servlet either to the directory holding JHTML files or to
the extension
.jhtml
. This
information is provided in enclosing <servletmapping>
tags.
This example shows the code you
should include in
web.xml
:<servlet>
<servlet-name>DynamoProxyServlet</servlet-name>
<servlet-class>atg.nucleus.servlet.NucleusProxyServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DynamoProxyServlet</servlet-name>
<url-pattern>/dyn/*</url-pattern>
</servlet-mapping>
Sites that Use
JSPs and JHTML Pages
For sites using both JSP and
JHTML pages, you need to define both
PageFilter
and DynamoProxyServlet
resources in your web.xml
so they are available when needed. For each
request, one of the two resources is called just after NucleusServlet
.
Request Processing
By default,
PageFilter
is mapped to handle
JSP requests. When the application server invokes PageFilter
,
it checks the request and response for a reference to a Dynamo request and
response pair. The pair does not exist, so PageFilter
starts the DAF
servlet pipeline by calling DynamoHandler
,
the first servlet in the pipeline. The DAF servlet pipeline processes through a
series of servlets that modify the request and response by extracting path
information and providing session, user, and security information. The last
servlet in the pipeline is TailPipelineServlet
.
It is responsible for calling FilterChain.doFilter()
,
which invokes the next filter defined inweb.xml
.
The web application, unless it uses Oracle ATG Web Commerce Portal, does not
include other servlet filters.
You can
use the ATG Dynamo Server Admin Component Browser to view request handling
pipeline servlets and their sequence within the pipeline:
a) In the
Component Browser (
http://host:port/dyn/admin/nucleus/
),
navigate to the first pipeline servlet: /atg/dynamo/servlet/dafpipeline/DynamoHandler
b) The
Component Browser lists all pipeline servlets in order of execution.
22. Customizing
request handling pipeline?
The
atg.servlet.pipeline
package provides interfaces for creating
request handling pipeline servlets. All pipeline servlet classes directly or
indirectly implement interfaceatg.servlet.pipeline.PipelineableServlet
. This
interface provides a nextServlet
property that points to the next component
in the pipeline. The ATG installation provides the implementation class atg.servlet.pipeline.PipelineableServletImpl
, which
you can subclass to create your own servlets. PipelineableServletImpl
implements
all Servlet
methods, so you only need to override the service
method.
To
insert into a request handling pipeline a servlet that subclasses
PipelineableServletImpl
:
a) Extend
atg.servlet.pipeline.PipelineableServletImpl
.
b) Define
the servlet as a globally scoped Nucleus component.
c) Reset
the previous servlet’s
nextServlet
property to point to the new servlet.
d) Set the
new servlet’s
nextServlet
property to point to the next servlet in
the pipeline.
e) Add the
servlet’s path to the
initialServices
property of /atg/dynamo/servlet/Initial
.
The
PipelineableServlet
interface has two sub-interfaces that
provide more flexibility for inserting new servlets into the pipeline:
InsertableServlet
The
InsertableServlet interface lets a servlet insert itself into the pipeline when
the service starts, without requiring changes to servlets already in the
pipeline, through the
insertAfterServlet
property, which points back to the
preceding servlet. The inserted servlet reads the preceding servlet’s nextServlet
property and points to it as the next
servlet to execute after itself.
For
example, a servlet pipeline might contain Servlet1, whose
nextServlet
property points to Servlet2. You can insert
MyNewServlet, which implementsInsertableServlet
,
between the two by setting its insertAfterServlet
property so it points to Servlet1. This
configuration splices ServletNew between Servlet1 and Servlet2 as follows:
·
MyNewServlet sets its own
nextServlet
property to the value of Servlet1’s nextServlet
property.
·
MyNewServlet reads Servlet1’s
nextServlet
property and links to Servlet2 as the next
servlet to execute after itself.
If an
insertable servlet inserts only itself into a pipeline, it uses the
nextServlet
property of its insertAfterServlet
servlet to resume pipeline execution. However,
if the inserted servlet starts a secondary pipeline, it sets its own nextServlet
property to the next servlet in that
pipeline. After the last secondary pipeline servlet executes, it passes control
to the nextServlet
servlet originally specified by the insertAfterServlet
servlet, and the original pipeline resumes
execution.
The ATG
installation provides an implementation of the InsertableServlet interface,
atg.servlet.pipeline.InsertableServletImpl
. This
class implements all Servlet
methods,
so you only need to override the service
method.
To add
an
InsertableServlet
to the servlet pipeline:
a)
Write your servlet by extending
atg.servlet.pipeline.InsertableServletImpl
.
b)
Define the servlet as a globally scoped Nucleus component.
c) Set the
insertAfterServlet
property of your servlet to point to the
path of the pipeline servlet you want your servlet to follow. For example, you
can insert a servlet after DynamoServlet
as follows:insertAfterServlet=/atg/dynamo/servlet/dafpipeline/DynamoServlet
d) Add the
servlet’s path to the
initialServices
property of /atg/dynamo/servlet/Initial
:initialServices+=/myServlet
When
the inserted servlet finishes processing, it calls the method
passRequest()
(defined in InsertableServletImpl
),
which automatically passes the request and response objects to the next servlet
in the pipeline.
Sample Servlet Code
The
following pipeline servlet class
URIPrinter
extends atg.servlet.pipeline.InsertableServletImpl
. It
prints the request URI before passing the request on to the next servlet in the
pipeline:import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import atg.servlet.*;
import atg.servlet.pipeline.*;
public class URIPrinter extends InsertableServletImpl {
public URIPrinter () {
}
public void service (DynamoHttpServletRequest request, DynamoHttpServletResponse response)
throws IOException, ServletException {
System.out.println ("Handling request for " + request.getRequestURI ());
passRequest (request, response);
}
}
Note: Subclasses of
InsertableServletImpl
that add their own logic to doStartService
must call super.doStartService()
.
DispatcherPipelineableServlet
The
DispatcherPipelineableServlet
interface provides a mechanism for
conditionally branching the pipeline. This interface includes a dispatcherServiceMap
property that is a Map of possible servlets
to invoke next, depending on some condition. For example, the MimeTypeDispatcher
servlet determines which servlet to invoke
depending on the MIME type of the request. ATG provides the implementation
class DispatcherPipelineableServletImpl
.
23. What
are the Advantages of DAF?
·
It is used to maintain huge data.
·
It has repositories which help is data
anywhere architecture.
·
Dependency injection.
·
It can write any object of type 1 call in
to the db.
·
Dynamo messaging using patch bay and JMS.
·
“Inversion of Control” design pattern,
whereby software components are discrete.
·
Entities coupled together by the Nucleus
container, rather than through direct reference.
24. Logging
features of ATG?
Oracle
ATG Web Commerce includes three different systems for sending, receiving, and
recording messages generated by components: Logging, Data Collection, and
Recorders. Oracle ATG Web Commerce Logging provides a convenient way to log
system messages. Any component that extends the GenericService class or
implements the ApplicationLogging interface can send LogEvents that are
received by log listeners and logged to a flat file. The logging system can log
only text messages and exceptions.
Any
component whose base class implements “ApplicationLogging” Interface can use
atg logging infrastructure. Logging can be done per-component, per-module or
per-application basis. Error, Warning, Info & Debug messages are the
various logging mechanisms. First three are logged by default,
whereas the Debug messages are just for debugging purpose and should be removed
when the code goes into production. Logging is managed using the
“GLOBAL.properties” file, which specfies the log levels of various modules.
25. What
is Configuration Layering?
Properties
set in later entries in the CONFIGPATH override earlier entries. By adding an
entry to the config-path you can customize any components in the system without
losing the original configuration information. You can have a global
configuration common to all machines then have machine specific information in
the last layer.
26. How
to register a repository with the dynamo?
Create
“/config/atg/registry/ContentRepositories.properties”
file and append our repository file (XML) name to the “initialRepositories”
property
initialRepositories+=
/myModule/mySampleRepository
27. What
are the performance issues with ATG?
Performance
problems come in many shapes and sizes, but they all mean that the processing
of some task is not happening at the expected and previously observed speed.
·
Performance issues include CPU utilization
problems
·
Slow response times
·
High levels of database activity
·
Long running SQL queries
·
Slow CA deployments
Just
to name a few.
28. What
is module hierarchy in ATG?
Module Dependencies
ATG
application often depends on other modules which are started automatically when
your module is started. These dependencies are declared in the module manifest
file at location
<module-name>/META-INF/MANIFEST.MF
The
list show above will include DSS at a minimum. If our application uses
facilities provided by other application layers (e-commerce) then we will need
to include those modules in the list as well. Note that we only need to include
the top-level module; all additional modules required by the top modules will
automatically be started.
E.g.
If our application requires DSS, which requires DPS, then we need to specify
only DSS not DPS.
ATG Modules
The
following tables list the module names for the main Oracle ATG Web Commerce
applications, demos, and reference applications. This is not an exhaustive list
of all Oracle ATG Web Commerce modules.
Module
|
Description
|
Admin.Init |
Adds
missing administrative accounts for the ATG Control Center. For more
information, see the Managing
Access Control chapter.
|
Admin.Reset |
Resets
the default login accounts for the ATG Control Center. For more information,
see the Managing
Access Control chapter.
|
DAF.Search |
Enables
the Oracle ATG Web Commerce platform integration with Oracle Endeca Commerce.
See the ATG-Endeca
Integration Guide.
|
DAS-UI |
Enables
an Oracle ATG Web Commerce server to accept connections from the ATG Control
Center.
Note: This module must
be running if you want to use the ATG Control Center.
|
DCC |
Runs
the ATG Control Center in the same JVM used by the application server that
the Nucleus-based application is running on. For more information, see the Installation
and Configuration Guide.
|
DPS |
Oracle
ATG Web Commerce Personalization.
|
DSS |
Oracle
ATG Web Commerce Scenarios.
|
DSSJ2EEDemo |
Oracle
ATG Web Commerce demo (Quincy Funds).
|
RL |
Repository
Loader. Takes files that are stored in a file system, converts them into
repository items, and loads the items into the repository. To learn more, see
the Repository
Guide.
|
SQLJMSAdmin |
Browser-based
administration interface for Oracle ATG Web Commerce’s SQL JMS message
system. For more information, see Using
the SQL-JMS Administration Interface.
|
Content Administration Modules
Module
|
Description
|
AssetUI |
Supports
the building of browser-based user interfaces for an ATG Content
Administration (versioned) environment. The module includes the Asset Picker
and functionality related to it. Requires the
WebUI module (see
below). |
BizUI |
The
Oracle ATG Web Commerce Business Control Center. Includes the Home page
functionality.
|
PublishingAgent |
Publishing
Agent. Runs on production and staging servers and performs content deployment
operations by communicating with the ATG Content Administration server.
|
PublishingWebAgent |
Publishing
web agent. Runs on the production and staging web servers and performs web
content deployment operations by communicating with the ATG Content
Administration server.
|
Publishing.base |
|
Publishing.WebAppRef |
The
source module for the Web Application Reference Implementation provided with
ATG Content Administration.
|
Publishing.WebAppRefVer |
The
versioning module for the Web Application Reference Implementation provided
with ATG Content Administration.
|
PubPortlet |
Supplies
the portlets that make up the Oracle ATG Web Commerce Business Control Center
interface. Including this module also causes the
Publishing.base , AssetUI , and BizUI modules to be
included. Include this module to perform most basic tasks in ATG Content
Administration, such as product evaluation. |
WebUI |
Contains
support for browser-based user interfaces. Examples are the tree-based asset
browsing feature, a calendar widget, and the View Mapping system.
|
Portal Modules
Module
|
Description
|
Portal.gears |
Includes
the Portal Application Framework and baseline gears.
|
Portal.paf |
Portal
Application Framework (PAF). At a minimum, you must include this module to
use Oracle ATG Web Commerce Portal. To learn more about the PAF, see the Portal
Administration Guide.
|
Portal.gear-name Portal.portlet-name |
Includes
the specified gear or portlet. For example, if you create a gear called
productprices , include the
module Portal.productprices . |
ATG Commerce Modules
Module
|
Description
|
B2BCommerce |
ATG
Business Commerce
Note: To run ATG
Commerce, you must use one and only one of the following modules:
B2BCommerce,B2BCommerce.Versioned, B2CCommerce , or B2CCommerce.Versioned . |
B2BCommerce.Versioned |
Use
instead of
B2BCommerce module if running
ATG Merchandising. (Also requires modules DCS-UI.Versioned and PubPortlet .)
Note: To run ATG
Commerce, you must use one and only one of the following modules:
B2BCommerce,B2BCommerce.Versioned, B2CCommerce , or B2CCommerce.Versioned .
Including
this module also includes
B2BCommerce , DCS.DynamicCustomCatalogs.Versioned , and their
modules. |
B2CCommerce |
ATG
Consumer Commerce
Note: To run ATG
Commerce, you must use one and only one of the following modules:
B2BCommerce,B2BCommerce.Versioned, B2CCommerce , or B2CCommerce.Versioned .
Including
this module also includes
DCS and its modules. |
B2CCommerce.Versioned |
Use
instead of
B2CCommerce module if running
ATG Merchandising. (Requires the DCS-UI.management and PubPortlet modules also.)
Note: To run ATG
Commerce, you must use one and only one of the following modules:
B2BCommerce,B2BCommerce.Versioned, B2CCommerce , or B2CCommerce.Versioned .
Including
this module also includes
B2Commerce , DCS.Versioned , and their
modules. |
CommerceGears.orderapproval |
Order
Approval Portal Gear (Requires ATG Portal also.)
Including
this module also includes
Portal.paf , Portal.authentication , Portal.templates ,Portal.communities , B2BCommerce , and their
modules. |
CommerceGears.orderstatus |
Order
Status Portal Gear (Requires ATG Portal also.)
Including
this module also includes
Portal.paf , Portal.authentication , Portal.templates ,Portal.communities , DCS , and their
modules. |
Cybersource |
Third-party
commerce module (from CyberSource Corp.) for authorizing credit cards, crediting
and settling accounts, calculating taxes, and verifying addresses.
Including
this module also includes
DCS and its modules. |
DCS |
Base
ATG Commerce module.
Including
this module also includes
DSS , DPS , and their
modules. |
DCS.AbandonedOrderServices |
Provides
tools for dealing with abandoned orders and shopping carts.
Including
this module also includes
DCS and its modules. |
DCS.CustomCatalogs |
Runs
custom catalogs in an ATG Commerce production environment, required to
support pre-ATG 11.0 Commerce applications; otherwise unused.
|
DCS.DynamicCustomCatalogs |
Runs
custom catalogs in an ATG Commerce development environment.
Including
this module also includes
DCS.CustomCatalogs and its modules. |
DCS.DynamicCustomCatalogs. Versioned |
Runs
custom catalogs in an environment running ATG Commerce and ATG Merchandising.
(Requires the
DCS-UI.management and PubPortlet modules also.)
Including
this module also includes
DCS.DynamicCustomCatalogs , DCS.CustomCatalogs.Versioned , and their
modules. |
DCS.PublishingAgent |
Use
instead of the
PublishingAgent module on the
target server if ATG Commerce repository items are deployed to that server.
Including
this module also includes
PublishingAgent , DCS , and their
modules. |
DCS.Search |
Adds
commerce-specific elements to the integration with Oracle Endeca Commerce.
See the ATG-Endeca
Integration Guide.
|
DCS.Versioned |
Use
instead of
DCS module if running
ATG Commerce with ATG Merchandising.
Including
this module also includes
Publishing.base , DCS , and their
modules. |
DCSSampleCatalog |
ATG
Commerce Sample Catalog.
Including
this module also includes
DCS and its modules. |
Fulfillment |
ATG
Commerce order fulfillment.
Including
this module also includes
DCS and its modules. |
MotorpriseJSP |
ATG
Business Commerce reference application (Motorprise).
Including
this module also includes
B2BCommerce , DCS.AbandonedOrderServices , and their
modules. |
PayFlowPro |
Third-party
commerce module (from VeriSign) for handling credit card authorization,
settlement, and crediting.
Including
this module also includes
DCS and its modules. |
Taxware |
Third-party
commerce module (from ADP Taxware) for calculating taxes, verifying addresses
and determining tax jurisdictions.
Including
this module also includes
DCS and its modules. |
Reference: ATG
Modules and features
29. EAR
file structure in ATG Project?
Manifest file: <module-name>/META-INF/MANIFEST.MF
Manifest-Version: 1.0
ATG-Config-Path: config/
ATG-Required: DAS DPS DSS
ATG-J2EE: j2ee-apps/EShop-ee.ear
ATG-EAR-Module: j2ee-apps/EShop-ee.ear
ATG-Class-Path: lib/
Through
command line move to C:\ATG\ATG9.1\home\bin and execute the following command:
runAssembler C:\Dummy.ear –m
Dummy;DafEar;DafEar.Admin
The
above command takes semi-colon separated list of modules to be assembled into
the big EAR and also two other important applications that make up the ACC
viz., DafEar and DafEar.Admin. The resultant Dummy.ear is created in the C:\
drive.
To enable
liveconfig
, you
can use the –liveconfig
argument for runAssembler
(see the Assembling
Applications section
of the ATG
Programming Guide), or add the following line to the WEB-INF/ATG-INF/dynamo.env
file in the atg_bootstrap.war
module of your EAR file:atg.dynamo.liveconfig=on
30. What
is ATG Scheduler? What you did in ATG Scheduler?
Most
server-side applications have routine tasks that must be performed
periodically. For example, a component in the application might need to clear a
cache every 10 minutes, or send email each morning at 2:00, or rotate a set of
log files on the first of every month.
Oracle ATG Web Commerce includes a Scheduler
service, atg.service.scheduler.Scheduler, which keeps track of
scheduled tasks and executes the appropriate services at specified times. You
can see a list of all scheduled tasks in the Component Browser at /atg/dynamo/service/Schedule.
Oracle ATG Web Commerce also includes a SingletonSchedulableService, atg.service.scheduler.SingletonSchedulableService, which
enables multiple Oracle ATG Web Commerce servers to run the same scheduled
service, while guaranteeing that only one instance of the service performs the
scheduled task at a time. This provides some protection from server failures,
as the loss of one Oracle ATG Web Commerce server does not prevent the
scheduled service from running on another Oracle ATG Web Commerce server.
Writing a Schedulable Component
The component
needs to be configured with two properties:
scheduler |
Points
to a Scheduler such as the standard Oracle ATG Web Commerce Scheduler.
|
schedule |
Points
to the standard Oracle ATG Web Commerce Scheduler. The
schedule property can be
set in a wide variety of formats, which Oracle ATG Web Commerce interprets
through the PropertyEditor that is defined
for the Schedule type. For more
information on format options, see the next section, Schedule
Settings. |
For
example:
scheduler=/atg/dynamo/service/Scheduler
schedule=every 10 seconds
This section describes how to write a component
that schedules itself to perform a task according to different schedules. In
this case, the task to be performed is to write Hello to
the console.
Such a component might look like this:
import atg.nucleus.*;
import atg.service.scheduler.*;
public class HelloJob extends GenericService implements Schedulable
{
public HelloJob () {}
// Scheduler property
Scheduler scheduler;
public Scheduler getScheduler () { return scheduler; }
public void setScheduler (Scheduler scheduler)
{ this.scheduler = scheduler; }
// Schedule property
Schedule schedule;
public Schedule getSchedule () { return schedule; }
public void setSchedule (Schedule schedule)
{ this.schedule = schedule; }
// Schedulable method
public void performScheduledTask (Scheduler scheduler,
ScheduledJob job)
{ System.out.println ("Hello"); }
// Start method
int jobId;
public void doStartService () throws ServiceException
{
ScheduledJob job = new ScheduledJob ("hello",
"Prints Hello",
getAbsoluteName (),
getSchedule (),
this,
ScheduledJob.SCHEDULER_THREAD);
jobId = getScheduler ().addScheduledJob (job);
}
// Stop method
public void doStopService () throws ServiceException
{
getScheduler ().removeScheduledJob (jobId);
}
}
Notice that this component extends GenericService, which
allows it to be notified of start and stop conditions through doStartService and doStopService. The
component also implements Schedulable by defining the performScheduledTask method
to print Hello. The component also requires the schedulerand schedule to
be set as properties.
When the component is started, it constructs a ScheduledJob from
the schedule property, and also specifies that the job should run in the
Scheduler’s thread. The component then adds the job to the Scheduler, and
stores the job ID returned by the Scheduler. When the component is stopped, it
removes the scheduled job by passing the ID of the job.
ScheduledJob Thread Methods
A
ScheduledJob
component has a threadMethod
property that indicates what threading
model should be used to execute the scheduled job. ThethreadMethod
property can have one of the following
values:
SCHEDULER_THREAD |
The
job is run in the Scheduler’s own thread. This is the most efficient thread
method, but it blocks the Scheduler from performing any other jobs until the
job is complete. Therefore, use this thread method only for jobs that do not
take a long time to run. Jobs that use I/O should probably avoid using this
option.
|
SEPARATE_THREAD |
Each
time the job is triggered, a new thread is created to run the job. The thread
is destroyed when the job completes. If a job is set to run periodically at a
rate that is faster than the job itself can run, new threads are created to
handle those jobs.
|
REUSED_THREAD |
A
separate thread is created to handle the job. Whenever the job is triggered,
that thread is directed to run the job. When the job completes, the thread
stays around waiting for the next time the job is triggered. If the job is
still running when it is scheduled to begin to run again, it does not start
again until the next time around. With this method, the Scheduler thread is
not blocked by executing jobs, and threads do not multiply out of control if
the job is triggering too quickly.
|
Schedule Settings
The
schedule
property of a Schedulable component can be
set in a variety of formats, which Oracle ATG Web Commerce interprets through
thePropertyEditor
that is
defined for the Schedule
type.
The
different types of Schedules can also be created programmatically by creating
instances of
RelativeSchedule
, PeriodicSchedule
, orCalendarSchedule
.
You can
set a schedule property to a
PeriodicSchedule
and RelativeSchedule
alone or in combination:
·
PeriodicSchedule
specifies a task that occurs at regular
intervals, in this format:schedule=every
integer
time-unit[ with catch up]
·
RelativeSchedule
specifies a time relative to the current
time, in this format:schedule=in
integer
time-unit
with catch up
You can
qualify a PeriodicSchedule with the string
with catch up
, which
determines whether the PeriodicSchedule
tries to catch up on missed jobs.
By specifying with catch up, you can
force execution of the missed jobs:
schedule=every 2 seconds with catch up
CalendarSchedule
A
CalendarSchedule
schedules a task to run at designated
points on the calendar. For example, you might schedule a task for 2:30am each
Sunday, or a specific date such as January 1. The format for a CalendarSchedule
looks like this:schedule=calendar mos dates wkdays mo-occurs hrs mins
Running the Same Schedulable Service on Multiple Servers
The
SingletonSchedulableService
,
a subclass of the standard SchedulableService
,
works in conjunction with a client lock manager to guarantee that only one
instance of a scheduled service is running at any given time throughout a
cluster of cooperating Oracle ATG Web Commerce servers.
Configuring a SingletonSchedulableService
SingletonSchedulableService
is an abstract class that extends SchedulableService
and implements the performScheduledTask
method in a way that tests for other
instances of the service before proceeding.
To
implement a
SingletonSchedulableService
,
create a subclass of this class, and then create a component based on that
subclass. Configure the component with a reference to a client lock manager, a
lock name, and a timeout period. For example:#Thu Aug 09 19:15:14 EDT 2001
$class=myclasses.MySingletonSchedulableService
$scope=global
clientLockManager=/atg/dynamo/service/ClientLockManager
lockName=ReportingLockManager
lockTimeOut=2000
Monitoring the Scheduler
To see a list of scheduled jobs in your application, navigate to
the /atg/dynamo/service/ Scheduler component in dynamo admin.
No comments:
Post a Comment