An annoying bug has been reported by several of my clients.
Any portal tab containing a chart will occasionally break when the user clicks away then returns:
If the user were to click on Public Folders, then return to the portal tab, suddenly the chart images are broken.
While I can’t explain why this is happening, I’m guessing that Cognos is flushing the image from the cache when the user leaves the page. When the user returns the image is no longer in the cache, so it’s returns a broken image.
Fortunately the refreshing the report will return the chart so this gives us a partial solution. If we can write a script that detects the state of the image (if it’s broken or not) we can have the portlet refresh.
First the report should be wrapped in a div with the display set to none. This will prevent users from seeing the broken charts. Second the chart itself should be wrapped in a div to give the function a place to start looking for broken images.
The function itself is fairly simple:
function checkImg() { var reportWrapper = document.getElementById('reportWrapper'); var chartWrapper = document.getElementById('chartWrapper'); var message = document.getElementById('message'); var img = chartWrapper.getElementsByTagName('IMG'); message.innerHTML = "checking image"; if (img[0].readyState == 'uninitialized') {refreshReport();message.innerHTML = "refreshing report";} else {reportWrapper.style.display="";message.innerHTML = "";} }
It checks the image’s readyState attribute. If it’s unitialized, the image is broken and the report should be refreshed, otherwise everything is fine and show the report.
The refresh function is from one of the IBM knowledge base articles.
function refreshReport() { var intval; var fW = (typeof getFormWarpRequest == "function" ? getFormWarpRequest() : document.forms["formWarpRequest"]); if ( !fW || fW == undefined) { fW = ( formWarpRequest_THIS_ ? formWarpRequest_THIS_ : formWarpRequest_NS_ ); } var preFix = ""; if (fW.elements["cv.id"]) { preFix = fW.elements["cv.id"].value; } var nameSpace = "oCV" + preFix; if(intval!="") { self.clearInterval(intval); intval=""; } self["RunReportInterval"] = self.setInterval( nameSpace + ".getRV().RunReport()",'0' ); intval = self["RunReportInterval"]; }
Finally the checkImg function needs to be called. It can’t be called as soon as the page is loaded, because the chart image itself takes a moment to load. If the function is called before the chart is loaded, it will refresh the page in an infinite loop. Instead it’s best to wait a moment. I find that 1 second works well.
setTimeout("checkImg()",1000);
Now when the page loads it will wait 1 second and check the chart. If the image is broken it will refresh the page:
It’s worth mentioning that this is a band-aid solution (and not a great one either). The true fix needs to come from IBM. There is an APAR open for this issue, but so far no hotfix. Slower computers may take longer to load the image, and may result in the user being stuck in an infinite loop. Additionally the report will only display after the function has a chance to check the image, effectively increasing the load time of the report by however long is set in the setTimeout.
Report XML: (Remember to create a page and add this to a cognos viewer)
<report xmlns="http://developer.cognos.com/schemas/report/8.0/" useStyleVersion="10" expressionLocale="en-us"> <modelPath>/content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Data Warehouse (query)']/model[@name='model']</modelPath> <drillBehavior modelBasedDrillThru="true"/> <queries> <query name="Query1"> <source> <model/> </source> <selection><dataItem name="Gross margin" aggregate="automatic"><expression>[Sales (query)].[Gross margin]</expression><XMLAttributes><XMLAttribute name="RS_dataUsage" value="fact" output="no"/></XMLAttributes></dataItem><dataItem name="Product line" aggregate="none" rollupAggregate="none"><expression>[Sales (query)].[Products].[Product line]</expression><XMLAttributes><XMLAttribute name="RS_dataType" value="3" output="no"/><XMLAttribute name="RS_dataUsage" value="attribute" output="no"/></XMLAttributes></dataItem></selection> </query> </queries> <layouts> <layout> <reportPages> <page name="Page1"><style><defaultStyles><defaultStyle refStyle="pg"/></defaultStyles></style> <pageBody><style><defaultStyles><defaultStyle refStyle="pb"/></defaultStyles></style> <contents> <HTMLItem description="report Display None"> <dataSource> <staticValue><div id="reportWrapper" style="display:none"></staticValue> </dataSource> </HTMLItem><HTMLItem description="Chart Wrapper"> <dataSource> <staticValue><div id="chartWrapper"></staticValue> </dataSource> </HTMLItem><combinationChart showTooltips="true" maxHotspots="10000" refQuery="Query1" name="Combination Chart1"> <legend> <legendPosition> <relativePosition/> </legendPosition> <legendTitle refQuery="Query1"> <style> <defaultStyles> <defaultStyle refStyle="lx"/> </defaultStyles> </style> </legendTitle> <style> <defaultStyles> <defaultStyle refStyle="lg"/> </defaultStyles> </style> </legend> <ordinalAxis> <axisTitle refQuery="Query1"> <style> <defaultStyles> <defaultStyle refStyle="at"/> </defaultStyles> </style> </axisTitle> <axisLine color="black"/> <style> <defaultStyles> <defaultStyle refStyle="al"/> </defaultStyles> </style> </ordinalAxis> <numericalAxisY1> <axisTitle refQuery="Query1"> <style> <defaultStyles> <defaultStyle refStyle="at"/> </defaultStyles> </style> </axisTitle> <gridlines color="#cccccc"/> <axisLine color="black"/> <style> <defaultStyles> <defaultStyle refStyle="al"/> </defaultStyles> </style> </numericalAxisY1> <combinationChartTypes> <bar/> </combinationChartTypes> <style> <defaultStyles> <defaultStyle refStyle="ch"/> </defaultStyles> </style> <commonClusters><chartNodes><chartNode><chartNodeMembers><chartNodeMember refDataItem="Product line"><chartContents><chartTextItem><dataSource><memberCaption/></dataSource></chartTextItem></chartContents></chartNodeMember></chartNodeMembers></chartNode></chartNodes></commonClusters><defaultChartMeasure refDataItem="Gross margin"/></combinationChart> <HTMLItem description="closing divs and script"> <dataSource> <staticValue></div> </div> <div id="message"> </div> <script> function checkImg() { var reportWrapper = document.getElementById('reportWrapper'); var chartWrapper = document.getElementById('chartWrapper'); var message = document.getElementById('message'); var img = chartWrapper.getElementsByTagName('IMG'); message.innerHTML = "checking image"; if (img[0].readyState == 'uninitialized') {refreshReport();message.innerHTML = "refreshing report";} else {reportWrapper.style.display="";message.innerHTML = "";} } function refreshReport() { var intval; var fW = (typeof getFormWarpRequest == "function" ? getFormWarpRequest() : document.forms["formWarpRequest"]); if ( !fW || fW == undefined) { fW = ( formWarpRequest_THIS_ ? formWarpRequest_THIS_ : formWarpRequest_NS_ ); } var preFix = ""; if (fW.elements["cv.id"]) { preFix = fW.elements["cv.id"].value; } var nameSpace = "oCV" + preFix; if(intval!="") { self.clearInterval(intval); intval=""; } self["RunReportInterval"] = self.setInterval( nameSpace + ".getRV().RunReport()",'0' ); intval = self["RunReportInterval"]; } setTimeout("checkImg()",1000); </script> </staticValue> </dataSource> </HTMLItem></contents> </pageBody> <pageHeader> <contents> <block><style><defaultStyles><defaultStyle refStyle="ta"/></defaultStyles></style> <contents> <textItem><style><defaultStyles><defaultStyle refStyle="tt"/></defaultStyles></style> <dataSource> <staticValue>This works</staticValue> </dataSource> </textItem> </contents> </block> </contents> <style> <defaultStyles> <defaultStyle refStyle="ph"/> </defaultStyles> <CSS value="padding-bottom:10px"/> </style> </pageHeader> <pageFooter> <contents> <table> <tableRows> <tableRow> <tableCells> <tableCell> <contents> <date> <style> <dataFormat> <dateFormat/> </dataFormat> </style> </date> </contents> <style> <CSS value="vertical-align:top;text-align:left;width:25%"/> </style> </tableCell> <tableCell> <contents> <pageNumber/> </contents> <style> <CSS value="vertical-align:top;text-align:center;width:50%"/> </style> </tableCell> <tableCell> <contents> <time> <style> <dataFormat> <timeFormat/> </dataFormat> </style> </time> </contents> <style> <CSS value="vertical-align:top;text-align:right;width:25%"/> </style> </tableCell> </tableCells> </tableRow> </tableRows> <style> <defaultStyles><defaultStyle refStyle="tb"/></defaultStyles> <CSS value="border-collapse:collapse;width:100%"/> </style> </table> </contents> <style> <defaultStyles> <defaultStyle refStyle="pf"/> </defaultStyles> <CSS value="padding-top:10px"/> </style> </pageFooter> </page> </reportPages> </layout> </layouts> <XMLAttributes><XMLAttribute name="RS_CreateExtendedDataItems" value="true" output="no"/><XMLAttribute name="listSeparator" value="," output="no"/><XMLAttribute name="RS_modelModificationTime" value="2011-06-09T13:50:33.233Z" output="no"/></XMLAttributes><reportName>Test 1</reportName></report>
this method very suitable for “real-time” monitoring
IBM now has a hot fix available for this product defect. You will need to open a service ticket with them to get an interim fix. I suspect this will also be addressed in the next fix pack.
Well the hotfix IBM gave didn’t work for us.
In the dispatcher settings under tuning, change the temporary file location to Content store, this will fix the issue.
It still can be considered a bug, as there is a field to control the number of hours the temporary location should hold the chart images, which is set to 4 hours by default. So, regardless of whether the selection is Content store or file system the charts should be held for 4 hours at least.
So it will always boil down to the same basic issue – if the temporary image has timed out, Cognos should be smart enough to refresh the page before attempting to render the missing image.
I haven’t tried the hotfix that Kevin mentioned, so this might be irrelevant now.
But if u change the setting to content store, the images will never disappear.
Interesting, I’ll take a look at that. Thanks!
On another note,
Have you ever used a prompt macro inside custom MDC ? I have used it successfully within custom SQL, but it just doesn’t seem to like it when used within custom MDC.
Any suggestions could be helpful,
Thanks,
Swetab
I honestly haven’t had much need for custom MDX. The only time I actually needed it was for a client who demanded the MDX be exactly the way they provided. Prompt macros should be possible, you probably just need to either transform the MUNs with the substitute function or work with the business keys. I’ll try to throw together something later this week.