Skip to main content
Server-rendered properties let you compute read-only column values that depend on data outside the current work item — related items, project metadata, repository information, or the current user’s permissions. Configure them via the serverRender key in the domain model YAML and display them in sheet columns marked as read-only.

Service Injection Architecture

diagram The server renderer populates two layers of Velocity context:
LayerLifetimeVariables
Static (cached)Server process lifetime$trackerService, $txService, $repositoryService, $securityService
Per-itemOne evaluation per work item$item, $wi, $tx, $module, $context
The static context is built once and stored in a cached base context object. All platform service references are then reused across every template evaluation without re-initialization, which keeps rendering fast even for large sheets.

Service Summary

VariablePolarion InterfacePurpose
$trackerServiceITrackerServiceQuery work items, access project metadata, run Lucene searches
$txServiceITransactionServiceTransaction management within templates
$repositoryServiceIRepositoryServiceAccess project metadata, users, roles, repository configuration
$securityServiceISecurityServiceCheck permissions, implement role-based visibility

$trackerService

PropertyValue
Variable name$trackerService
Polarion interfaceITrackerService
ScopeStatic (cached)
Primary useWork item queries, Lucene searches, project metadata
Provides access to work item queries, project-level tracker metadata, and Lucene search operations. This is the most commonly used platform service in server-rendered properties because it enables cross-item lookups and data aggregation across the project.

Common Operations

OperationMethodReturn Type
Retrieve work item by URIgetWorkItemByUri(uri)IWorkItem
Access Lucene query servicegetDataService()IDataService
Access project by IDgetProject(projectId)IProject

Example: Retrieve a Work Item by URI

#set($related = $trackerService.getWorkItemByUri($item.uri))
Related title: $related.title

Example: Run a Lucene Query

#set($ds = $trackerService.getDataService())
#set($results = $ds.searchInstances("WorkItem", "type:systemRequirement AND project.id:MyProject", "title", -1))
Found $results.size() system requirements

Example: Access Project Metadata

#set($proj = $trackerService.getProject("MyProject"))
Project: $proj.name

Example: Count Linked Design Requirements

This pattern queries for all design requirements linked to the current work item:
#set($ds = $trackerService.getDataService())
#set($q = "type:designRequirement AND linkedWorkItem:$item.id")
#set($results = $ds.searchInstances("WorkItem", $q, "id", -1))
$results.size()
Lucene queries inside serverRender execute once per row in the sheet. On a sheet with 500 work items, a single Lucene query in a server-rendered column runs 500 times. Keep queries simple and avoid them on large datasets. Test on a filtered subset first.

$txService

PropertyValue
Variable name$txService
Polarion interfaceITransactionService
ScopeStatic (cached)
Primary useTransaction context access
Provides access to Polarion transaction management. In the context of server-rendered properties, templates execute within a read-only evaluation context. The transaction service is primarily useful for understanding the execution context rather than performing write operations.
The $txService variable is available in all templates. Its available methods depend on the Polarion server version. Consult the Polarion API documentation for the ITransactionService interface. Server-rendered expressions should not use this service to initiate write transactions — they run in a read-only evaluation context.

$repositoryService

PropertyValue
Variable name$repositoryService
Polarion interfaceIRepositoryService
ScopeStatic (cached)
Primary useProject metadata, users, roles, repository configuration
Provides access to repository-level operations: project metadata, user information, roles, and repository configuration. Useful for templates that need to display data from outside the current work item’s project scope or that need to resolve user or role information.

Example: Access Project Name

#set($proj = $repositoryService.getProjectById($item.projectId))
Project: $proj.name

Example: Resolve a User ID to Display Name

#set($user = $repositoryService.getUserById($item.author.id))
Author: $user.getName()
Available methods depend on the Polarion server version. The repository service provides read-only access to repository-level resources. Consult the Polarion API documentation for IRepositoryService.

$securityService

PropertyValue
Variable name$securityService
Polarion interfaceISecurityService
ScopeStatic (cached)
Primary usePermission checks, role-based visibility, user identification
Enables permission checking, role-based visibility, and user identification within templates. Use this service to conditionally render content based on the logged-in user’s identity or to verify access rights before displaying sensitive data.

Example: Show Current User

#set($user = $securityService.getCurrentUser())
Evaluated by: $user.getId()

Example: Permission-Based Visibility

#if($securityService.canRead($item))
  $item.title
#else
  [Restricted]
#end

Example: Role-Based Content

#set($user = $securityService.getCurrentUser())
#if($user.hasRole("project_admin"))
  Admin view: $item.title ($item.status.id)
#else
  $item.title
#end
Combine $securityService with conditional Velocity logic to build columns that display different content depending on the current user’s role or permissions. The rendered value is computed server-side, so the user cannot bypass the check client-side.

Per-Item Context Variables

In addition to the static platform services, the server renderer injects per-item variables for each work item during evaluation. These are documented in detail on the Context Variables page. The summary:
VariableTypeDescription
$itemModelObjectPrimary work item accessor. Properties: .title, .status, .author, .created, .updated, .uri
$wiIWorkItemLegacy Polarion API. Only available for work item entities. Use for: $wi.getCustomField("fieldId"), $wi.getLinkedWorkItems()
$txTransactionCurrent transaction context. Templates see the transaction state at evaluation time
$moduleIModuleDocument (LiveDoc) containing the work item. null for entities outside a document. Properties: .moduleFolder, .moduleName, .space
$contextPowersheetContextServer API context with project scope and query capabilities
Prefer $item (ModelObject) for accessing standard work item properties. Use $wi (IWorkItem) only when you need methods not available on $item, such as getCustomField() or getLinkedWorkItems(). The $wi variable is only set for work item entities — it is null for non-work-item entity types.

