Wednesday, December 30, 2015

PropertyDescriptor to Compare and return value based comparison (ATG Oracle Commerce)


Find below Property descriptor that will compare 2 values that will be set as attribute tags, along with the comparison to do, it will
return the boolean with the result of the operation:

It works as follows, it requires  the followinng attirbutes:

  • compareOperator, it can be any logical operator such as lt,gt,eq, based on el notation.
  • leftSideType it can be a number type or a property type
  • leftSideValue it can be the value in number, or the property that contains the value
  • rightSideType it can be a number type or a property type
  • rightSideValue it can ve the value in number, or the property that contains the value


Here are 2 examples:

And here is the Java Class that makes this possible

Wednesday, December 16, 2015

PropertyDescriptor to Concatenate properties (ATG Oracle Commerce)

We have faced with a scenario where a property needed to contain it's value and also have concatenated other value.
There are not property descriptors to Concatenate Items, So I have created one, that works as follows:

It will concatenate n values that will be set as attribute tags as property, and will separate them by parameter called
separator.

An example for a property using this PropertyDescriptor is described below:
this means that it will use the value from the current property.

The class to make this happen is this:

I hope you find this useful for your project.

How to Make coupon codes be case Insensitive (ATG Oracle Commerce)


As you might know ATG OOTB supports the creation of coupons and batch coupons, and you can redeem them or check are valids with /atg/commerce/claimable/ClaimableManager
By default Coupon Codes are Case Sensitive, menaing FREESHIP is different that freeShip.

But this can be changed with a Flag @ /atg/commerce/claimable/ClaimableTools

# This will make sure that coupons can be entered with different cases
caseInsensitiveClaimableIds=true



This will make the code check for couponCode without considering the case and is just a change on a flag.

You can find this on the documentation at http://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGCommProgGuide/html/s0704theclaimabletoolscomponent01.html

Monday, November 30, 2015

Make Thumbnails on BCC use the image you want (ATG Oracle Commerce)

ATG 11 OOTB uses thumbnails for the skus, and products, this is done with a view Mapping into ViewMappingRepository.



Is just matter of know which property you want to use as thumbnail and set it, on our project we decided to do similar as follows:

These 2 attribute are AmAvPrdtPrImagePropName and AmAvSkuPrImagePropName for product and sku respectively

Product will use the thumbnail of the first childSku

The Sku will use the it's own thumbnail Image.
OOTB is kind of different for product, it uses it's own thumbnailImage
This can be found at DCS-UI/install/data/viewmapping.xml

All these xml needs to be executed at /atg/web/viewmapping/ViewMappingRepository which is a Repository that CA/BCC instance have.

PropertyDescriptor That set values on other properties (ATG Oracle Commerce)

As you already know PropertyDescriptors are great tool to make repository properties return or set a value based on your code logic instead of getting/setting this directly into the DB.

There are some good posts about PropertyDescriptors out there, like these:


And also Oracle Documentation is fine:



Recently I had a requirement that required change some properties based on the value of other property.
Then the first thing that came into my mind was: "a PropertyDescriptor could do this"

Since Property Descriptor methods have the RepositoryItemImpl and the value as parameter for both methods setPropertyValue and getPropertyValue
So is as easy as simply get the property you want to set, and it is great that it works for other items if those are related, an example of this are childSkus.

Below is an example of how to set skuProperties based on product Properties, meaning that the this PropertyDescriptor will Set some properties on childSkus based product's value and some configuration.


The code above can be used when Setting a value on a BCC project, and it will affect all the assets that were involved into the change, this is due we are working with CurrentVersionItem.
And also if a property happens to be null this can be catch by

skuValue instanceof RepositoryItemImpl.NullObject

Share contextRoot on multi Site environment (ATG Oracle Commerce 11.x)

ATG does support multisite out of the box, you need to set up your sites to make this happen, as you can see on CRS.



