Docker with Oracle on Mac

Sharing my Experience with setting up Docker on Mac. I have chosen this approach with docker is because there is no proper installable available for Oracle 12c on Mac. It seems Official support was dropped from 10g onwards.  I was left with either docker or using a VM which is more cumbersome.

Install and Run Docker for Mac

https://docs.docker.com/docker-for-mac/install/

Get the Docker image for Oracle

Get the docker image from https://hub.docker.com/

https://hub.docker.com/r/sath89/oracle-12c/  (This is an already available docker image with Oracle Standard Edition 12c Release 1 on Ubuntu )

docker pull <imagename>

My-MacBook-Pro:tmp user$ docker pull sath89/oracle-12c

Using default tag: latest
latest: Pulling from sath89/oracle-12c
863735b9fd15: Pull complete 
4fbaa2f403df: Pull complete 
44be94a95984: Pull complete 
a3ed95caeb02: Pull complete 
b8bc6e8767ee: Pull complete 
c918da326197: Pull complete 
448e1619a038: Pull complete 
faadd00cf98e: Pull complete 
48a252b66251: Pull complete 
0be1ba285f23: Pull complete 
Digest: sha256:0d075905ca2243f0c60397e49eaae6edd62afcce43528df77768f346ece7c49b
Status: Downloaded newer image for sath89/oracle-12c:latest

docker images     (to list the images)

My-MacBook-Pro:tmp user$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              1815c82652c0        3 weeks ago         1.84kB
sath89/oracle-12c   latest              7508a4d8d54f        4 weeks ago         5.7GB

docker run

Run with 8080 and 1521 ports opened:

If -d option is present, we won’t see the errors if any, as the process runs in the background

My-MacBook-Pro:tmp user$ docker run -p 8080:8080 -p 1521:1521 sath89/oracle-12c

Database not initialized. Initializing database.
Starting tnslsnr
Copying database files
1% complete
3% complete
11% complete
18% complete
37% complete
Creating and starting Oracle instance
40% complete
45% complete
50% complete
55% complete
56% complete
60% complete
62% complete
Completing Database Creation
66% complete
70% complete
73% complete
85% complete
96% complete
100% complete
Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/xe/xe.log" for further details.
Configuring Apex console
Database initialized. Please visit http://#containeer:8080/em http://#containeer:8080/apex for extra configuration if needed
Starting web management console

PL/SQL procedure successfully completed.

Starting import from '/docker-entrypoint-initdb.d':
found file /docker-entrypoint-initdb.d//docker-entrypoint-initdb.d/*
[IMPORT] /entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
Import finished

Database ready to use. Enjoy! 😉

Connect database with following setting:

hostname: localhost
port: 1521
sid: xe
service name: xe.oracle.docker
username: system
password: oracle

 

Install SQLPLUS (Oracle Instant client) 

Follow the steps mentioned here

Issues while connecting to Oracle from sqlplus

If you want to connect remotely to the oracle in the container, use the following arguments to docker run command

-e ORACLE_ALLOW_REMOTE=true
docker run -p 8080:8080 -p 1521:1521 -e ORACLE_ALLOW_REMOTE=true sath89/oracle-12c

If you get the following error, while connecting to the database,

ERROR:  ORA-21561: OID generation failed

Edit /etc/hosts as per the following answer

https://stackoverflow.com/questions/31338916/sqlplus-remote-connection-giving-ora-21561

With this addition in the /etc/host file and the ORACLE_ALLOW_REMOTE=true setting, you should be able to access the Database externally (from sqlplus or from your application)

Import Data

As impdp utility is not part of Oracle instant client, you cannot use that option external to the docker container. So get into the container

The docker exec command runs a new command in a running container.

docker exec -it <container_name> bash

If container-name is not specified during rum, container id can be used in the above command. To get the container id, use docker ps command.

docker ps -a

Both Impdp and sqlplus are available inside the container. You need to have the data dump file also available inside the container. The easier approach is to mount the dump file location in the local to any location in the container.

To mount location use the -v argument

docker run  -v /work/MyProject/Oracledump:/mnt/dumpdir -p 8080:8080 
-p 1521:1521  -e ORACLE_ALLOW_REMOTE=true sath89/oracle-12c

