Saturday, 18 February 2017

Navigation State in Endeca

The Term Navigation State Can be Defined as the Current State of the Search, by which we can Filter or Sort the Results, the Navigation state is considered to be the Way Endeca identifies the Request and Process it accordingly.

The Componet /atg/endeca/assembler/cartridge/manage/NavigationStateBuilder is Responsible for Defining the Navigation  State.

This Component is of class ExtendedNavigationStateBuilder extends UrlNavigationStateBuilder.We Can See What are the Advatages of Class and How to Define it.

This class has the Method parseNavigationState which is being Called whe the Scope comes to the Navigation State, This method in turn calls Correspondig Navigation StatProcessors .For More Details on the Navigation State Processors You can Watch out My posts

http://searchendeca.blogspot.in/2016/10/usersegments-in-endeca.html

This Method Inturn Calls the parseRangeFilters which takes the Values that we defined as Range Filters.

This Method also inturn Calls the parseRecordFilters which holds the Value We Defined as RecordFilters.

For More Details about Record Filters You Ca Watch Out My Blogs Regarding the Record Filters

http://searchendeca.blogspot.in/2017/02/record-filters-in-endeca.html

If your Logic Needs to play wit this RecordFilter,RangeFilters You Can Play with this Class. 

Friday, 17 February 2017

Record Filters in Endeca

The Term Record Filter Can be Defined as Filtering the Records based on Some Property Value, this Type of Filters Can be added once if we know the Value that can Filtered from the List of Records , endeca Provides the Powerful Way by Which we can Achieve this functionality.

Step:1

Make the corresponding property as Record Filterable.

For More Information how to make property as Record Filterable You can Watch my following posts .

http://searchendeca.blogspot.com/2016/09/about-indexconfigcmdbat.html This posts has the Procedure to make the property as the RecordFilterable.


Step:2

Create a component of class that extends RecordFilterBuilderImpl and Override the buildRecordFilter method , the Return Value should be the Filterable Value.


Step:3

After you create a particular component you have to register the Same in the Navigation State by assaing to  recordFilterBuilders property in the NavigationStateBuilder component in the Path /atg/endeca/assembler/cartridge/manager this Filter Class will be called and set in the Navigation State During the Request.



For Reference you can Refer LocationTypeFilterBuilder From CRS.


Saturday, 31 December 2016

Happy New Year 2017

Hi Guys, hope you are doing well. Happy New Year to all of you let this New Year bring you all the happiness in your life. Hope fully  i will  continue writing this blog for the further updates on the Oracle commerce Guided search.  Lets all have the Fun Learning Part this year also.



Saturday, 17 December 2016

RuleSet in ATG / Indexed Item Group

HI all, I feel all are good and doing their best. Today we are going to see some interesting topic on the indexing part of the endeca. We cannot claim this topic to be fully endeca . Its ATG topic that we are utilizing for the indexing as well. It is  considered to be the simpler one but I am writing this blog to ease most of the logic we write during the accessor time.Its very effective and easy.

Ruleset can be defined as the couple of condition that is written for some specific purpose or does some specific purpose.As of my knowledge on endeca there is no mechsanism where we can restrict the products or the skus to be restricted from the search , apart from the recordfilter property constraints. If we implement the above constraint also that’s going to be the highly performance driven one. If that does not require more than reverting the code is also a complex one.
ProductCatalog outputconfig is a component that is responsible for providing the product for indexing . in the above component we can define the Repository Item group property to be pointing to the IndexedItem Group component where we will be defining the ruleset.

Rule set has two types of the condition.
1) Accepts rule.
2) Rejects rule.
These rules were called during the indexing process and corresponding filtration is done.  You can find the oracle document briefly describing about this. I am going to describe in terms of  Integration with the ATG and some of the problems we face during the development of the endeca.

Case:1
To Remove the Inactive products during the Indexing. We can define this type of condition in both accepts and reject clause.
 rules=\
<ruleset>\
<accepts>\
                <rule op\=eq>\
                                <valueof target\="isActive">\
                                <valueof constant\="true">\
                 </rule>\
</accepts>\
 </ruleset>

Case: 2
To remove only the specific set of items during the indexing. Where item may be product or some other repo item. Were id is the repo id.
rules=\
<ruleset>\
<rejects>\
                <rule op\=includes>\
   <valueof constant\="[item1,item2]">\
  <valueof target\="id">\
    </rule>\
    </rejects>\