Once you have your sites set up there is an important configuration that needs to happen in order your application understand that the sites are gonna share contextRoot as it happens on a multi-site environment.
That can be set in a single component /atg/dynamo/service/VirtualContextRootService/, just enable this component and the multi site will works sharing the same contextRoot.
This is configured OOTB at CRS.

This can be found at Oracle Documentation at http://docs.oracle.com/cd/E52191_03/Platform.11-1/ATGPlatformProgGuide/html/s0906configuringvirtualcontextrootreq01.html

Similar for previous versions are documented at http://docs.oracle.com/cd/E36434_01/Platform.10-1-2/ATGMultisiteAdminGuide/html/s1303contextroots01.html 

Special Thanks to Adolgo who found this :)

Wednesday, October 21, 2015

Get DDL for any object with a query with Oracle

Have you ever wonder how the DB Client tools such as SQL Developer, TOAD and so on..
get the DDL to for you?


Well, I wonder that as well, and it is easy to get, that is META_DATA of the database right?
You can access any object DDL with a query:

Here are just some examples of this:

And this is how looks like the result set.
Important Note:

  • Any object can be queried, index, package, procedures, triggers and so on..
  • Object name is case sensitive, so you should be able to find it only if you use the same casing, otherwise will return an error as follows, my_function does not exist, what exist is MY_FUNCTION:


Friday, October 16, 2015

PMDL templates does not consider salePrice when applying rule (ATG Oracle Commerce)

One of our clients had an issue about a BOGO promotion that was giving  FREE the item with higher price, even when they configured it to use the "Lowest Item First" on the "Apply Discount To:" property on the Condition and Offer section, as the follow screen shot.


After some research we found that it was OOTB issue.
I have replicated this on CRS with these two jeans and the promotion from screenshot above.

As you Can see the item "Distressed Jeans" has a lower sale price, but a higher list price than "Straight Leg Jeans".
This translate into a pmdl rule evaluation for the Promotion above give the discount to the item with lower price, but as you see the next screenshot you will notice is applying the rule with the one with higher price.


In the cart the item with higher price was the one getting the promotion, this happened due the PMDL rule was saying that it was going to use listPrice when doing the sort for the evaluation.

In order to Fix this issue:
The pmdl rule that does the validation needs to consider salePrice instead.
This can be done for existing promotions with a Content Administration Project as follows:
Change that to use salePrice will solve the issue and it will consider salePrice to do apply the rule.

However this is considering that the items that qualify for the promotion needs to have salePrice, otherwise this will not work, since is relaying on something that is not defined.

Also you can change the template that creates this, those templates are located inside of $ATG_ROOT/DCS/config/config.jar at /atg/registry/data/promotiontemplates

And is as easy as edit that xml and replace the config on your application.


Note: Oracle is working on a permanent solution for this, but since needs to consider both, sale and list prices and the pmdl rule just allows you to use one of them.





Wednesday, September 30, 2015

Auto Login with Cookies aka warm users experience / soft login (ATG Oracle Commerce)

ATG does provide auto login with cookies OOTB, is just matter of configure this:
This will create 2 cookies to make this possible DYN_USER_ID and DYN_USER_CONFIRM. The DYN_USER_CONFIRM cookie is a hash of the DYN_USER_ID cookie.
There are few steps in order to make this happen:

@ /atg/userprofiling/CookieManager.propertie configure sendProfileCookies and profileCookieMaxAge

 
#Set to true to send a profile cookie including the user ID.
sendProfileCookies=true
# Set to be 30 days
profileCookieMaxAge=2592000
@ /atg/userprofiling/ProfileRequest.propertie configure extractProfileFromCookieParameter property

 
# 
# /atg/userprofiling/ProfileRequest
# Profile information associated with a request
# It will tell the application that the profile can login from cookieParameter to allow warm user or soft-login enabled
#
extractProfileFromCookieParameter=true
This is configured at https://docs.oracle.com/cd/E52191_02/Platform.11-1/ATGPersProgGuide/html/s0502trackingregisteredusers01.html
and all the configuration for those cookies https://docs.oracle.com/cd/E52191_02/Platform.11-1/ATGPersProgGuide/html/s0502profilecookieconfiguration01.html

Important Note: If you did are not using CRS on your project do the following update to make thre rest of the users to be able to autologin with cookies


 
UPDATE DPS_USER SET AUTO_LOGIN = 1 WHERE AUTO_LOGIN = 0;
COMMIT;
@ /atg/userprofiling/userProfile.xml configure autoLogin property to have default value as true

 
   
    ....
         
    ....
    
With this configuration in place, customers will be logged in with Security level 2 (Auto-login by cookies) as shows the following table:

This is documented at https://docs.oracle.com/cd/E52191_02/Platform.11-1/ATGPersProgGuide/html/s0502securitystatus01.html
In order to configure the access that your user logged with cookies will have you can configure AccessControlServlet due, warm users can do just a few things on the site, checkout is somehting you do not want them to do.

Thursday, September 17, 2015

Use a Database Migration Tool (Flyway) for your Evolving project

When you are doing development on application that has a database schema that will be changing over time you need to have a good way to manage those changes, and if you are working with team that needs to have those changes to avoid issues during their development you might want to think about a Data base migration Tool.

Before a Database migration Tool we used to send email to a distribution list of developers and DBAs to make sure the new DDL or database DML were executed to support new code.

I'll focus on Flyway which is the one I have used for my latest project.


Flyway is an open-source database migration tool. It strongly favors simplicity and convention over configuration.

I'll try to summarize flyway workflow for migration:
It needs to have a directory where all the .sql files that will be executed on a database
It will need the driver for your database
The schema and the credentials for the user to run the .sql files
Having the above when, a migration can be done, here is an example of what migration is with flyway:


As you can see there is a database table called Schema_version

That table is created by flyway to save version of each migration, and a version is the representation of the .sql scripts that have been executed since the baseline, here is how this table looks like
Once you have all your .sql files ready for a migration you can run migration on flyway and everything will be executed for you without.
Here is how the file system looks like:


Now that a migration process is understood, the next step is to store all the.sql into a source code repository, there is a great article about this at http://www.jeremyjarrell.com/using-flyway-db-with-distributed-version-control/

There are more tasks rather than migration such as (clean,info,validate,baseline,repair).

Flyway comes with several EXECUTION MODES

  • Command-line
  • API
  • Maven
  • Gradle
  • Ant
  • SBT


I'll used ANT for my project, but feel free to use the Execution mode that fits better on your project

With Ant is as easy as configure a build.xml for your database migration, here is an example of how easy is to do it.


 

    
        
            
                
                
            
        
        
            
        
        
        
        
        
        
        
        
    
   

Once this is done, it is as easy as just Run the ant Task and the Migration will happen for the files over your configured location.

This is a great tool, spend like 4 hours to do a POC, and you will realized that it was worth.

Friday, September 11, 2015

Register RMI Service on RmiServer and how to consume it (ATG Oracle Commerce)

ATG does have an RMI server running when the application starts, that can be seen at the logs with a line similar to this:

INFO  [nucleusNamespace.atg.dynamo.server.RmiServer] (ServerService Thread Pool -- 55) Service /atg/dynamo/server/RmiServer listening at rmi://localhost:8860/

And this rmi server is used for BCC on the agents.


Let's see how we can create our on RMI Service and register this on ATG RmiServer, this example Service will invalidate cache on a given Repository.

Create base Interface for our RmiService.
First of All you will need a Interface that that extends java.rmi.Remote
This will have the methods you want to expose to be executed Remote.

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RepositoryCacheInvalidation extends Remote {
    
    /** 
     * Method signature for invalidateCache that will receive repositoryPath to invalidate.
     * @param repositoryPath to invalidate.
     * @throws RemoteException if happens.
     */
    void invalidateCache(String repositoryPath) throws RemoteException;
    
}


Create Class that Will be our RmiService
Once this is done, lets implement the Interface, our class will Implement our interface, and will extend atg.nucleus.GenericRMIService

import java.rmi.RemoteException;

import atg.adapter.gsa.GSARepository;
import atg.core.util.StringUtils;
import atg.nucleus.GenericRMIService;
import atg.nucleus.spring.NucleusResolverUtil;
import atg.repository.ItemDescriptorImpl;
import atg.repository.Repository;
import atg.repository.RepositoryException;

public class RepositoryCacheInvalidationImpl extends GenericRMIService implements RepositoryCacheInvalidation {

    /** Constant to hold serialVersionUID. */
    private static final long serialVersionUID = 3719003929540922692L;

    /**
     * Default constructor that throws RemoteException.
     * 
     * @throws RemoteException if happens.
     */
    public RepositoryCacheInvalidationImpl() throws RemoteException {
        super();
    }

    /** 
     * Method signature for invalidateCache that will receive repositoryPath to invalidate.
     * @param repositoryPath to invalidate.
     * @throws RemoteException if happens.
     */
    @Override
    public void invalidateCache(final String repositoryPath) throws RemoteException {
        vlogDebug("Start RepositoryCacheInvalidationImpl.invalidateCache({0})", repositoryPath);
        if (!StringUtils.isBlank(repositoryPath)) {
            Object obj = NucleusResolverUtil.resolveName(repositoryPath);
            if (obj != null && obj instanceof Repository) {
                ((GSARepository) obj).invalidateCaches();
            }
        }
        vlogDebug("End RepositoryCacheInvalidationImpl.invalidateCache({0})", repositoryPath);
    }
    
}


Register the RmiSerivce as Dynamo Component 
Since this class will be a component we need to create the .properties for it, to be registered on dynamo server.

##
# /com/example/repository/rmi/RepositoryCacheInvalidation/
# RMIService component that will be used to invalidate cache.
##
$class=com.example.repository.rmi.RepositoryCacheInvalidationImpl


Register RepositoryCacheInvalidation on RmiServer
Now we need to make sure our Server register this Service, this needs to be done at /atg/dynamo/server/RmiServer
Just add the new RmiService at exportedServices as Follows:

exportedServices+=/com/example/repository/rmi/RepositoryCacheInvalidation as


This will make your RmiSerivce be available on the RmiServer, if everything is done correctly you will see it as follows:



Create a client for the RmiService
The new RmiService is created and registered, let's call it, you can create a GeniercService class to call this, here is how the method should look like to call our new RmiService

    /**
     * Method that will invalidate the cache for the repository that is sent as parameter.
     * @param repositoryPath to invalidate.
     * @throws MalformedURLException if wrong rmi servers are sent.
     * @throws RemoteException if there is an error connecting to rmi server.
     * @throws NotBoundException if Naming.lookup method fails fails.
     */
    public void invalidateCaches(final String repositoryPath)
            throws MalformedURLException, RemoteException, NotBoundException {
        if (!StringUtils.isBlank(repositoryPath)) {
            String url = "rmi://localhost:8860/com/example/repository/rmi/RepositoryCacheInvalidation";
                if (null != Naming.lookup(url)) {
                    vlogDebug("calling RMI service for cache invalidation {0}", url);
                    RepositoryCacheInvalidation repositoryCacheInvalidation = 
                            (RepositoryCacheInvalidation) Naming.lookup(url);
                    repositoryCacheInvalidation.invalidateCache(repositoryPath);
                }
        }
    }


And that's it, everything is documented at http://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPlatformProgGuide/html/s1003writinganrmiservice01.html

Thursday, September 3, 2015

How to set up Oracle Commerce Business Intelligence on ATG 11.1 (ATG Oracle Commerce)

This is already documented for ATG 11.1 and is at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0101introduction01.html however I did it and had some issues with it, so I'll try to summarize it as follows:

Here is a diagram that shows an overview of the complete end to end process on Oracle Commerce Business Intelligence.
All the Instances can have Loggers to log transactions such as Order Submission, User Registration, Site Visits and so on, not that CSC and BCC can have loggers as well, and this is due the fact that you can track agents activities and Deployments data as well.


You can do this with cim, the steps to do this are at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0202installingwithcim01.html, there is another option that is create by yourself the DB schema and run the DDLS thse are located at ${ATG_INST_PATH}/ARF/DW/base/sql/db_components/oracle/ the steps to to this are at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0302creatingthedatawarehouseschema01.html 


In this post we will focus just on Store Instance, but the same applies for CSC and BCC.
Store instance needs to include the following modules: 
  • DCS.DW 
  • DCS.CustomCatalogs
  • ARF.base
The list of modules to include per instance is at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0303applicationearfiles01.html

Then DWDataCollectionConfig needs to be enabled and set the location where the logfiles that the loggers will create as follows:



Documentation for this is here http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0303enablingserverlogging01.html


Oracle says loader servers must run on dedicated servers.
In order to make this happen the logger location for all the servers needs to be a Shared network location, so the Loader server can get the data from there.
On the loader server you need to specify the same for component DWDataCollectionConfig
And all the Datasources need to be available for DWLoader, the details can be found at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0305configuringthedatawarehouseloade01.html 

This is all needed from Oracle Commerce point of view, having all the above stes configured DW schema will be populated with the data into the logs because the loggers will log every hour and the loader server will run once at day to get the data from logs and save it into DW database.

In case you want to do Load from the logs you just need to go into the loader component and do it by yourself all the loaders are at /dyn/admin/nucleus/atg/reporting/datawarehouse/loaders/ on your Loader Server.
Here is an example of how a Loader component looks like:



Files can be added manually to the queue and those can be loaded by running method loadAllAvailable, it will make the loader save your data into DW Database.
This is all you need to to in Oracle Commerce to load your information into DW database that will be used by Oracle Business Intelligence.

Installing Oracle Business Intelligence is a separate topic, however the documentation to do it is at http://www.oracle.com/technetwork/middleware/bi-enterprise-edition/documentation/bi-ee-087853.html  

Once Oracle Business Intelligence is installed we need to Prepare the datamodel, this is docummented at http://docs.oracle.com/cd/E52191_03/ACI.11-1/ATGBusIntellInstallGuide/html/s0403deployingthedatamodelandanalysis01.html 

This will make OBI have Some default dashboards generated by ATG



Create a Dashboard and run it to get the data created on your Store application


I hope this help you to understand Oracle Commerce Business Intelligence.

Monday, August 31, 2015

Grant SYSDBA role to SYSTEM user on Oracle

SYSTEM user by default is not a dba, and this is an issue when you are trying to do Installations with  Oracle tools such as RCU.

Being the DBA just connect with sqlplus as sysdba

/home/omurillo$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Mon Aug 31 09:39:23 2015

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL> grant sysdba to system;
Grant succeeded.

And you are done.

Thursday, August 27, 2015

Make your web app look like an Stand Alone application on Mobile devices (Android, iOS)

Mobile devices have the availability to add a web page to home screen, and your web application can specify how to behave once this happens.

There is a simple configuration for Android and iOS that will make your app look as a Mobile Application.

For Android devices.
You need a manifest.json file that will contain the details of your application, here is an example:

{
  "name": "A|G Fitness",
  "short_name": "A|G",
  "icons": [{
        "src": "images/touch/icon-128x128.png",
        "sizes": "128x128",
        "type": "image/png"
      }, {
        "src": "images/touch/apple-touch-icon.png",
        "sizes": "152x152",
        "type": "image/png"
      }, {
        "src": "images/touch/ms-touch-icon-144x144-precomposed.png",
        "sizes": "144x144",
        "type": "image/png"
      }, {
        "src": "images/touch/chrome-touch-icon-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
      }],
  "start_url": "/#!/",
  "display": "standalone"
}