When I did this first time, I got the following error

The path /work/MyProject/Oracledump
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.

As mentioned, add the location to the shared location

Screen Shot 2018-06-01 at 6.12.41 PM

Finally run the docker instance as follows

docker run  -v /work/MyProject/Oracledump:/mnt/dumpdir -p 8080:8080 
-p 1521:1521  -e ORACLE_ALLOW_REMOTE=true sath89/oracle-12c

 

Create a new image from a container’s changes

It can be useful to commit a container’s file changes or settings into a new image.

docker commit d8ae665b2d01 dockeroracle

If you do a docker images now, you can see the new image also listed

Finally run the new mage

docker run --name=dockeroracle -v /work/My/Oracledump:/mnt/dumpdir -p 9090:8080 -p 1521:1521  -e ORACLE_ALLOW_REMOTE=true dockeroracle
docker exec -it dockeroracle bash
docker start dockeroracle

Install SQLPLUS (Oracle Instant client) on MAC

Free, light-weight, and easily installed Oracle Database tools, libraries and SDKs for building and connecting applications to an Oracle Database instance

http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html

1. Download the desired Instant Client ZIP files. All installations require the Basic or Basic Light package.

2. Unzip the packages into a single directory such as “~/instantclient_12_1”. For example, to use SQL*Plus:

cd ~

unzip instantclient-basic-macos.x64-12.1.0.2.0.zip

unzip instantclient-sqlplus-macos.x64-12.1.0.2.0.zip

                        
3. Create the appropriate libclntsh.dylib link for the version of Instant Client. For example:

cd ~/instantclient_12_1

ln -s libclntsh.dylib.12.1 libclntsh.dylib


5. To be able to run SQL*Plus, update PATH. For example:

export PATH=~/instantclient_12_1:$PATH

                        
6. Run SQL*Plus and connect using your database credentials and connection string:

./sqlplus system/oracle@//localhost:1521/<service_name>

Oracle 12c and the common issues for a beginner

I had to install Oracle 12c on Windows 64bit OS. I chose to create as a Container database in the Step 6 of installation. I gave the Global database name as ‘orcl’ and the pluggable database name as ‘pdborcl’ which are the default ones. At the time of installation I did not bother about the differences between Container database and Pluggable databases.

The next step was to create a user and thats where the problems began as I got the following error

SQL> CREATE USER TESTUSER IDENTIFIED BY TESTUSER;
CREATE USER TESTUSER IDENTIFIED BY TESTUSER
*
ERROR at line 1:
ORA-65096: invalid common user or role name

Following is the details about this error:-

ORA-65096: invalid common user or role name

Cause: An attempt was made to create a common user or role with a name that was not valid for common users or roles. In addition to the usual rules for user and role names, common user and role names must start with C## or c## and consist only of ASCII characters.

Action: Specify a valid common user or role name.

Upon investigation, it is found that, this happens in Oracle 12c when we dont give C## prefix in the name while creating user.
However the proper solution is NOT to just add the prefix or some scripts as follows to set a hidden parameter “_oracle_script”.
alter session set “_ORACLE_SCRIPT”=true;

We should not be creating objects in the container database, the container holds the metadata for the pluggable databases. It is the primary database that contains multiple plugged-in databases.
We should use the pluggable database for the general database operations. These are the databases that are stored within the CDB (container DB). A PDB (pluggable DB) is a portable collection of schemas, schema objects, and nonschema objects that appears to an Oracle Net client as a non-CDB.
Note that all Oracle databases before Oracle Database 12c were non-CDBs.
To create the user in user in a particular container (PDB) then I used the alter session set container first, so that the create is applied within that container.

SQL> alter session set container=PDBORCL;

Session altered.

SQL> create user TESTUSER identified by TESTUSER ;

User created.

This time the user is created succesfully with name TESTUSER in the PDB whose name is pdborcl.

Then I tried to connect to the new user, I got the following Error

Enter user-name: testuser
Enter password:
ERROR:
ORA-01017: invalid username/password; logon denied

To connect to the correct pdb we need to specify the correct service name in the connect string. Enter the user name as ‘testuser@pdborcl’

Enter user-name: testuser@pdborcl
Enter password:
ERROR:
ORA-12154: TNS:could not resolve the connect identifier specified

I had to add the following in the tnsnames.ora file (path is <ORACLE_HOME>/NETWORK/ADMIN)

PDBORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = pdborcl)
)
)

It worked. Just make a note that we need to specify the service name as ‘pdborcl’ in the connection parameters.

 

 

My Experiments with Endeca and ATG 11

I have configured CRS application using the CIM tool on ATG 11 installation integrated with Endeca. It was all working fine after the initial setup a month back.
Today I found that the CRS pages are not getting loaded when I hit localhost:8180/crs (Yes, my production server runs on 8180 port)and this is what I see in the JBOSS console.

“SEVERE [com.endeca.infront.publish.AuthoringContentClient] (http-/127.0.0.1:8180-3) Exception while requesting a node from the server.: java.io.IOException: Unable to connect on workbench publishing port localhost/127.0.0.1:8007. Please check your assembler.properties file matches your webstudio.properties file for this port setting.
at com.endeca.infront.publish.AbstractNioTcpClient.send(AbstractNioTcpClient.java:165) [_DAF.Endeca.Assembler_slib_sendeca__assembler__core-11.1.0.jar:11.1.0]”

First thing I did was to verify if the services ‘Endeca CAS Service’, ‘Endeca HTTP Service’ and ‘Endeca Tools Service’ are started and running.

Then I tried to locate the file webstudio.properties and opened it. It is available at <Endeca_Dir>\ToolsAndFrameworks\11.1.0\server\workspace\conf.
Following is the content from the webstudio.properties that matches the port 8007 in the error.

# The host name of this Workbench instance
com.endeca.webstudio.hostname=localhost

# This must be set to a non-SSL port, even if you are using the
# SSL version of Oracle Commerce Workbench
com.endeca.webstudio.port=8006

# Port opened for promotion of content from Workbench to
# Live Environments.
com.endeca.webstudio.promotion.port=8007

So it seemed like something related to the workbench. Tried accessing the workbench at localhost:8006.

When I hit localhost:8006, it gets redirected to localhost:8006/icfr and the page is continuously refreshed and displays a same message.

“Workbench is starting up (110 of 110 bundles activated, 116 of 145 components ready)…”

Verified that workBenchPort is 8006 in the component /atg/endeca/assembler/AssemblerApplicationConfiguration as well as in <Endeca_Dir>\Apps\CRS\config\script/WorkbenchConfig.xml.
Everything was set correct and then I checked the ‘Tools and Frameworks’ log file located at <Endeca_Dir>\ToolsAndFrameworks\11.1.0\server\workspace\logs\ifcr.log

Following is the error messge from the ifcr.log file.

 *ERROR* [Repository Pinger] org.apache.jackrabbit.core.RepositoryImpl failed to start Repository: internal error: failed to read custom node type definitions stored in /nodetypes/custom_nodetypes.xml javax.jcr.RepositoryException: internal error: failed to read custom node type definitions stored in /nodetypes/custom_nodetypes.xml

Then I tried to locate this file and found that there is one custom_nodetypes.xml at <Endeca_Dir>\ToolsAndFrameworks\11.1.0\server\workspace\state\sling\_ifcr\jackrabbit\repository\nodetypes
This file was corrupt and cannot be opened. I had never touched this file before.

As per the expert advice, I stopped the service ‘Endeca Tools Service’ and deleted this file and restarted the service. Restarted the production jboss server instance and it worked.

CRS is up! Have you ever faced such a situation? No, then you are lucky. Yes, then here are the steps.

What is new in Oracle Commerce 11

What is new in ATG 11? No, that’s not the right question. The right question would be what is there in Oracle Commerce 11.

Yes, that is the first change. Oracle ATG Web Commerce is now baptized as Oracle Commerce.

As per Oracle, version 11 is a strategic move towards unifying the leading commerce, content, and experience technologies on the market. With that, Oracle ATG Web Commerce will be know as Oracle Commerce Platform, ATG CSC will be known as Oracle Commerce Service Center, Endeca Guided Search will be known as Oracle Commerce Guided Search, Endeca Experience Manager will be known as Oracle Commerce Experience Manager and the list goes on.

