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.
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.
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:
Use FSM task Manage Administrator Profile Values and add a Site level value as illustrated below:
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:
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.
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