Then on your web page you need to add some meta details inside your head as follows:
   <%-- Meta details to set add to home on Android Mobile devices as stand alone application --%>
   <meta name="theme-color" content="#4d4d4d">
   

This will tell the Android Device:

  • The name of the Application via short_name
  • The icon that will be used, based on device screen resolution
  • The start_url for the application to start
  • And at last to behave as stand alone application and not inside a browser.
  • theme-color that will be the status bar background color on your Android device.
  • Point your page to your manifest so it can be read by the Android device.


And that's it. You need to do anything afterwards, but is worth to mention that this functionality works on chrome browser, other browsers does not support this feature yet.
This is how you add it to your home Screen:
 
This is how looks like on home Screen:

And This is how it looks when it runs as Mobile Stand alone application.

 


For iOS Devices is a little bit different, but it can be accomplished, but instead of using manifest.json you need some metadata to make it works:

<%-- Meta details to set add to home on iOS Mobile devices as stand alone application --%>
   <meta name="apple-mobile-web-app-capable" content="yes">
   <meta name="apple-mobile-web-app-status-bar-style" content="black">
   <meta name="apple-mobile-web-app-title" content="A|G">
   
   

This will tell the iOS Device:

  • apple-mobile-web-app-capable will make it run as stand alone application
  • apple-mobile-web-app-status-bar-style will define the color of the status bar
  • apple-mobile-web-app-title is the title of the name of the application on home Screen
  • apple-touch-icon this is the icon that will be used on home screen
  • /ux/js/ux.main.links.js it is a script that will make all the links on your app stay on stand alone, this is needed to make the application stay as standalone, otherwise it will open new links on a tab, the code for this is on GitHub at https://gist.github.com/irae/1042167

As in Android Safari is the browser that support the add to home screen feature, this will not work on chrome since is not the native iOS browser.

Unfortunately I do not have an iOS device handy to show the screenshots as in Android, but believe it works the same, the only thing is that if you are running over https and your certificate is not trusted the icon will not be used, it will use an screenshot of the page instead.

Refer to https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html for ios related code
And for Android at https://developer.chrome.com/multidevice/android/installtohomescreen

Thursday, August 20, 2015

How To Change prefix on auto generated Ids (ATG Oracle Commerce)

ATG out of the box provide a mechanism to auto generate ids.

If you have been working with ATG you will know this by now, here are some examples of these Ids

Orders by default are created with prefix o, an order number is o4318732, shipping Groups are with prefix sg i.e. sg3251233.

This configuration can be changed easily updating das_id_generator table.

Let's say that we want to have an order prefix that starts with QAL, this is just matter of do the following update:

update das_id_generator set prefix = 'QAL' where id_space_name = 'order';

Now if we want to change the promotions prefix to be different we just need to do as follows:

update das_id_generator set prefix = 'p' where id_space_name = 'promotion';

This will do change it from promo to p.

As you can see id_space_name does match with the item descriptor type

Note: You will need to restart your server after the update since I do not know if there is a repository that can be used to invalidate the caches for these configurations.

So here are a sample of the records on das_id_generator_table, you can change any item descriptor prefix and suffix to make it work as your business needs, also it works with new item-descriptors, just need to create an entry on this table to make it work, SEED and BATCH_SIZE are used for IdGenerator component located at /atg/dynamo/service/IdGenerator/ oracle documentation is clear on how to use the columns and how to use the component these had not changed since a while so it applies to all versions as far as I have seen.



Friday, July 31, 2015

Create a Download link with javaScript (Front End Stuff)

If you want to have some content fetched by JavaScript you just need to do as follows:
Download File

Now this is simple create the content hardcoded but you can do whatever you want, here is an example on getting content from server download the file
          ${responseItem.xmlRequest} 

          Download Request
          