I was going through the reference document ‘What’s New in Oracle Commerce 11’ and I found a lot of interesting new features. I am sharing my notes on some of the exciting features here.

Changes in Oracle Commerce Platform

  • Single Sign On with Oracle Access Manager Integration
    Single Sign on is available with BCC and Workbench as both have been integrated with OAM (Oracle Access Manager). OAM will be utilized as the point of authentication for access to these tools and there will be links provided in one tool to switch to the other one. Business users can use the same credentials for all the tools.
  • CA Data Import Performance Improvements
    This is really a good news. In one of our ATG implementations, we are importing the catalog data from external system. The import process, scheduled to run twice a day, is taking too much time as it imports the assets in the context of a project in BCC and deploys them.
    With Oracle commerce 11, the APIs and scripts to import data into CA projects are updated so as to improve the performance of the import process. The new scripts issue SQL directly to the underlying database, instead of using the Repository layer. Along with with others changes made in prior versions (direct SQL deployments, improved CMS performance, and improved cache management), this new API changes will definitely help us in bringing down the import and deployment time.

Changes in Oracle Commerce Business Control Center (BCC)

  • Image Thumbnails in the Merchandising UI
    With this feature, business users can now see the thumbnail image of the catalog assets on the left side of each asset name in the left navigation area in the Merchandising UI, which will help them in quickly identifying the catalog items.
  • Site Context in Browse Mode
    In the Merchandising UI Browse mode, site name is displayed above the asset list, which will help the business users in determining which site’s catalog they are working on.
  • Export Prices
    In addition to the existing export feature (where the properties of Catalog items can be exported), Oracle Commerce adds the feature to export prices from BCC into an Excel or CSV file. This will help the users in making the pricing changes quickly as there is an existing import feature too.
  • Promotions Management
    Oracle Commerce 11 release offers a new promotions template – ‘Get Group Discount‘, that enables the user to set a fixed price, fixed discount, or percent off for a group of items
    Maximum Discounts Per Order – Another new feature is that in Oracle Commerce 11, a user can specify the maximum number of times a discount can be applied per order. For example if you have a promotion that gives “25% off on Shirts”, you can limit the number of Shirts in the order that gets this discount.
    Maximum Coupons Per Order – With this feature, users can specify the maximum number of coupons that can be used per order. This can be specified in the Site Administration. In one of our previous ATG implementation, we had this requirement and we had to lot of customization to achieve this. Now its all out-of-the-box.

 Changes in Oracle Commerce Workbench

  • User Segments
    User Segments created within the BCC available to business users in Experience Manager and they now create page experiences that are specific to these user segments.
    Localization to support 22 locales, Automatic Phrasing tool, Relevance Ranking Evaluator tool are also included in Oracle ATG Commerce version 11.
    Other major features are ‘Experience Manager Content Organization‘ that helps in managing the content in hierarchical folder structures and ‘Experience Manager Preview‘ that allows business users to make edits and preview the changes without
    marking their changes as live for production.

Changes in Oracle Commerce Service Center (CSC)

  • ATG Search replaced with Database-Optimized Search
    There comes my most favourite change. ATG Search is replaced with Database-Optimized Search, also known as full text search (FTS), for Order Search and Profile Search in CSC. FTS provides the same or superior performance as ATG Search. In one of our previous implementations, we had lot of issues with ATG Search as some of the orders and profiles were not getting indexed during high traffic period.
    We need not be worried whether ATGOrder and ATGProfile environments are ‘running’ and about other CSC exceptions like RoutingSearchException.  The new FTS is a more lightweight and less complex solution than ATG Search. FTS does not require additional hardware and configuration of specialized search software.
  • Web Services
    Additional Web Services are available out of the box, that expose all of the functionality found in the CSC application. There are lot of such services including the ones for initiating/recieving/canceling a return or an exchange, services for Searching for catalogs, Changing price lists and catalogs, Reviewing, modifying, and approving an order etc.