</ruleset>

How to define in that component .

/atg/commerce/search/IndexedItemsGroup.properties

Define the ruleset in the string format is must. we cannot define the ruleset for the skulevel . Since the product-sku mapping has defined the sku as map .



Monday, 5 December 2016

Endeca Errors

1) @error:com.endeca.infront.navigation.NavigationException: com.endeca.navigation.ENEConnectionException: Connection unable to determine response code from navigation engine


ROOT CAUSE:
When you encounter the above error, check for the ENEQuery Being sent to Endeca. It Must be overloaded with the FieldNames or sorters or any other fields. 

IDENTIFICATION:
Check for the Dgraph Logs for the Query being sent to Endeca.

SOLUTION:
 Follow the Best Practises in setting up the Query, always initialize and set in query.

2) @error=com.endeca.infront.content.ContentException: com.endeca.navigation.ENEConnectionException: HttpENEConnection looking for binary port of Navigation Engine, but found XML port instead. Reconfigure connection to port-2 for binary Navigation Engine port. Check MDEX Logs and specified query parameters


ROOT CAUSE:
When you Encounter above error it means , you are getting the Exception from the LoadBalancer VIP that was configured. When the Mdex is down for few seconds because of the Indexing is in Progess, during that time you will face this issue.

IDENTIFICATION:
Configure the VIP in Assembler Application Configuration and make the Dgraph Down from EAC admin console and hit the Application.

SOLUTION:
 WorkAround should be in the Load Balancer side . 

3) SEVERE: Caught an exception while invoking method 'run' on object 'BaselineUpdate'. Releasing locks.
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.endeca.soleng.eac.toolkit.Controller.invokeRequestedMethod(Controller.java:931)
        at com.endeca.soleng.eac.toolkit.Controller.execute(Controller.java:269)
        at com.endeca.soleng.eac.toolkit.Controller.main(Controller.java:137)
Caused by: com.endeca.soleng.eac.toolkit.exception.AppControlException: Error executing valid BeanShell script.
        at com.endeca.soleng.eac.toolkit.script.Script.runBeanShellScript(Script.java:179)
        at com.endeca.soleng.eac.toolkit.script.Script.run(Script.java:127)
        ... 7 more
Caused by: com.endeca.soleng.eac.toolkit.exception.CasCommunicationException:
 Error starting baseline crawl 'stg1-last-mile-crawl'.
        at com.endeca.eac.toolkit.component.cas.ContentAcquisitionServerComponent.startBaselineCasCrawl
(ContentAcquisitionServer
Component.java:400)
        at com.endeca.eac.toolkit.component.cas.ContentAcquisitionServerComponent.runBaselineCasCrawl
(ContentAcquisitionServerComponent.java:308)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at bsh.Reflect.invokeMethod(Unknown Source)
        at bsh.Reflect.invokeObjectMethod(Unknown Source)
        at bsh.Name.invokeMethod(Unknown Source)
        at bsh.Reflect.invokeObjectMethod(Unknown Source)
        at bsh.Name.invokeMethod(Unknown Source)
        at bsh.BSHMethodInvocation.eval(Unknown Source)
        at bsh.BSHPrimaryExpression.eval(Unknown Source)
        at bsh.BSHPrimaryExpression.eval(Unknown Source)
        at bsh.BSHBlock.evalBlock(Unknown Source)
        at bsh.BSHBlock.eval(Unknown Source)
        at bsh.BSHBlock.eval(Unknown Source)
        at bsh.BSHIfStatement.eval(Unknown Source)
        at bsh.Interpreter.eval(Unknown Source)
        at bsh.Interpreter.eval(Unknown Source)
        at bsh.Interpreter.eval(Unknown Source)
        at com.endeca.soleng.eac.toolkit.script.Script.runBeanShellScript(Script.java:165)
        ... 8 more
Caused by: Crawl failed to start: Error retrieving attributes from the config repository: 
Unable to create JSON output for merge request: validation errors:
  ERROR: failure to add '/sites/CRs/attributes/content.repositoryId' to merged output: wrong value for property 'mergeAction' (UPDATE) when no imported entry found to merge with.
  ERROR: failure to add '/sites/CRS/attributes/product.repositoryId' to merged output: wrong value for property 'mergeAction' (UPDATE) when no imported entry found to merge with.
  ERROR: failure to add '/sites/CRS/attributes/store.repositoryId' to merged output: wrong value for property 'mergeAction' (UPDATE) when no imported entry found to merge with.
  ERROR: failure to add '/sites/CRS/attributes/article.repositoryId' to merged output: wrong value for property 'mergeAction' (UPDATE) when no imported entry found to merge with.
  ERROR: failure to add '/sites/CRS/attributes/sku.margin' to merged output: wrong value for property 'mergeAction' (UPDATE) when no imported entry found to merge with.