This is a live demo, just click HERE to download a file generated as the above code
Is worth to mention that if you have spaces on your test you need to encode them, otherwise those will disappear as in the download file above. The reference for this can be found at http://stackoverflow.com/questions/7717851/save-file-javascript-with-file-name

Get Current method name (Java)

There are classes that it is important to debug when a method starts and when a method ends.
Since there will be several methods you can get the mehtod name with java code so you just use the same line to log where your code is being executed.

in order to do this, we need to get the method and the class name for the current method

This is done by calling the currentThread Statck so we can get the name for the method as follows:


As you can see the currentThread().getStackTrace()[2] will be the thread that called getCurrentMethodLogMessage() that is why is on index [2]

In order to call this you can do as follows:

You can get a reference for this at http://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method

Monday, July 27, 2015

Set property values to dynamo components (ATG Oracle Commerce)

There are several ways to set values to dynamo components that are not just simple String, Boolean, Numbers or Components.

Set a Property to point to another component
commerceItemManager^=/atg/commerce/order/purchase/PurchaseProcessHelper.commerceItemManager

Define a List of values:
requiredAddressPropertyNames=firstName,\
                             lastName,\
                             address1,\
                             city,\
                             state,\
                             country,\
                             postalCode,\
                             phoneNumber

Define a Map, which is similar to the list
addressPropertyNameMap=firstName=First Name,\
                lastName=Last Name,\
                address1=Street Address,\
                city=City,\
                state=State,\
                country=Country,\
                postalCode=Zip Code,\
                phoneNumber=Phone Number

Set Null using the Constants component
relRankStrategy^=/Constants.NULL


All of this can be found on ATG Oracle Commerce documentation:

Tuesday, July 21, 2015

Grails domain class response as json (Grails)

With a grails Controller you can response your Domain class objects as json response.
it is as easy as follows:

Let's create a Product domain class as example

  Then run grails generate-all com.ocorp.grails.Product

 This will generate all our controllers, views, test cases.

 Inside our ProductController let's create a list() method or name it as you like better, and reneder the contest as json as follows:

When you go to /yourAppContext/product/list the response will be json for all the elements for your Domian Class Product:


This can be found at grails documentation http://grails.github.io/grails-doc/2.3.4/guide/theWebLayer.html#xmlAndJSON


Wednesday, July 15, 2015

Difference between doStopService and stopService on GenericService components (ATG Oracle Commerce)

It is common that when you are working with a GenericService component you need to change properties on it, and those are not reflected when the service runs after the changes are made, for those cases you need to stop the service and start it again.

There are 2 methods doStopService and stopService.

So, what should I do, just doStopSerivce?, run both? if so in which order?



According to the API, here is what each method does.

stopService

public void stopService()
                 throws ServiceException
Stops the service. This will be called when the Service is being shut down, either by explicit instructions from the administrator, or for various other reasons. A Service should clean up any resources it is using, but should be prepared to restart itself. When asked to restart, its properties may have changed.

doStopService

public void doStopService()
                   throws ServiceException
This is called when a Service is required to shut down. The Service should respond by stopping any processes that it has started.

So here are the answers for the questions above:

You just need to run stopService, this will call doStopService on it, and it will do things like change running flag to false and clean up resources, meaning your properties changes will be grabbed next time the service Starts.


Wednesday, July 8, 2015

Avoid java verbose code for Setters and Getters with anotations (Java)

There are times where your class needs to have several properties along with their setters and getters, this is ok, you can just auto generate them with eclipse, but your code at the end of the day will be full of a lot of verbose lines of code for those Getters and Setters.

In order to avoid this there is a Project called Lombok, they made a library to create Setters and Getters with Java annotations, at the beginning I was skeptical about this, but when I implemented on our Enterprise application, realized that it works as expected, and the good thing is that is integrated with eclipse out of the box, and the only requirement for your project is add this on your Java classpath.

The code looks like this, eclipse compile the code for you and display the generated setters and getters on the outline for you.


Just take a look at  Lombok and check the Demo Video, setters and getters are just a single feature, they have more that this.