Changes in Oracle Commerce Reference Store (CRS)

  • Home Page Driven by Experience Manager, New Storefront Branding (Instead of ATg Store and ATG Home, you will see CRS Store and CRS Home) are some of the changes in CRS.
  • Store Locator Pages
    The CRS Web application includes managing store locator pages from both the BCC and Experience Manager. Displaying relevant store location results is a requirement in our ongoing ATG implementation project and we are really benefited from this.
  • CRS provide guidance on how to implement the SEO techniques.
    The latest version of CRS adds a brand landing page managed through Experience Manager., demonstrates the use of Guided Search Auto-Suggest capabilities, use of the Search Adjustments cartridge.

Why wait? Migrate to Atg 11. Oh no, its Oracle Commerce 11.

ATG Multisite – Site Context

How ATG sets a site context in a multisite application?

The first site-related servlet in the servlet pipeline is SiteContextPipelineServlet (/atg/dynamo/servlet/pipeline/SiteContextPipelineServlet/)

SiteContextPilelineServlet  evaluates the request to determine the site’s identity.  This servlet derives the site Id from the request URL and determines whether site information is available for requests. It checks if the corresponding site is enabled or not. If the site is not enabled, it stops processing the request.
If SiteContextPilelineServlet.enabled is set to false, it passes the request to the next servlet in the pipeline. To disable multisite feature set SiteContextPilelineServlet.enabled=false

#/atg/dynamo/servlet/pipeline/SiteContextPipelineServlet   
$class=atg.multisite.SiteContextPipelineServlet        
siteSessionManagerPath=/atg/multisite/SiteSessionManager
siteContextManager=/atg/multisite/SiteContextManager
siteManager=/atg/multisite/SiteManager

ruleFilters=\
        /atg/multisite/RequestParameterRuleFilter,\
        /atg/multisite/URLPatternMatchingRuleFilter
defaultRuleFilter=/atg/multisite/DefaultSiteRuleFilter
 
insertAfterServlet=/atg/dynamo/servlet/pipeline/DynamoHandler

The SiteContextPipelineServlet has a ruleFilters property which is an array of SiteContextRuleFilter components. Each filter is queried one after the other until a site is determined. By default, RequestParameterRuleFilter and URLPatternMatchingRuleFilter are the filter components configured in the servlet. SiteContextRuleFilter components are based on classes that implement atg.multisite.SiteContextRuleFilter. Developers can add their own filters to this property to customize how sites are assigned to requests.

RequestParameterRuleFilter sets the site named in ‘pushSite‘ request parameter. This parameter name is configured in the property RequestParameterRuleFilter.pushSiteParamName. This filter is useful for testing the sites during development phase. This must be disabled in Production environment.

URLPatternMatchingRuleFilter determines the site Id from the request URL, based on certain rules. It first checks the URLPatternMatchingRuleFilter.URLs map property to see if the request URL matches any of the URLs in this map property. The URLs property may be manually populated by the developers for testing purpose. If no match is found, the filter asks SiteURLManager for a match. SiteURLManager builds cached map of URLs from the Site Repository. SiteURLManager.getSiteIdForURL() will return the site ID.

If none of the ruleFilters returns a siteID, then the rule filter defined by the property SiteContextPipelineServlet.defaultRuleFilter, will be executed.
DefaultSiteContextRuleFilter sets the site to the site configured in the property DefaultSiteContextRuleFilter.defaultSiteId. By default, defaultSiteId is null.

Based on the site ID returned by the rule filters, SiteContextPipelineServlet selects the site context. After the site context has been selected, the ProfilePropertyServlet uses it to set site-specific properties on the current profile.

Possible Issues and solutions.

Turn on loggingDebug on SiteContextPipelineServlet. You may see following debug messages:-

  • “Rule filters returned no site Id for current request:”
    This happens when multisite is enabled, but there are no sites defined in the site repository.
  • “Site <site id> is not active. Processing stopped for this request: ”
    This happens when the request URL matches any of the site’s production URL and that site is not enabled. You may see a blank page in the browser. To solve this, either enable the site (enabled=true) or change the Site Base URL (productionURL) via BCC and deploy the project.

To display the current site in the page , include the following code in the JSP.
<dsp:valueof  bean=”/atg/multisite/Site.id”/>

ATG Servlet Pipeline

Ever wondered how the request goes through the ATG request handling pipeline?

In this section, you will see how a request is handled in the ATG application starting with a filter configured in the web.xml

