Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

[jira 6] Velocity: how to retrieve context?

Jerome Renaud November 26, 2013

Hi all,

I'm trying to customize JIRA's release notes to include (among other things) component. Indeed the main goal is to output notes by component instead of issue type.

I'm new to Velocity which is not helping, but oddly some JIRA API classes are or are not available and I’ve guessed this is supposed to be in a mysterious ‘Velocity context’. Looking around I’ve found what looks to be a deprecated document: https://confluence.atlassian.com/display/JIRA042/Contents+of+the+Velocity+Context

(I’ve checked this page in 6.0: https://confluence.atlassian.com/display/JIRA060/Contents+of+the+Velocity+Context)

What is puzzling for me is the availability of java classes in Velocity: where is it defined? Do I have to guess what’s available?

Thank you for your help.

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

3 votes
Answer accepted
Jerome Renaud October 12, 2014

Hi all,

My workaround is no longer working as I get a new error when trying to load the class dynamically:

org.apache.velocity.exception.MethodInvocationException: Invocation of method 'findClass' in class org.apache.catalina.loader.WebappClassLoader threw exception java.lang.LinkageError: loader (instance of org/apache/catalina/loader/WebappClassLoader): attempted duplicate class definition for name: "com/atlassian/jira/component/ComponentAccessor" at templates/jira/project/releasenotes/releasenotes-components-html.vm[line 24, column 79] at org.apache.velocity.runtime.parser.node.ASTMethod.handleInvocationException(ASTMethod.java:351) ...

I don't know exactly what changed but to be able to keep it working I had to change

#set ($componentAccessorClass = $constantsManager.getClass().getClassLoader().findClass('com.atlassian.jira.component.ComponentAccessor'))
#set ($componentAccessorConstructor  = $componentAccessorClass.getConstructor())
#set ($componentAccessor = $componentAccessorConstructor.newInstance())

to

#set ($componentAccessor = $constantsManager.getClass().forName('com.atlassian.jira.component.ComponentAccessor').newInstance())
Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 2, 2015

Thanks for posting this! I was trying to figure out how to load a class dynamically in Velocity after upgrading JIRA and was wondering what I could do to get it working. It helped a lot!

IshanL
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 29, 2015

Thanks for the answer.

Dominic Markert September 25, 2015

you are a saint

0 votes
Jerome Renaud December 2, 2013

Thanks to Andy the final answer si in the ReleaseNoteManager.java code:

add("action", action).
                add("req", ExecutingHttpRequest.get()).
                add("issueTypes", issueTypes).
                add("appProps", applicationProperties).
                add("version", version.getName()).
                add("versionObj", version).
                add("project", project.getString("name")).
                add("textUtils", new TextUtils()).
                add("requestContext", new DefaultVelocityRequestContextFactory(applicationProperties).getJiraVelocityRequestContext()).
                add("constantsManager", constantsManager).
                add("customFieldManager", customFieldManager)

Edit: based on that I've found a trick to instanciate the object I need with the Java Reflection API:

#set ($componentAccessorClass = $constantsManager.getClass().getClassLoader().findClass('com.atlassian.jira.component.ComponentAccessor'))
#set ($componentAccessorConstructor  = $componentAccessorClass.getConstructor())
#set ($componentAccessor = $componentAccessorConstructor.newInstance())

#set ($projectComponentManager =  $componentAccessor.getProjectComponentManager())
#set ($projectManager =  $componentAccessor.getProjectManager())

Not the nicest but it works...

0 votes
Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

See https://developer.atlassian.com/pages/viewpage.action?pageId=4227172 it shows how to show the content of the context.

Adolfo Casari
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

Do you know how to add classes to that context?

See my question : https://answers.atlassian.com/questions/237110/how-to-access-velocity-tools?page=1#237462

Thanks!

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

thats a different question to your previous and this! It depends on what context. If you are writing an addon, you can expose anything you like through $action which is your webwork action.

Adolfo Casari
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

I was aware of that module, velocity-context-item, but it only applies to Confluence, and I need this for JIRA.

Jerome Renaud November 27, 2013

Thanks Andy but it's not working (just output nothing). If you try to "dump" the objet like this:

$ctx

It just output ... $ctx. I've tried $context without much luck.

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

Ah yes, not useful (re-edited above for clarity).

I think that it is possible but only in some situations where you are rendering a view via an Action provider class. With Web-Panels, you get to provide the context you need. Can you expand on where you want to do this?

If you are trying to 'inject' new things into someone elses view this wont be possible without a code customization.

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

that means whatever place you are in has a custom velocity context containing only the things it needs. It would require source code lookup to figure out whats in the context. Bottom line, no, you cant just pull in new things, you will need to either write a new thing or customize code in the existing thing.

Adolfo Casari
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2013

Can you expand on where you want to do this?

In a velocity file I would like to use the velocity tools, i.e. $number(decimal, $value) for instance. This is in a customfield plugin.

Thanks.

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 1, 2013

It looks like this got answered;

https://answers.atlassian.com/questions/237110/how-to-access-velocity-tools

Documentation covering the default content of the custom field context is at:

https://developer.atlassian.com/display/JIRADEV/Custom+field+Velocity+context+unwrapped

If you are writing your own Custom field you can define the velocity context yourself:

@Override
@SuppressWarnings("unchecked")
public Map getVelocityParameters(Issue issue, CustomField field,
FieldLayoutItem fieldLayoutItem) {
Map map = new HashMap();
Map<String, String> results = new HashMap<String, String>();
results.put("1", "A");
results.put("2", "B");
map.put("results", results);
return map;

}

You also have access to $action, which Im pretty sure would match to your custom field impl. So without merging contexts, you coudl also expose any custom operations you need within Java, eg getNumberTool() which returns an instance of NumberTool, accessed with $action.getNumberTool()

Adolfo Casari
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 1, 2013

As you suggest, I implemented my own getVelocityParameters to do the formatting of the CF. However this is not a clean approach both design and maintenancewise. The right thing here is to have straight access to GenericTools from velocity , since I am doing pure presentation stuff.

Why is this not available out of the box ??

Jerome Renaud December 1, 2013

Hi Andy, thank you for your reply.

So I understand that there is no documentation on what's available in this "release note" context. It sounds a bit rough to me… do you know where I can look for a piece of code describing it?

Thanks!

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 1, 2013

@ Adolfo, if you are implementing your own custom field its entirely expected that you provide what you need for your template to render as you want (emphasis on you!).

You might request access as a feature request, though, I doubt it will happen, there are lots of templates, and the net benefit to Atlassian is nil unless they were to adopt it.

@ dword, use the source luke :D find . -name *ReleaseNote* over the JIRA source download (available from your my.atlassian.com JIRA license screen) will return about 6 entries. On of them is the manager class will defines the content of the velocity context. Please post new questions as new questions, its related but is not the same question as asked.

TAGS
AUG Leaders

Atlassian Community Events