Skip to end of metadata
Go to start of metadata

Introduction

PlusWorkflow plugins can serve dynamic http pages built with the Freemarker library. This page will introduce the basics of creating such views.

Freemarker Editor

Unfortunately, the Eclipse environment does not have a built-in Freemarker editor.Such an editor can be installed separately along with JBoss Tools.

More at: http://freemarker.org/editors.html

Basics

 

Freemarker is an alternative to JSP, which cannot be integrated into a plug-in mechanism for a number of reasons. Freemarker templates are created dynamically and do not require compilation into Java classes.

Pages are created dynamically by inserting object values from the model straight into the template. The model is completed with, for example, request attributes (HttpServletRequest) quite like JSP.

 

Completion of the model is usually done in the controller:

HelloController
@Controller
public class HelloController {
 
	// The result of these 2 methods will be the same
 
	@RequestMapping("/hello")
	public String sayHello(Model model){
		model.addAttribute( "username", "World" );
		return "hello"; // /views/hello.ftl
	}
 
	@RequestMapping("/hello2")
	public String sayHello(HttpServletRequest request){
		request.setAttribute( "username", "World" );
		return "hello"; // /views/hello.ftl
	}
}

Template

hello.ftl
 <h1>Hello ${username}</h1>

Result

hello.html
 <h1>Hello World</h1>

Freemarker supports loops, if..else expressions, html escape, date formatting etc. It is recommended to read the documentation http://freemarker.org/docs/index.html

PluginRequestContext object

KEach rendered .ftl view has access to an additional PluginRequestContext object that facilitates the retrieval of translations, paths, etc:

Examples of PluginRequestContext
<!-- Downloading plugin context path: /{contextPath}/plugin/{id}/  -->
${pluginContext.pluginContextPath}
 
<!-- Get the relative address to the plugin context: /{contextPath}/plugin/{id}/hello  -->
${pluginContext.getPluginContextUrl('hello')}
 
<!-- Get plugin resource path: /{contextPath}/plugin/{id}/resources/{timestamp}  -->
${pluginContext.pluginResourcesPath}

<!-- Get the path to the plugin resource: /{contextPath}/plugin/{id}/resources/{timestamp}/hello.js  -->
${pluginContext.getPluginResourcesUrl('hello.js')}
 
<!-- Get contextPath: e.g. /PlusWorkflow -->
${pluginContext.contextPath}
 
<!-- Get contextPath: e.g. /PlusWorkflow/Admin.do  -->
${pluginContext.getContextUrl('Admin.do')}
 
<!-- Get key translation without parameters -->
${pluginContext.getMessage('messagekey')}

<!-- Get translation with parameters -->
${pluginContext.getMessage('messagekey', ['somearg'])}

Macro plugin.ftl

In addition, the plugin can import a macro that simplifies operations on the PluginRequestContext object.

Macro plugin
<!-- Importing a macro -->
<#import "/plugin.ftl" as plugin/>
 
<!-- Get the relative address to the plugin context: /{contextPath}/plugin/{id}/hello  -->
<@plugin.url 'hello'/>
 
<!-- Get the path to the plugin resource: /{contextPath}/plugin/{id}/resources/{timestamp}/hello.js   -->
<@plugin.resourceUrl 'hello.js'/>
 
<!-- Get contextPath: e.g. /PlusWorkflow/Admin.do -->
<@plugin.systemUrl 'Admin.do'/>
 
<!-- PGet key translation without parameters -->
<@plugin.message 'messagekey'/>

Using JspTagLib

Freemarker allows calls to JspTagLib (e.g. displaytag, jstl).

Nowadays, there should be no need to use taglibs. A better alternative to them, for example, is to use dynamic JavaScript components or move the logic to a controller.

There is no guarantee that the TagLib used will work smoothly.

jstl
<!--  Assigning the tagline "JSTL" to the variable "c" -->
<#assign c=JspTaglibs["http://java.sun.com/jsp/jstl/core"] />
 
<!-- <c:import...> -->
<@c.import charEncoding="UTF-8" url=someUrl />
displaytag
<!-- Assigning the tagline "displaytag" to the variable "display" -->
<#assign display=JspTaglibs["http://displaytag.sf.net"] />
 
<@display.table id="table" name="records" pagesize=20 partialList=true requestURI="someUrl">
	<@display.column title=pluginContext.getMessage("Lp") class="small">${table_rowNum}</@display.column>
	<!-- ... -->
</@display.table>

View decorators

Freemarker views generated by the plugin are decorated by default to match the style of the PlusWorkflow system.

By default, all requests that:

  • are not Ajax requests (do not contain the X-Requested-With: XMLHTTPREQUEST header)
  • the request decorator parameter is not present or has a value other than none

The following decorators are available in the system (we use the name as the value of the decorator parameter):

NameDescriptionUrl
systemDefault decorator - enters the contents of the template into the body area of the page. The header, system menu, footer will be automatically generated.http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=system

empty

Empty decorator - contains all scripts and css styles. It does not contain any structure such as header or footer.http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=empty
plainSimple decorator - contains only standard JavaScript scriptshttp://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=plain
noneNo decorator. Only the contents of the template will be displayed.http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=none
notloggedLogin page decorator to display information about invalid loginhttp://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=notlogged



  • No labels