PageFilter is mapped to handle JSP requests.  This is configured in the web.xml in your application as shown below.

<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>

PageFilter will start the DAF servlet pipeline by calling DynamoHandler, which is the first servlet in the pipeline.

Each servlet in this chain, performs its own specific function on the request and after that it pass the request to another servlet based on the nextServlet configuration. This chain of servlets is called a request-handling pipeline.

( For handling JSPs, specify the PageFilter filter. For JHTML pages, specify the DynamoProxyServlet servlet. PageFilter calls DynamoHandler to start the DAF servlet pipeline for JSP requests.
DynamoProxyServlet calls DynamoHandler to start the DAS servlet pipeline for JHTML requests. We are covering only DAF servlet pipeline here. )

OOTB pipeline servlets

Though there are a lot of servlets in the pipeline, I am explaining the role of some of the major OOTB servlets.

DynamoHandler
This pipeline servlet takes in an HttpServletRequest/Response pair and passes on a DynamoHttpServletRequest/Response pair to the subsequent servlets in the request-handling pipeline. This must be the first servlet in the pipeline.

SiteContextPilelineServlet
This servlet evaluates the request to determine the site’s identity. SiteContextPilelineServlet derives the site Id from the request URL and determines whether site information is available for requests. It checks if the corresponding site is enabled or not. If the site is not enabled, it stops processing the request.
To disable multisite feature set SiteContextPilelineServlet.enabled=false

DynamoServlet
Sets various properties of DynamoHttpServletRequest

ProtocolSwitchServlet
ProtocolSwitchServlet performs switching between a secure sever and a non-secure server based on the configurations in the pipeline component. The values for the properties hostName, secureHostName, httpPort, httpsPort etc need to be specified in this component. ProtocolSwitchServlet has list property named secureList where you can enter the list of secure URLs. The servlet matches the incoming request with these URLs and swicthes to secure server if a match is found. Similarly it has an ignoreList property also, which can be used for specifying the URLS that need to be ignored while making a decision to switch.

ProfileRequestServlet
ProfileRequestServlet creates an instance of the atg/userprofiling/Profile component, If a Profile doesnot exist for the current session. While creatiing the Profile, it creates a transient RepositoryItem and sets to the Profile component’s dataSource property. It also creates a cookie containing the Profile ID of the current guest user.
To persist anonymous profiles in DB set ProfileRequestServlet.persistentAnonymousProfiles=true.

ProfilePropertyServlet
ProfilePropertyServlet sets properties on the profile. This is done based on the property setter components added in the property ProfilePropertyServlet.profilePropertySetters. Out of the box, three property setters are configured which are /atg/userprofiling/SiteProfilePropertySetter, /atg/userprofiling/CatalogProfilePropertySetter and atg/userprofiling/PriceListProfilePropertySetter. SiteProfilePropertySetter update profile properties with the values from the current site. CatalogProfilePropertySetter sets the catalog property, while PriceListProfilePropertySetter sets the priceList. More details on this available here.

AccessControlServlet
This servlet checks the reqiestUri to see if it matches any of the restricted URLs identified in its accessController map. If a restricted request URL is requested, it checks if the current Profile is permitted to view the page based on the the AccessController rules. If access is denied, then it redirects the user to the URL in the deniedAccessURL property of the corresponding AccessController.

DAFDropletEventServlet
This servlet comes into picture when a form is submitted. This DAFDropletEventServlet is responsible for calling the setX/handleX methods of a bean/formhandler when a form is submitted.

TailPipelineServlet
This is the last servlet in the pipeline is TailPipelineServlet. It is responsible for calling FilterChain.doFilter(), which invokes the next filter defined in web.xml.

With ATG-Endeca Integration, one of the options for querying the Oracle Endeca Assembler and MDEX engine is invoking the Assembler via a servlet as part of Oracle ATG’s request handling pipeline. This is the AssemblerPipelineServlet.

AssemblerPipelineServlet
It takes the URL and based on the uRL it decides whether it can handle the request or it has to pass it on. By default, the AssemblerPipelineServlet component passes all known MIME types and only executes for a null MIME type. If there is no extension, AssemblerPipelineServlet calls the Endeca Assembler. Endeca Assmebler will now talk to the Experiemce Manager and Experiemce Manager will assemble the contents based on the rules.
To disable this servlet set AssemblerPipelineServlet.enabled=false