. See config repository log for more details.

        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

ROOT CAUSE:
When you encounter the above error,every time when indexing is running in place , it will look for the properties or dimensions defined here if it is not available then it will throw the merge error. 

IDENTIFICATION:

Delete the particular property from the DB , so not a single value is found then this error will occur.


SOLUTION:

 Remove the Value from the indexconfig and set the indexing config again, then you are set 
For more information on setting the config see my earlier posts .

Querying for Dynamic Field Names in Endeca.

Hi all, have you wonder how can we query for the multiple fieldnames in endeca? . This is also as simple as querying for the fieldnames as others, but the Dynamic fields should be initiazed properly before sending it to Endeca.

We can see how to initialize and set it in the Query for Endeca below.

How to Set FieldNames in Endeca.

pCartridgeConfig.setFieldNames(fieldNames);

Where pCartridgeConfig is the ResultsListConfig Component. Which holds the Value for the Cartridges Setting and Configurations.


fieldNames is the List that will be used for the Defining the List of Fields.


How to Set Dynaic FieldNames in endeca

List<String> fieldNames = new ArrayList<String>(getFieldNames());
pCartridgeConfig.setFieldNames(fieldNames);

In Case of the Dynamic fieldNames, we have to first initialize it and then set it in the pCartidgeConfig.The Reason being that the Setting the Property Value in the Request or Prototype Component we have to initiaze and set it . As given in the actual ATG Document.

Sunday, 13 November 2016

Registering Cartridges

Any time a cartridge handler has a name that does not match its cartridge type exactly, it must be registered in 
the /atg/endeca/assembler/NucleusAssemblerFactory.handlerMapping property. For example, The CategoryHeaderBanner component is registered in the NucleusAssemblerFactory.handlerMapping property as the handler for cartridges with an ID of HeaderBanner-ATGCategory. The following mappings cartridge type and handler are defined in Commerce Reference Store.


When the cartridge name and the handler name , both matches then you don’t need to register here.


handlerMapping+=\
  ContentSlot-Main=/atg/endeca/assembler/cartridge/handler/ContentSlot,\
  ContentSlot-Header=/atg/endeca/assembler/cartridge/handler/ContentSlot,\
  ContentSlot-Secondary=/atg/endeca/assembler/cartridge/handler/ContentSlot,\
  PageSlot=/atg/endeca/assembler/cartridge/handler/ContentSlot,\
  PromotionalContent-ATGSlot=\
     /atg/endeca/assembler/cartridge/handler/PromotionalContentSlot,\
  PromotionalContent-ATGTargeter=\
     /atg/endeca/assembler/cartridge/handler/PromotionalContentTargeter,\
  ProductSpotlight-ATGSlot=\
     /atg/endeca/assembler/cartridge/handler/ProductSpotlightSlot,\
  ProductSpotlight-ATGTargeter=\
     /atg/endeca/assembler/cartridge/handler/ProductSpotlightTargeter,\
  HeaderBanner-ATGCategory=\
     /atg/endeca/assembler/cartridge/handler/CategoryHeaderBanner,\
  DimensionSearchAutoSuggestItem=\
     /atg/endeca/assembler/cartridge/handler/DimensionSearchResults,\
  ProductSpotlight-ATGCategoryRelatedProducts=\
     /atg/endeca/assembler/cartridge/handler/CategoryRelatedProducts,\
  ProductSpotlight-ATGCategoryRecommendations=\
     /atg/endeca/assembler/cartridge/handler/CategoryRecommendations,\
  HorizontalRecordSpotlight=\
     /atg/endeca/assembler/cartridge/handler/RecordSpotlight,\
  ProductList-ATGCategoryChildren=\
     /atg/endeca/assembler/cartridge/handler/ProductListCategoryChildren

Note: The PriceSlider cartridge handler has the same name as the PriceSlider cartridge, so it does not need to be registered in the handlerMappingproperty.
  

Default Cartridges in Endeca