Caching Behavior

AspectDetail
Cache scopeStatic base context instance built at first evaluation
LifetimePersists for the lifetime of the Polarion server process
Thread safetyService instances are thread-safe; shared across all concurrent evaluations
ExtensionPer-item variables ($item, $wi, $module, $context, $tx) are layered on top of the cached context for each evaluation
Additional servicesAdditional context services may be injected beyond the four core platform services

Error Handling

When a Velocity template evaluation fails, the server renderer returns the constant error marker:
#SERVER_RENDER_ERROR
If this value appears in a sheet column, the serverRender expression for that property contains an error. Check the Polarion server logs for one of these exceptions:
ExceptionCause
ParseErrorExceptionInvalid Velocity syntax in the template (mismatched directives, bad variable references)
MethodInvocationExceptionA method call on a service or object threw an exception (null pointer, permission denied, invalid argument)
ResourceNotFoundExceptionA referenced Velocity resource (macro, include file) does not exist
IOExceptionI/O failure during template processing
The #SERVER_RENDER_ERROR marker is the only client-visible indicator of a problem. To diagnose the root cause, check the Polarion server logs (logs/polarion*.log) where the full stack trace is logged with the template pattern and exception details. Common causes include referencing a null property without an #if guard, calling a method with the wrong argument type, or using incorrect Velocity syntax.

Domain Model Configuration

Server-rendered properties are configured in the domain model YAML using the serverRender key on a property definition. The value is an Apache Velocity template that is evaluated for each work item when the sheet loads.

Property Definition

KeyTypeDescription
serverRenderstringVelocity template pattern evaluated per work item. The result replaces the property value in the sheet.
Properties with serverRender are automatically marked as read-only — the computed value cannot be edited by users.

Single-Line Expression

domainModelTypes:
  SystemRequirement:
    polarionType: systemRequirement
    properties:
      evaluatedBy:
        serverRender: "$securityService.getCurrentUser().getId()"

Multi-Line Template

Use YAML block scalar syntax (|) for templates with conditional logic or multiple statements:
domainModelTypes:
  SystemRequirement:
    polarionType: systemRequirement
    properties:
      projectName:
        serverRender: |
          #set($proj = $repositoryService.getProjectById($item.projectId))
          $proj.name

Complete YAML Example

The following domain model and sheet configuration demonstrate all four platform services used in server-rendered properties within a standard RTM entity type. Domain model YAML:
domainModelTypes:
  SystemRequirement:
    polarionType: systemRequirement
    properties:
      title:
      severity:
      evaluatedBy:
        serverRender: "$securityService.getCurrentUser().getId()"
      projectName:
        serverRender: |
          #set($proj = $repositoryService.getProjectById($item.projectId))
          $proj.name
      linkedCount:
        serverRender: |
          #set($links = $wi.getLinkedWorkItems())
          $links.size()
      relatedReqCount:
        serverRender: |
          #set($ds = $trackerService.getDataService())
          #set($q = "type:designRequirement AND linkedWorkItem:$item.id")
          #set($results = $ds.searchInstances("WorkItem", $q, "id", -1))
          $results.size()
Sheet configuration YAML:
columns:
  id:
    width: 80
  title:
    width: 300
  evaluatedBy:
    width: 150
    isReadOnly: true
  projectName:
    width: 150
    isReadOnly: true
  linkedCount:
    width: 80
    isReadOnly: true
  relatedReqCount:
    width: 100
    isReadOnly: true

sources:
  - id: requirements
    title: System Requirements
    model: rtm
    query:
      from: SystemRequirement
Server-rendered properties are always read-only in the sheet. The serverRender value is computed on each query and cannot be edited by the user. Mark the corresponding sheet columns with isReadOnly: true to communicate this in the UI.

Best Practices

PracticeRationale
Keep templates simpleEvery serverRender expression executes per row. Complex logic multiplies server load.
Avoid nested Lucene queriesA Lucene query inside serverRender on a 500-row sheet runs 500 times. Pre-compute if possible.
Use $item over $wiModelObject ($item) is the modern API. Fall back to $wi only for custom field access or linked work item traversal.
Test with small datasetsValidate templates on a filtered query before applying to the full document.
Check for #SERVER_RENDER_ERRORIf a column shows this marker, check server logs for the exception type and template pattern.
Use #if for null safetyWrap service calls in #if guards: #if($item.projectId)...#end to avoid null pointer exceptions.
Avoid write operationsTemplates run in a read-only context. Do not use $txService to start write transactions.
Prefer standard properties firstOnly use serverRender when a standard property, formula, or display expression cannot provide the needed value.

Service Availability Quick Reference

Use the following decision table to determine which service fits your use case:
Use CaseServiceExample Pattern
Look up a related work item$trackerService$trackerService.getWorkItemByUri($item.uri)
Search for work items by query$trackerService$trackerService.getDataService().searchInstances(...)
Access project metadata$trackerService or $repositoryService$trackerService.getProject("projectId")
Get current user identity$securityService$securityService.getCurrentUser().getId()
Check user permissions$securityService$securityService.canRead($item)
Conditionally show content by role$securityService$user.hasRole("role_name")
Resolve user details$repositoryService$repositoryService.getUserById("userId")
Access repository configuration$repositoryService$repositoryService.getProjectById("projectId")


Source Code
  • ServerRenderer.java — core rendering engine, service injection via static context builder
  • ServerRendererTest.java — validates service injection into Velocity context
  • DataPropertyFactory.java — security and type mapping for server-rendered properties