X

Best Practices from Oracle Development's A‑Team

Engagement Cloud Groovy - replace hard coded values with Profile Options

Tim Bennett
CX Solution Architect

Introduction

If you have Groovy that looks like this, then this blog should be of interest!

switch (comp)
    {
        case 'Option1':
            return '300000007070670'
            break
        case 'Option2':
            return '300000007070671'
            break
        case 'Option3':
            return '300000007070672'
            break
		case 'Option4':
            return '300000007070673'
            break
        case 'Option5':
            return '300000007070676'
            break
    }

The only way to make changes or add new options is to edit the code and perform a software release. Business users cannot change the values, it is very easy to make mistakes, and it is difficult to check the values without looking through the code. Also, hard coded IDs rarely match between environments so the above code will have to cater for different values in dev/test/prod etc.

Other examples of hard coding that can be addressed through Profile Options are below.

Environment specific hard coding:

if (env =='dev') {
    def emailList = 'user1@oracle.com,user2@oracle.com,user3@oracle.com'
} else {
    def emailList = 'user4@oracle.com,user5@oracle.com,user6@oracle.com'
}

 

If statements:

{if(LinesOfBusinessType_c=='Lob1'){
    LineofBusiness='AA';
}
if(LinesOfBusinessType_c=='Lob2'){
    LineofBusiness='AN';
}
if(LinesOfBusinessType_c=='Lob3'){
    LineofBusiness='ME';
}
if(LinesOfBusinessType_c=='Lob4'){
    LineofBusiness='SG';
}
if(LinesOfBusinessType_c=='Lob5'){
    LineofBusiness='GS';
}

 

Hard coded usernames:

def username = adf.context.getSecurityContext()?.getUserName()
if (username == 'system_user') {
    //do system flow
} else {
    //end use flow
}

 

This blog shows 2 methods to maintain values used in Groovy scripts without needing a software release.

Method 1 - Profile Options

Method overview

This method uses new Profile Options to store the values. Single values are stored as Strings, and option/value pairs (as used in switch and if statements) are stored as "stringified" maps. The hard coded values used in Groovy are replaced by a call to the relevant Profile Option. In the case of switch and if statements the profile option is converted to a Map, and values are retrieved using standard Map methods.

 

Create a new Profile Option

Use FSM task Manage Profile Options to create new Profile Option. Set them up as below, making sure that the Site Enabled and Updatable flags are set. Note - it is also possible to add SQL validation to the profile values, and they can also be set at User level.

 

Enable the Site and User levels as necessary:

 

 

Edit Profile Option Values

Use FSM task Manage Administrator Profile Values and add a Site level value as illustrated below:

 

Retrieve Profile Option in Groovy

The values of Profile Options are retrieved using the syntax:

oracle.apps.fnd.applcore.Profile.get("PROFILE_NAME")

Note - if the profile option exists at User level for the logged in user, then the user value will be retrieved.

Using this approach, the first code sample in the introduction becomes:

Profile Option:    TJB_SALES_METHOD_ID

Value: Option1:300000007070670,Option2:300000007070671,Option3:300000007070672,Option4:300000007070673,Option5:300000007070676

 

Groovy:

def pair
def Map salesMethod = oracle.apps.fnd.applcore.Profile.get("TJB_SALES_METHOD_ID")
    .split(',')
    .collectEntries
    { 
      pair = it.split(":") 
      [pair[0],pair[1]]
    }

return salesMethod[comp]

The above code reads the "stringified" profile option TJB_SALES_METHOD_ID and converts it into a Map. Once the switch statement (or if statements) are converted to a Map, standard Map methods are used to retrieve the value of a key.

Since Profile Options are specific to an environment and are not moved by CSM, the environment specific code is not necessary and the environment specific email example becomes:

def emailList = oracle.apps.fnd.applcore.Profile.get("EMAIL_DL")

 

Where EMAIL_DL is a profile option containing the value user1@oracle.com,user2@oracle.com,user3@oracle.com in the dev environment and user4@oracle.com,user5@oracle.com,user6@oracle.com in prod.

User level Profile Options can be used for user specific flows:

if (oracle.apps.fnd.applcore.Profile.get("TJB_SYSTEM_FLOW")=='Y') {
      println("System flow")
} else {
      println("User flow")
}

In the above, the Site level profile value is set to N, and specified users have a value set to Y as illustrated below: 

 

Method 2 - Custom Object

While Profile Options provide an out of the box solution, there are scenarios where they may not be sufficient. For example, the following may be required:

Maintenance by end users without FSM access

Enhanced value validation

Functional and Data security

Values > 1000 characters

 

Instead of Profile Options, this method uses a Custom Object to store the parameter names and values. For example:

The object has 2 fields - ParameterName_c and ParameterValue_c. System parameters are retrieved via a Global Function (called getSystemParameter in this example) that accepts the parameter name as input:

 

def parmsVO = newView('SystemParameters_c')
parmsVO.appendViewCriteria("ParameterName_c = '" + ParameterName  + "'") 
parmsVO.executeQuery()
return parmsVO.first()?.getAttribute("ParameterValue_c")

 

Using this global function, the values would be retrieved by a call to the function, for example:

setAttribute('OwnerId', Long.ValueOf(adf.util.getSystemParameter("OWNER_ID") ))

def emailDL = adf.util.getSystemParameter("TJB_SALES_EMAIL_DL")

def SalesMethodId = adf.util.getSystemParameter("SALES_METHOD_ID")

Note, profile option values are Strings, so must be converted as necessary. In the first example above OwnerId is Long, hence the use of Long.ValueOf.

In addition to enabling easy maintenance and enhanced security, this approach can be extended to define the business scope of system parameters beyond Site and User, e.g. Country, Role, Region etc. 

Note - if end users are not given access to the System Parameters object, the "Privileged" flag will need to be set on the Global Function and access to the System Parameters object must be granted to the "Privileged Script Administration" role.

Regarding performance, in a test environment the global function response time was ~10ms, versus ~1ms for profile options.

 

Conclusion

A solution that uses hard coded system and business values that can only be changed via a software release will become difficult to maintain and will reduce business flexibility. Use one of the above methods to enable more flexible and transparent maintenance. By using the custom business object approach data security can be implemented and other features such as effective date and parameter scope can easily be added. Consider using Profile Options for parameters that rarely change, and the business object approach for those that require data security and/or need to be maintained by business users.

For customers using Visual Builder with Fusion Applications, there is also a  REST service that can be used to retrieve Profile Values. See the documentation for details:

https://docs.oracle.com/en/cloud/saas/applications-common/21a/farca/api-profile-values.html

 

 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha