EWM/RTC Javascript attribute customization - does return value need to be the last line in script?
I had a "Calculated Value" script to set the value of a Custom Attribute. This script had worked for a long time but suddenly started being flakey under 7.0.2 (worked sometimes and sometimes it didn't).
I started playing with it in our DEVELOPMENT environment (adding some console.log statements) and discovered that it wouldn't set the custom attribute at all. I could tell from the browser's "Development Tools"/"Console" and my "console.log" that the script was being invoked/executed but the value would never be updated.
I decided to take out the try/catch (originally had a try/catch block). When I took out the try catch such that the last line in the script was the return value, the script worked/updated the custom value.
Are try/catch blocks forbidden in calculated values?
Script before (wouldn't update value):
dojo.provide("com.example.storyPointsLastModified");dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");(function() {dojo.declare("com.example.storyPointsLastModified", null, {getValue: function(attribute, workItem, configuration) {try {// testvar lastModifiedDate = new Date();var lastModifiedDateString = dojo.date.stamp.toISOString(lastModifiedDate, {milliseconds:true, zulu:true});var txt = "The date story points were modified was: " + lastModifiedDateString;console.log(txt);return lastModifiedDateString;}catch(err) {var txt;txt="There was an error on this page.\n\n";txt+="Error description: " + err.message + "\n\n";txt+="Click OK to continue.\n\n";if (typeof window !== "undefined") {window.alert(txt);}}}});})();
Script after (successfully updates value):
dojo.provide("com.example.storyPointsLastModified");dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");(function() {dojo.declare("com.example.storyPointsLastModified", null, {getValue: function(attribute, workItem, configuration) {var lastModifiedDate = new Date();var lastModifiedDateString = dojo.date.stamp.toISOString(lastModifiedDate, {milliseconds:true, zulu:true});var txt = "The date story points were modified was: " + lastModifiedDateString;console.log(txt);return lastModifiedDateString;}});})();
Accepted answer
- As far as I am aware, you can not use window alert. My understanding is, the Javascript is run in its own engine and has no connection to the web UI.
- You can use console.log. The log output goes into the eclipse workspace log.
- Calculated values and the other attribute customization provider are defining a function. You have to always return a value, otherwise the interface contract is broken and you do not get the correct behavior. In your case, if you try/catch you still have to return a valid value e.g. you can return the original value.
My experience is shared here:
https://rsjazz.wordpress.com/?s=attribute+customization&submit=Search
https://rsjazz.wordpress.com/?s=attribute+customization&submit=Search
Comments
3 other answers
No you can return at any time.
There are a couple of things to check:
- you have a console log statement in your try but not your catch. While I can't see that your script would throw an error it may be worth checking that catch isn't being invoked, because you return nothing inside it
- I'm not sure you even need a try/catch here. What were you wrapping that might need exception protection?
- having said that, try/catch should work just fine as it's standard Javascript
Comments
@Ralph Schoon:
Thank you for your explanation. It was very helpful. I was finally able to get it working as desired by adding the return of the original value in the catch as you suggested. If I uncomment the "throw new Error" line and step through the debugger (setting ?debug=true and using the browser's developer tools to load the script), I can see that the "window.alert" does display a diaglog box which is good.
The final script looks like:
dojo.provide("com.example.storyPointsLastModified");dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");(function() {dojo.declare("com.example.storyPointsLastModified", null, {getValue: function(attribute, workItem, configuration) {// Get the current value of the custom attribute (used in "catch" path)var storyPointsModifiedCur = workItem.getValue("storyPointsLastModified");try {var lastModifiedDate = new Date();var lastModifiedDateString = dojo.date.stamp.toISOString(lastModifiedDate, {milliseconds:true, zulu:true});var storypointsactual = parseInt(workItem.getValue("com.ibm.team.apt.attribute.complexity"), 10);var txt = "The date story points were modified was: " + lastModifiedDateString;console.log(txt);//throw new Error('Cannot update storyPointsLastModifiedAttribute');return lastModifiedDateString;}catch(err) {var txt;txt="There was an error on this page (Attribute: storyPointsLastModified was NOT updated).\n\n";txt+="Error description: " + err.message + "\n\n";txt+="Click OK to continue.\n\n";if (typeof window !== "undefined") {window.alert(txt);}return storyPointsModifiedCur;}}});})();
Thank you for your response.
Comments
In my DEV environment, I couldn't get the custom attribute to update at all. The script was being invoked because I saw the "console.log" output in the browser tools but after saving the work item, the custom attribute would just appear as "None" in query output.
That's when I got the idea to completely take out the catch and observed that it started working. It is my understanding that;
if (typeof window !== "undefined") {
window.alert(txt);
}
only runs "window.alert" on the client.
I know I don't really need the try/catch since the value is being set to the current date time. It may make sense to just remove the try/catch all together.
In our PRODUCTION environment, my users were complaining that the value does get set "sometimes" so maybe your theories are correct. I was planning to update the script in PROD this weekend so I think I will take out the try/catch all together. Will see if my users quit reporting the problem.
Thank you for all your great insights/suggestions.
Comments
1 vote