Modify the Request handling pipeline

Before using, you may fine tune the OOTB behaviour of ATG DAF Request handling pipeline.

  • Do not make unnecessary modification to the order of the pipeline, escpecially on the position of DynamoHandler and TailPipelineServlet.
  • Disable unnecessary servlets.
  • Add new servlets if required.

Eg – if you want to identify the requests to your application from Search engines and perform any specific operation like adding user to a particular segment etc.
– If you want to get the users location based in incoming IP address.
– If you want to perform some logic based on specifich type of request URLs

Inserting Servlets in the Pipeline

You can modify the servlet pipeline by changing the nextServlet or related properties of existing components, and by creating Nucleus components that are instances of classes extended from PipelineableServlet
InsertableServlet implements PipelineableServlet. 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.

To add an InsertableServlet to the servlet pipeline:

  • Create a new global scoped component and specify the new servlet class.
  • The servlet class should extend InsertableServletImpl class
  • Set the insertAfterServlet property of your servlet to point to the path of the pipeline servlet you want your servlet to follow.
  • Add the servlet to the initialServices property of the component /atg/dynamo/servlet/Initial, so that it gets started when the nucleus starts.

Do you think, now you understand the role of ATG servlet pipleine and the request flow?

ATG Assigning and Navigating Catalog in Multisite

Assigning a catalog to user.
With earlier versions of ATG, there was a practice of depending on scenario to assign default catalog to a user (anonymous user).

With the newer versions where ATG multisite is enabled, this need to be done based on the Site Context.

In Site Administration, you can specify the default catalog for each site. For every request, ATG sets the profile’s catalog property to the current site’s default catalog.
In this way, the customer will always see a catalog that is correct for the current site.

How this works

ProfilePropertyServlet is a request pipeline servlet. It has a property profilePropertySetters as shown below:-

#/atg/dynamo/servlet/dafpipeline/ProfilePropertyServlet       

profilePropertySetters+=/atg/userprofiling/SiteProfilePropertySetter,\
                        /atg/userprofiling/CatalogProfilePropertySetter,\
                        /atg/userprofiling/PriceListProfilePropertySetter

The CatalogProfilePropertySetter, which calls the determineCatalog() method of the CatalogTools component is responsible for setting the profile’s catalog property.

This method uses the boolean property ‘useProfile’ in the component /atg/commerce/util/ContextValueRetriever component to determine whether the site’s catalog to be used or not.
– If the useProfile property is set to true, in case of a logged in user, the catalog assigned to the profile will be used and not the one from the site.
– If the useProfile property is set to false and if there is current site, the defaultCatalog from site configuration of he current site is used.
– If the useProfile property is set to false and if there is no current site, the defaultCatalog from CatalogTools component is used.

ContextValueRetriever.useProfile is set to false by default, so that it takes the catalog from site.

What you need to do

– Set the defaultCatalog property for all the siteConfiguration item. This need to be done via BCC.
– Set the deaultCatalog in the CatalogTools component, only if you need a catalog when there is no site selected.

Catalog Navigation

Profile.catalog will return the catalog from the site configuration. This is the default OOTB behaviour. This is because the useProfile property in /atg/commerce/util/ContextValueRetriever component is set to false by default.

Root categories are those that appear in the allRootCategories property of the user’s catalog. When a category (new or existing) is added to the catalog as a child, it gets automatically added to the rootCategories property of the catalog.

<dsp:droplet name="/atg/dynamo/droplet/ForEach">
  <dsp:param bean="/atg/userprofiling/Profile.catalog.allRootCategories" name="array"/>
  <dsp:oparam name="output">
     // Code to display the top level categories.
  </dsp:oparam>
</dsp:droplet>

As per ATG CRS best practices, it is good to have a non-navigable root category (for example name it as ‘Non Navigable Products’) and another category namely ‘Commerce Root’ for the navigable items.

CRS has extended catalog item to store the root navigation category. The new property name is rootNavigationCategory. In this case, the following line of code can be used to get the top level categories.

<dsp:getvalueof  var="topLevelCategories"  bean="Profile.catalog.rootNavigationCategory.childCategories" />