Cartridge can be defined as the components, that serve specific purpose in the pages or it may be defined as the dynamic content that was loaded in to the Content item.
Cartridges can be defined by both custom and reuse the OOTB one. Oracle commerce guided search provides the  easiest way , so that we can extend the OOTB one  and customize based upon our project need.


What are the Default Methods of the Cartridge handlers?

There may be some default methods available in the handlers , that should be taken in to account while extending it.

public void preprocess

This method is the First method to be called when the scope comes to the Handler from the nucleus assembler factory. It can also be defined as the method where we set the query to be returned from the endeca,  pCartridgeConfig is the handler config which is used for this purpose.Setting up the Rollup key, adding the dynamic filters will also be done in this method.

public <HandlerType> process

This is the Method used for the processing of the results, creating mdex query and firing it and getting the ENEResults, from the results we can able to fetch the Required . We can also manipulate the Results based on the specific condition. This method where the returntype will be return type of the Handler.


Hence the above two method are considered to be the default method to be considered when extending the handlers.

What are the Default Cartridges avalaible in Endeca OOTB

RefinementMenu
HorizontalRecordSpotlight
ResultsList
SearchBox

Other Existing Endeca Cartridges

The DAF.Endeca.Assembler module includes configuration, in the /atg/endeca/assembler/cartridge/handler/ Nucleus folder, for additional existing Oracle Endeca cartridge handlers from the com.endeca.infront.cartridge package. The table below provides a list of these cartridge handlers (note that some of these cartridges handlers are used by Commerce Reference Store and some are not):

Nucleus Component
Cartridge Handler Class
Breadcrumbs
BreadcrumbsHandler
ContentInclude
ContentIncludeHandler
ContentSlot
ContentSlotHandler
DimensionSearchResults
DimensionSearchResultsHandler
NavigationCartridgeHandler
NavigationCartridgeHandler
NavigationContainer
NavigationContainerHandler
RecordBasedNavigationCartridgehandler
RecordBasedNavigationCartridgeHandler
RecordDetail
RecordDetailsHandler
RecordSpotlight
RecordSpotlightHandler
RefinementMenu
RefinementMenuHandler
SearchAdjustments
SearchAdjustmentsHandler


We can also see about the individual handlers in the upcoming tutorials.

Wednesday, 2 November 2016

Getting Started Oracle Commerce Cloud

What is Oracle Commerce cloud:

Oracle Commerce Cloud is a modern, flexible and scalable SaaS solution that emphasizes simplicity, allowing online businesses to quickly launch feature-rich, responsive storefronts across desktop and mobile devices without sacrificing features or brand control.

Descoped:
From  October 1st the ATG and Endeca Commerce Knowledge Zones have been decommissioned. The Oracle ATG and Endeca Commerce specialization and resell programs have been retired as well. Oracle strongly encourage you to subscribe to the Oracle Commerce Cloud Service Knowledge Zone.

BackGround:

Oracle has launched its cloud Platform for the commerce. It may be called as saas commerce platform . The Greater Advantage over the traditional installation packages and this saas is more. We can see whats new , advantages , getting started, How to signup for the trial subscription in the following.

Whats New :
Commerce Cloud is the next evolution of a 20-year,industry-leading commerce platform, reimagined for the modern cloud. The most scalable SaaS platform on the market, Commerce Cloud ignites agility, growth, and cost savings at retail and branded commerce programs.

Commerce Cloud empowers commerce programs to become:

FAST: Move at the speed of business with 24/7 agility.
FLEXIBLE: Customize your experience with intuitive tools in an open platform.
COMPLETE: Deliver amazing omnichannel experiences with everything you need in one place.
RELIABLE: Innovate with rapid upgrades scale with thepeace of mind of the proven Oracle Cloud.

Fast: It allows the Commerce to be delivered to the Client very quickly by its built in Tools .Following are the built in tools. 




Key points about oracle cloud :
  • Deliver mobile experiences without additional work
  • Intuitive drag-and-drop tools and an integrated Preview environment
  • Internationalize quickly with support for over 30 languages and 40 currencies.Quickly launch new brand or seasonal shops.
  • Keep moving with simplified upgrades
  • Empower the business to innovate with limitless front-end customization
  • Commerce Cloud allows brands to control and differentiate their site on their terms. Create any branded look and feel, build custom templates, extend your site, and easily plug in Oracle or third-party applications
  • API-first,standards-based platform API-first architecture, Commerce Cloud features REST Web Services framework, with programming skills like HTML CSS and JavaScript (Bootstrap).
  • Dramatically cut down on integration time and cost


