Script Service

Last modified by Vincent Massol on 2026/09/10 21:24

Reference

Release Notes Application 2.7+ $services.releasenotes creates, reads and searches release notes and changes from a wiki page. It is a thin layer over the Java API, with the same rights checks, so a page can build views and creation forms of its own.

MethodReturnsDescription
createReleaseNote($note)DocumentReferenceCreates the release note from its template and returns its page.
getReleaseNoteReference($product, $version)DocumentReferenceThe page a release note has, or would have.
updateReleaseNote($note)ReleaseNoteRelease Notes Application 2.8+ Replaces the release note that product and version locate, and returns it as stored.
getReleaseNote($reference)ReleaseNoteReads a release note back. Throws when the page carries none.
getReleaseNotes($product)List<ReleaseNote>Every release note of a product, or of all of them when $product is null.
getAggregatedVersions($reference)List<String>The versions a note covers, its milestones and release candidates included.
createChange($change)DocumentReferenceAllocates the next Entry001 page, writes both objects and saves once.
reserveNextEntry($product, $version)DocumentReferenceAllocates and saves that page empty, for a form that then opens it in the editor.
updateChange($reference, $change)ChangeRelease Notes Application 2.8+ Replaces the change that page holds and returns it as stored. A property the passed change leaves out is emptied.
getChange($reference)ChangeReads a change back. Throws when the page carries none.
parseQuery($parameters)ChangeQueryBuilds a query from the comma-separated filter strings the macros take.
search($query)ChangeSearchResultRuns it. getChangeNames() gives page names a Velocity list can hold, hasMore() whether a further page exists.
getDefaultProduct()StringThe configured default product.
getDefaultTemplate()DocumentReferenceThe configured default template.

Two idioms are worth knowing, because neither is guessable from the signatures.

Pass a map, not a bean. Change and ReleaseNote have registered converters, so a Velocity map literal is converted on the way in, and the property names are those of the model:

{{velocity}}
#try()
#set ($created = $services.releasenotes.createChange({'product': 'MyProduct', 'version': '3.0',
  'title': 'Live Data replaces the Live Table', 'audience': 'user', 'importance': 'high'}))
The change was created as $created
#end
{{/velocity}}

Catch with the try directive. The service throws instead of returning null and stashing an error, so a call that may fail goes inside a try block, which puts the exception in the variable it names rather than letting it break the page:

{{velocity}}
#try('creationError')
#set ($note = $services.releasenotes.createReleaseNote({'product': 'MyProduct', 'version': '3.0'}))
#end
#if ($creationError)
  The release note could not be created: $creationError.message
#else
  The release note is at $note
#end
{{/velocity}}

Searching takes the same filter language as the getChanges macro, which is itself a shim over parseQuery and search. Use the macro on a page that only needs to list changes, and the service when the page has to work on the result:

{{velocity}}
#set ($query = $services.releasenotes.parseQuery({'products': 'MyProduct', 'versions': '3.0,3.0-milestone%',
  'audience': 'user', 'importance': '>=medium', 'limit': 20}))
#set ($result = $services.releasenotes.search($query))
#foreach ($name in $result.changeNames)
* [[$name]]
#end
{{/velocity}}

A page calling the creation methods needs edit right on the page being created, for the user viewing it and for the page's own author, and the wiki refuses the call otherwise.

FAQ

Why does my call return nothing instead of failing?

It did fail: the service throws, so an uncaught exception stops the script. Wrap the call in a try block and read the exception it puts in the variable you named.

Why does a map literal work where the signature asks for a bean?

Change and ReleaseNote have registered converters, and the Method Arguments Uberspector converts the map before the call. A missing mandatory property is reported as a conversion error naming it.

When should I use the getChanges macro instead?

Whenever the page only lists changes: the macro already calls this service and hands the page names to a display macro. Use the service when the page has to filter, count or reorder the result itself.

Related

Get Connected