We briefly mentioned one use-case for using application properties when we covered logging levels. The logging verbosity property is used more by the platform than your application. There are many other uses for storing application related settings for your application. Some common examples are default values, watermark or date stamp for recurring jobs, or any other values that you might not want to hard-code strings in scripts. When you hard-code values in scripts it exposes that script to a greater chance that something could go wrong when you need to change the value. One little typo in a script could crash the entire process. It's much more reliable to change a property value then edit a script.
The challenge in ServiceNow Fuji release is that you can no longer write to sys_properties records from your app scope scripts. So the case of using a property for a watermark that might have to be updated occasionally, will no longer be possible.
One of the primary reasons for this is that properties, and the way they are cached, aren't really designed for frequent updating which could happen if you are updating them from scripts.
Properties still have their place since you can expose them through a standard property page using categories which allows them to be viewed and edited through the UI.
For those cases where you just need a property to store and update a value from scripts, the alternative is to create a new table in your applications. This may seem like overkill, especially if you only need a couple of values stored. You may end up creating a table with 2 fields and 2 rows. But hey, it's easy enough to create tables, so why not.
The only real downside, and it's minor, is you'll need a bit more code to access and update the values then you would using get|setProperty.
//using properties in global scope or pre-Fuji gs.getProperty("my_app_prop"); gs.setProperty("my_app_prop", "hold this for me"); //Fuji app scope properties in a custom table var appProp = new GlideRecord("x_cavu_my_app_settings"); appProp.get("name", "app_prop1"); //get property var currentValue = appProp.getValue("value"); //set property appProp.setValue("value", "hold this for me"); appProp.update();
You might be wondering what happens if you have migrated code to an application scope, or just attempt to write to sys_properties from your scripts. Here's the result of a gs.setProperty call.
gs.setProperty("x_cavu_my_app.app_prop1", "hold this for me");
Evaluator: com.glide.script.fencing.MethodNotAllowedException: Function setProperty is not allowed in scope x_cavu_my_app Caused by error in script at line 1 ==> 1: gs.setProperty("x_cavu_my_app.app_prop1", "hold this for me");
And if we tried to update the record using GlideRecord we end up with.
var prop = new GlideRecord("sys_properties"); prop.get("name", "x_cavu_my_app.app_prop1"); prop.setValue("value", "hold this for me"); prop.update();
Security restricted: Write operation against 'sys_properties' from scope 'x_cavu_my_app' has been refused due to the table's cross-scope access policy
If you've been following the FujiForty series you already know this is because the application access control on the sys_property table prevents updates from other scopes.
I feel like this is another short-term issue that will eventually be addressed with a cleaner solution. Ideally applications need an easy way to store it's own properties that allow for updating though a nice property display page, updating via scripts with an easy API, and be cached like system properties.
Can you tell I already have a wish list for Geneva even though we just arrived in Fuji?