Architecture:




To know more about the oracle cloud



This is a one month free subscription . You can watch out This blog for more interesting topics on the oracle cloud commerce, guided search tutorials. 

Friday, 28 October 2016

UserSegments in Endeca

If you want display content only to the specified set of people, then you need to have the User segment configure in the Xm .

You can add the usersegment by the following ways.











Once you added the usersegment then you should progrmatically add by the following way.

Step:1
create a class implements NavigationStateProcessor

Step:2
Override the method process.
@Override
public void process(final NavigationState pArg0) {

//custom business logic

getUserState().addUserSegments(“men”);

}
In the Component file define the following things

userstate =/atg/endeca/assembler/cartridge/manager/user/LiveUserState

We have to write a custom logic when the Usersegment can be applied on the particular condition.

Register this component in /atg/endeca/assembler/cartridge/manager/NavigationStateBuilder

in the property navigationStateProcessors

Thursday, 27 October 2016

Scheduled indexing in endeca

In Endeca Scheduled Indexing can be made by following the Below steps.

Step :1

Go to ProductCatalogSimpleIndexingAdmin

and Enable the Following property enableScheduledIndexing to true .

Step :2

Set the Calendar event in the Below Property

baselineSchedule=calendar * * 7 * 23 30

where 7 is the Week,23 30 is  it will trigger indexing daily by 23:30

 to trigger indexing for every one hour 

set the Following property to

baselineSchedule=calendar * * * * * 59

It will trigger for every one hour periodically.


Triggering Automatic mail After Indexing


Hi All Many of you where working in Endeca, will enable the Schedule Indexing, automatic Indexing and Waiting to See the Status of the indexing is Successful or not, will though to Trigger a Mail also after the Indexing. This tutorial will give you a Detailed Information how to check the Status of the Indexing and Trigger Mail after that.

I am Writing This Blog Assuming that you are intersted to trigger a mail after every Scheduled Indexing .


Step 1:

Extend the Class SimpleIndexingAdmin

Step 2:

Override the Method performScheduledTask

