Cognos 10.1.1 bug: Charts breaking when switching between tabs

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>&lt;div id="reportWrapper" style="display:none"&gt;</staticValue>
			</dataSource>
		</HTMLItem><HTMLItem description="Chart Wrapper">
			<dataSource>
				<staticValue>&lt;div id="chartWrapper"&gt;</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>&lt;/div&gt;
&lt;/div&gt;
&lt;div id="message"&gt;
&lt;/div&gt;
&lt;script&gt;

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);
&lt;/script&gt;
</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>

Bug: In Cognos 10 new packages don’t inherit permissions

For the past week I’ve been researching a fix to an issue where new packages don’t inherit permissions.

Take the following scenario:

My client has a policy where all packages are saved in specific folders according to the associated project.

All projects are saved in the “Projects” folder with their own specific permissions.

Admins are granted full permission, the project admins are responsible for creating and maintaining the reports, and for granting rights to other users besides the default users for the project. Users are granted only read, execute, and traverse rights. Meaning that they can run any report, but not save anything to the folder. Admins can override this, of course, but that’s their own problem.

In theory, every new item should inherit these settings. Admins can override, but the general practice is to always allow the inheritance. Unfortunately there is a bug in Cognos in which newly created packages overwrite the inherited permissions.

Admins have their execute permissions removed, meaning they can’t run any of their reports, while users have been granted write rights. If the admins don’t notice and fix it immediately, this leaves a big hole in the security.

Fortunately IBM support is hot on the case. There response is that it’s a known issue, but the work-around is to modify the FM.ini file in the configuration directory.

To fix it, backup and open ..cognosc10configurationfm.ini in your text editor of choice.

Find the line

<Preference Name="SetPolicyPackage">FALSE</Preference>

and replace it with

<Preference Name="SetPolicyPackage">TRUE</Preference>

and save the file.

As this is not an XML file, no restart of Cognos is necessary. You probably need to restart FM if it’s open. All new packages will now inherit correctly.

My thanks to the IBM rep who helped me solve it, and to Noam at Libi who opened the ticket for me.

JavaScript stopped working in Cognos portal

Today I got a call from a friend. Shortly before going to production it was noticed that a report that works flawlessly from Report Studio, and from clicking on the report link in the portal, doesn’t work in the Cognos Portal.

The report relies on JavaScript to alter the prompts. When he runs the report from RS, everything is beautiful. Prompt headers are removed, default options are set, and everything behaves as expected. However, once the report was placedin a Cognos Viewer portlet in the portal an “Object Expected” error would be thrown every time the report was run.

It turns out there are several significant differences between the Report Viewer (from RS) and the Cogons Viewer (what’s used in the portlets). I cordially invite (okay, I’m begging. I really don’t want to go through a few thousand lines of JS.) any actual Cognos Devs to explain the differences between RV and CV.

An example of the original code:

<script language="javascript">
var f = getFormWarpRequest();
var list = f._oLstChoicesPrompt_Years;

list.remove(1);
list.remove(0);
list.removeAttribute("hasLabel");

canSubmitPrompt();
</script>

It removes the first two rows from the prompt (prompt label and the —), then removes the “hasLabel” attribute (which prevents those two rows values from being selected).

The corrected code is:

<script language="javascript">
var fW = (typeof getFormWarpRequest == "function" ? getFormWarpRequest() : document.forms["formWarpRequest"]);
if ( !fW || fW == undefined)
   { fW = ( formWarpRequest_THIS_ ? formWarpRequest_THIS_ : formWarpRequest_NS_ );}

var list = fW._oLstChoicesPrompt_Years;

list.remove(1);
list.remove(0);
list.removeAttribute("hasLabel");

canSubmitPrompt();
</script>

It was a very simple adaptation of the code found at IBM here.

This method will work in all versions from 8.3 and above (at least until they change the engine again).