Note that it is the responsibility of the developer/business user to specify the root navigation category.

For more information on this, refer the code in CRS at store.war/navigation/gadgets/catalog.jsp

.
Possible Issues

When you use CategoryLookup droplet to get the childCategories or other details of a parent category, you may get an error saying “this item is not part of current site”.
This happens because the Sites property (name = siteIds) of the Catalog is not updated with the correct list of sites that uses the catalog. To have this relationship correctly set, follow the practices below:-
– Make sure that the catalog is added in a catalog folder
– Make sure that the catalog is assigned to the site via BCC and not using ACC. This is because the Catalog update service which builds the relationships are run after the deployment.
– Manually Run catalog update service in BCCs dyn/admin. A project will be created in BCC with name starting with “CatalogUpdate” and deploy it to Production.

ATG Best Practices

Why do we need Best Practices? These are the methods or techniques that contribute to the success. Here are some of the ATG Best Practices:-

Form Handler   When extending A FormHandler or writing a custom Formhandler, do not the write the business logic in the handle method or any other method in the Formhandler. Instead write the business logic in the corresponding Manager class. That means whenever you create a custom FormHandler, create a manager component also.
The advantage of having methods (be it validation methods or complex business logic handling methods) in a Manager component is that they can be re-used as the Manager component always will be of global scope.
FormHandler scope can be request or session.
A FormHandler should refer only components that have same or higher scope.
Do not invoke one handle method from another handle method.

Repository –
– Define cache size for all the items in a repository. Cache settings should be defined in a separate cache config layer.
– Define column-name attribute explicitly, even when the column name is identical to property’s name. This is a per CA best practice.
– Set required attribute to true for properties linked to columns that are non-nullable. This is a per CA best practice.
– Set the display-name or display-name-resource property.

Database – Never alter OOTB tables. Whenever an OOTB repository item is extended to add a new property, define the column in a new auxiliary table, instead of altering OOTB tables.

Order Modification – Follow the best practices for updating Order. This is to prevent Concurrent update exceptions, Invalid version exception etc.
– Obtain local Lock on profile ID.
– Begin transaction
– Synchronize on Order
– Perform all modifications to order
– Call OrderManager.updateOrder
– End synchronization
– End Transaction
– Release local lock on proifle ID
Pricing – Keep the pricing at the SKU level for greater flexibility. Use PriceLists whenver required. Advantage of using pricelists discussed here.

Implementing Pricing Method – In case of creating custom promotion type and adding a calculator, follow the steps mentioned below
– get matching object or qualifying items
– get necessary info out of DiscountStructure
– calculate pricing adjustment
– set the new price in PriceInfo Object
– create new PricingAdjustment object and add it to priceInfo’s adjustments property

Catalog Setup – Create a non-navigable root category (for example name it as ‘Non Navigable Products’). This category can be used for adding the non-navigable items like gift wrap sku, skus that are part of bundle links, config options etc. The advantage is that if the business user doesn’t want a product to be non-navigable, the can simply drag and drop it to this category. With ATG Endeca Integration, this category need not be sent to Endeca for indexing. More details on Assigning a Catalog to user is available here.

MultiSite – The siteConfiguration item in the site repository should not be sub-typed and none of the OOTB properties should be removed. This is to avoid unexpected behaviour in ATG.
A possible solution to this is to use ‘siteTemplates’ to present different site ‘categories’. Note that siteConfigiration can be extended to add properties.

Servlet Pipleine –
– Disable unnecessary servlets in the pipeline.
– Add new servlets if required.
– Do not make unnecessary modification to the order of the pipeline, especially on the position of DynamoHandler and TailPipelineServlet. More details on Servlet pipeline is available here.

This section will be updated as and when I come across new best practices.

Welcome to atg commerce lessons

Welcome to the world of ATG commerce lessons

Today I was having a discussion with my colleagues on various aspects of ATG framework.
We shared lot of thoughts starting from the design patterns used in ATG to the cache tuning in ATG repository to the features available in BCC.
I couldn’t find one place where I get all the information about ATG development.
I am starting this as a one stop shop for sharing all the learnings and experiences with Oracle Commerce (ATG).