@Override
public void performScheduledTask(Scheduler pScheduler, ScheduledJob pJob)
  {
  long startTime = System.currentTimeMillis();
  long nextTime = pJob.getSchedule().getNextJobTime(startTime);
  boolean status=Boolean.FALSE;
  try {
  if (pJob == this.mBaselineScheduledJob) {
  status=indexBaseline();
 
  }
  else if (pJob == this.mPartialScheduledJob) {
  status=indexPartial();
  }
  else
  vlogError("Failed to find indexing job corresponding to {0}", new Object[] { pJob });
  }
  catch (IndexingException e) {
  vlogError(e, "Error while executing scheduled job {0}", new Object[] { pJob.getJobName() });

  long currentTime = System.currentTimeMillis();
  boolean enoughTime = nextTime - currentTime - this.mRetryInMs > 2L * (currentTime - startTime);

  if ((this.mRetryInMs > 0L) && (enoughTime)) {
  try {
  Thread.sleep(this.mRetryInMs);
  vlogInfo(e, "Retrying scheduled job {0} after a failure", new Object[] { pJob.getJobName() });

  if (pJob == this.mBaselineScheduledJob){
  status=indexBaseline();
 
  }
  else if (pJob == this.mPartialScheduledJob){
  status=indexPartial();
  }
  }
  catch (IndexingException ee) {
  vlogError(e, "Error while retrying scheduled job {0}", new Object[] { pJob.getJobName() });
  }
  catch (InterruptedException te) {
  vlogError(e, "InterruptedException while while retrying scheduled job {0}", new Object[] { pJob.getJobName() });
  }
  }
  else if ((this.mRetryInMs > 0L) && (!(enoughTime)))
  vlogInfo(e, "Not retrying scheduled job {0} - too little time till the next scheduled run", new Object[] { pJob.getJobName() });
  }
  if (getEmailConfiguration().isEnableEmailServices()) {
  @Override
public void performScheduledTask(Scheduler pScheduler, ScheduledJob pJob)
  {
  long startTime = System.currentTimeMillis();
  long nextTime = pJob.getSchedule().getNextJobTime(startTime);
  boolean status=Boolean.FALSE;
  try {
  if (pJob == this.mBaselineScheduledJob) {
  status=indexBaseline();
 
  }
  else if (pJob == this.mPartialScheduledJob) {
  status=indexPartial();
  }
  else
  vlogError("Failed to find indexing job corresponding to {0}", new Object[] { pJob });
  }
  catch (IndexingException e) {
  vlogError(e, "Error while executing scheduled job {0}", new Object[] { pJob.getJobName() });

  long currentTime = System.currentTimeMillis();
  boolean enoughTime = nextTime - currentTime - this.mRetryInMs > 2L * (currentTime - startTime);

  if ((this.mRetryInMs > 0L) && (enoughTime)) {
  try {
  Thread.sleep(this.mRetryInMs);
  vlogInfo(e, "Retrying scheduled job {0} after a failure", new Object[] { pJob.getJobName() });

  if (pJob == this.mBaselineScheduledJob){
  status=indexBaseline();
 
  }
  else if (pJob == this.mPartialScheduledJob){
  status=indexPartial();
  }
  }
  catch (IndexingException ee) {
  vlogError(e, "Error while retrying scheduled job {0}", new Object[] { pJob.getJobName() });
  }
  catch (InterruptedException te) {
  vlogError(e, "InterruptedException while while retrying scheduled job {0}", new Object[] { pJob.getJobName() });
  }
  }
  else if ((this.mRetryInMs > 0L) && (!(enoughTime)))
  vlogInfo(e, "Not retrying scheduled job {0} - too little time till the next scheduled run", new Object[] { pJob.getJobName() });
  }
  if (getEmailConfiguration().isEnableEmailServices()) {
  getEmailConfiguration().sendAutomatedEmail(status);
}
  }

Where getEmailConfiguration() is a GenericService class that will be acting as a Email Sender.

Step 3:

For this Tutorial am using the Template Email Sender that is coming as part of the ATG for sending the email.

Befor Going into Coding Part let us under stand the Basic Concepts.

TemplateEmailInfoImpl

/atg/scenario/DefaultTemplateEmailInfo  is a component responsible for holding the Content of the Mail, Of class TemplateEmailInfoImpl


 TemplateEmailSender

/atg/userprofiling/email/TemplateEmailSender is a component responsible for the Sending the Emails.
you have to inject the component and call its 

getTemplateEmailSender().sendEmailMessage(pTemplateEmailInfo, emailTo, true, false);

This method will send the email on the Successful trigger of Indexing .


public synchronized void sendAutomatedEmail(boolean pScuccess) {
if (isLoggingDebug()) {
logDebug("BEGIN:::sendEmail Method. ::");
}
if (pSuccess) {
pTemplateEmailInfo.setMessageTo(getEmailMessageTo());
emailTo[0] = pTemplateEmailInfo.getMessageTo();
pTemplateEmailInfo
.setMessageSubject(getSuccessSubjectMsg());
else {
pTemplateEmailInfo.setMessageTo(getEmailMessageTo());
emailTo[0] = pTemplateEmailInfo.getMessageTo();
pTemplateEmailInfo.setMessageSubject(getFailureSubjectMsg());
if (isLoggingDebug()) {
vlogDebug("Email sending Failure {0}",emailTo[0]);
}
}

try {

getTemplateEmailSender().sendEmailMessage(pTemplateEmailInfo, emailTo, true, false);
}catch(TemplateEmailException exp){
if (isLoggingError()) {
vlogError("Error in sending email from sendEndecaBaselineIndexingEmail", exp);
}
}

if (isLoggingDebug()) {
logDebug("END:::sendEmail Method. ::");
}
}

in the DefaultTemplateEmailInfo Define the Following for the Temaplate.It is Mandatory to Define the template Url. This is the JSP where we used to define the Content used to send.



Step 4:

$class=atg.userprofiling.email.TemplateEmailInfoImpl
contentProcessor=/atg/userprofiling/email/HtmlContentProcessor
templateURL=/email/mailtemplate.jsp
mailingName=Service-Email
fillFromTemplate=true

mailtemplate.jsp

<%@ taglib uri="/dspTaglib" prefix="dsp"%>
<%@ taglib uri="/dspELTaglib" prefix="dspel" %>
<%@ taglib uri="c" prefix="c"%>
<%@ taglib uri="fmt" prefix="fmt" %>
<dsp:page>
<div id="main">
Indexing process has completed.Please check the Status for more details.
</div>
</dsp:page>

Once if all is done then the Email will be triggered automatically.