Writing a Velocity report step by step

By Jason posted 01-07-2016 14:14

  
Please note that Jama versions prior to 8.42 will require an old version of Velocity which uses different syntax.
Note that user-created Velocity reports can be uploaded to on-premises versions of Jama only. Hosted customers need to follow the instructions here to have their reports uploaded.
 
This is a guide to writing Velocity reports in Jama. It demonstrates starting with a basic template and building the report through multiple iterations, making small changes at each step so that it is easy to see what worked and what did not. This shows a specific report as an example, but the workflow should apply to any report you want to write.

The report in this example shows the number of active items by type in each project in Jama. To run any of the examples, save the example code in a text file named "itemcounts.vm." In Jama, go to Admin > Reports and add a report with the following settings:


To run the report, select a project and then Reports > Item Counts by Project > Run Report.

Step 1) Base template
Velocity reports are fundamentally just HTML markup, so start with a very basic layout.

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
</body>
</html>




 
 
 
Step 2) List Projects
First, the report needs to list available projects in Jama. In Jama's Velocity report documentation, the projectSource.getProjects() method returns a list of projects.
 
#set($projects = $projectSource.getProjects(true))

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
#foreach ($project in $projects)
$project.name<br>
#end

</body>
</html>


 

Step 3) Show only actual projects
Some entries are showing up in the list twice, like "IIBA BABOK." In the Select Project window in Jama, projects can be arranged in Folders. The folders are the extra entries in the previous example. 


 
For this report, the folders are not needed, just a list of projects. To fix that, check to see if each project is a Folder, and only show it if it is not.
 
#set($projects = $projectSource.getProjects(true))

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
#foreach ($project in $projects)
#if (!$project.isFolder)
$project.name<br>
#end
#end
</body>
</html>


 
 

Step 4) Get item counts for each project
In Jama's Velocity documentation, documentSource.getAllItemTypesCount() returns a map object, which is a list of name/value pairs. In this case, the name is the Item Type and the value is the number of items of that type in a project. 
 
#set($projects = $projectSource.getProjects(true))

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
#foreach ($project in $projects)
#if (!$project.isFolder)
#set ($itemCounts = $documentSource.getAllItemTypesCount($project.id))

$project.name<br>
$itemCounts<br>
#end
#end
</body>
</html>



 
 
Step 5) Show each Item Type on its own line
Each Item Type should be on its own line. The Velocity User Guide has an example of how to get keys (names) and values out of a map object.
 
#set($projects = $projectSource.getProjects(true))

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
#foreach ($project in $projects)
#if (!$project.isFolder)
#set ($itemCounts = $documentSource.getAllItemTypesCount($project.id))

$project.name<br>
#foreach ($itemType in $itemCounts.keySet())
$itemType - $itemCounts.get($itemType)<br>
#end
#end
#end
</body>
</html>



 
 
Step 6) Display Item Type names instead of id numbers
That is a good start, but the report needs the name of the Item Type instead of just the ID number. In Jama's documentation, documentSource.getAllDocumentTypesMap() returns a map object containing id/document type pairs in a given organization.
 
For each Item Type, get the name of the Item Type from the $documentTypes map, and the count from the $itemCounts map.
 
#set($projects = $projectSource.getProjects(true))
#set($documentTypes = $documentSource.getAllDocumentTypesMap(2))

<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
#foreach ($project in $projects)
#if (!$project.isFolder)
#set ($itemCounts = $documentSource.getAllItemTypesCount($project.id))

$project.name<br>
#foreach ($itemType in $itemCounts.keySet())
$documentTypes.get($itemType) - $itemCounts.get($itemType)<br>
#end
#end
#end
</body>
</html>



Note: Another way to do this would be to make a documentSource.getDocumentType() call for each document type in the report. In a short report, this probably would not make much difference. In a report with many projects and Item Types, it could be considerably faster to get all the document types at once.
 
 

Step 7) Add formatting
Now that all the data is in the report, change the page layout so each project is in its own row with the Item Types to the right.
 
#set($projects = $projectSource.getProjects(true))
#set($documentTypes = $documentSource.getAllDocumentTypesMap(2))
<html>
<head>
<title>Item Counts by Type per Project</title>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
<table>
#foreach ($project in $projects)
#if (!$project.isFolder)
#set ($itemCounts = $documentSource.getAllItemTypesCount($project.id))
<tr>
<td>$project.name</td>
<td>
<table width="100%">
#foreach ($itemType in $itemCounts.keySet()) 
<tr>
<td>$documentTypes.get($itemType)</td>
<td>$itemCounts.get($itemType)</td>
</tr>
#end
</table>
</td>
</tr>
#end
#end
</body>
</html>



 

Step 8) Change font and fix the alignment
Finally, change the font on the page, add formatting and fix the alignment in the tables.
 
#set($projects = $projectSource.getProjects(true))
#set($documentTypes = $documentSource.getAllDocumentTypesMap(2))

<html>
<head>
<title>Item Counts by Type per Project</title>
<style>
body { font-family: sans-serif;}
h1 { font-size: 1.5em; text-align:right;}
</style>
</head>
<body>
<h1>Item Counts by Type per Project</h1>
<table>
#foreach ($project in $projects)
#if (!$project.isFolder)
#set ($itemCounts = $documentSource.getAllItemTypesCount($project.id))

<tr>
<td valign="top"><b>$project.name</b></td>
<td>
<table width="100%">
#foreach ($itemType in $itemCounts.keySet())
<tr>
<td align="left">$documentTypes.get($itemType)</td>
<td align="right">$itemCounts.get($itemType)</td>
</tr>
#end
</table>
</td>
</tr>
#end
#end
</body>
</html>



 
 
Troubleshooting

Problem: Velocity shows variable names instead of values in the report

For example: 
#set ($myText = "This is my text")
$myText
$otherText

Displays:
This is my text
$otherText
If a variable or property does not exist, by default Velocity will print the variable's name instead. Often that is because a property does not exist on one type of item. For example, when iterating through all items in a project, a Requirement and a Test Case have different fields. 
 
Use a quiet reference to override that behavior by adding an exclamation point after the dollar sign. For example:
#set ($myText = "This is my text")
$!myText
$!otherText
 
Would display:
This is my text


#tutorial #velocity
3 comments
1446 views

Comments

05-01-2019 19:55

Is there any documentation that provides more information on the methods, formats etc for the DAO calls, preferably written in a way that non-developers can understand.

01-07-2016 15:10

Thanks for sharing. 

01-07-2016 14:58

This is my new favorite post!!!!! THANK YOU!