15 October 2015

So it turns out you can use SOY templates in JIRA webwork actions, but its not a straightforward switch.

Soy

First you need to convert your template to soy:

{namespace Magical.templates}

/**
 * Render the main UI
 * @param something
 */
{template .main}
    <html>
        ...
    </html>
{/template}

Web-resource

Then add a web-resource to declare your soy file:

<web-resource key="action-templates">
    <resource type="soy" name="does-not-matter" location="somewhere/magic-action.soy"/>
</web-resource>

Webwork

Then adjust the webwork action to refer to it:

<webwork1 key="some-magic" class="java.lang.Object">
    <actions>
        <action name="com.example.MagicAction" alias="Magic">
            <view type="soy" name="input">:action-templates/Magical.templates.main</view>
        </action>
    </actions>
</webwork1>

Notice the view refers to the web-resource module key: :action-templates - this is short form for my-plugin-key:action-templates, followed by the fully namespaced template name after a slash. We don't need to know the file location or resource name here.

Watch it fail

Then give it a whirl, and watch it fail ;)

Annotate like crazy

We don't get any parameters passed to the template at all by default, which in someways is good, but it means extra work adapting your action.

You no longer have an $action parameter either.

To pass data into the template you need to annotate the methods in your action with @ActionViewData, eg:

@ActionViewData
public String getSomething() {
    return ...;
}

The data from these methods is gathered prior to rendering, and not called on-demand, as velocity does. Also if you want to get data from a method higher in the inheritance hierarchy you'll need to override it and annotate it, eg:

@ActionViewData
@Override
public String getReturnUrl() {
    return super.getReturnUrl();
}

You can no longer call arbitrary methods from your action, @ActionViewData only supports methods that return something and take no parameters.

Although you can return any object from these methods and a soy mapper will handle resolving keys to method calls, as best as it can. If you need more control over the process, either format and return new data, or use a SoyDataMapper - I haven't tried this yet though.

@ActionViewData does allow you to specify an alternative parameter name for the data return by the method, and you can also limit which views the data will be collected for.

@ActionViewDataMappings is similar but allows specifying of several action views.

I18n

Wherever you used to do this:

${i18n.getText('foo')}

you'll do:

{getText('foo')}

but BEWARE, the argument has to be a literal string, this will not work:

{getText($myI18nKey)}

you'll have to resolve dynamic i18n keys in your action beforehand.



blog comments powered by Disqus