I have used this inside my ATG application, just needed to add the .jar into MAINFEST.MF along with the Java classpath.

Tuesday, June 23, 2015

How to know which ATG modules are running on your server (ATG Oracle commerce)

There is an easy way to know which modules are started along with your server, without going into the logs or every single MANIFEST.MF file, that can be done within /dyn/admin

Just need to go to https://server:port/dyn/admin/atg/dynamo/admin/en/running-products.jhtml

Then you will find everything that is running with your server, in a screen as below:




This information is good for you if you are having odd issues, maybe a needed module did not started correctly and you can spot that in this page.

Thursday, June 18, 2015

How to configure a property to use a range of values on xml repository definition (ATG Oracle Commerce)

There are some things that you can do with xml definition file to define a range of values for a property into a repository.

Let's talk about the following scenario, we need a property that will hold the hour of the day which will be used to determine the released hour for a new product.

So we define this as a number property on our ATG xml repository as follows:



Since this is a property to hold the hour of the day, we need to restrict the field to be just from 0 to 23 if we use 24 hours format.

having said this we have some options that ATG does provide OOTB

One is an enumerated the code is as follows:

The other option is a java Class to create a Property Descriptor class that extends GSAPropertyDescriptor in order to restrict the data entered by the user, an example of how to do this can be found here.

Both options are ATG solutions, however there is an easier way to configure this and is not on ATG side, but on the Database as a constraint level that ATG will be forced to use, and that is a simple DB constraint as follows:

And that's it.
We used the Constraint on our last project, since is easier and less invaise in terms of code, feel free to use the option that fit better for your client needs.

Tuesday, June 16, 2015

How to change locale on your Store app (ATG Oracle commerce)

ATG does provide a mechanism to change locale on your application very easily with a component called RequestLocale, this componet can change the locale of the application and it is a session component, just need to change localeString Property to use the locale you want.

Inside a jsp can change the locale, below is an example of how to change it when switchTo parameter is send:
Once this is done the application will read the resource bundles from the new locale, so the site will be on the new locale. Important Note: For the Repository translations it will be needed to set
 /atg/dynamo/servlet/pipeline/DynamoHandler.generateRequestLocales to true.

This will serve repository translated properties by locale.

This can be found on documentation at: http://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPlatformProgGuide/html/s1807allowinguserstochoosealocale01.html and http://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s1808characterencodingandlocaleconfig01.html

It is important to note that if there is a missing key on resourceBundle the site will display this ????theBundle.key?????

And also if there is not translation or resourceBundle associated with the locale provided, ATG will use the default one which is en_US.

Here are some screenshot examples of the above code working on a store header.





This post is related to this translations post, which shows how to configure a Repository to use different locales.

Wednesday, May 20, 2015

How to get Thread Dumps from java application and how to analyze them

Thread dmps can say a lot about your application, but without a tool to do analysis on them are useless.
We will focus on how to get thread dmps from jboss application server as example, and how to analyze them.

First thing you need to do is get the processId of your jboss application, we can use something like this:

That will return the process which contains jboss on their data.


Now that you have the processId is just matter of call this jstack command to get the thread dmp



This will create a file called thread_running.out which is the actual thread dmp.

now a single thread dmp is not that useful, so I suggest you get several ones of the application your want to know about.

Once you have a several of them is time to analyze them.

There are several options, online tools, stand alone programs, but there is an eclipse plugin that is very friendly is called lockness, just go to the site and follow the steps to install it.

There is a bad thing, Luna does not support this, I bet that there is a work around for it, but I do not have that, so I used it on Kepler version.

Once Lockenss is installed you can see your thread dmps files in an eclipse window as follows:

Then you can see each thread dmp file inside eclipse, see dependencies between threads, deadlocks, threads waiting and what do started them, this will help you to trouble shoot faster an odd issue about a long running thread or dead locks on your application.






Special Thanks to Lockness plugin for exist.