Loading freemarker templates from database into process

Hi all,

We are planning to load freemarker templates from a database to use then in service tasks for emails etc. Thus we want to avoid the need to re deploy the process in case we want to change the text of the mail.

My first idea was to use a spring bean that calls a function that loads the template from the database like

 ${loadtemplate("tplname")}

And makes it directly available as an input parameter. However, it seems to me that Tomcat does not support spring beans?

Any other thoughts? There is the possibility to load the text on start of the engine in a variable and use that one in the service tasks then but this breaks the simplicity of just referencing the template name in the service tasks itself.

Any recommendations?

@Tristan1 here is a example using scripts: see:

and here is a full function ready to be dropped into place:

You just need to change the getResource from the camunda db into your db call

@StephenOTT thanks for your reply and the very good work! However, as template loading occurs very often in our use cases I am a little bit reluctant to include that much of code in every process. Especially if sql database connections are involved we must handle all the dB stuff as well.
Maybe the idea, based on your contribution, is to create an external script that loads the contents from a database and use that script as an input parameter. The problem might be that we must give the script the template name in a convenient way. Eventually one could realise this by an extension parameter.

But it feels hacky and not really as simple as it could be (having all the logic in java itself and not in the diagramm)

Ya in practice we load all our scripts as a external script file.
something like this:

In this context, we opted to not use java deployments, and so most things are done as a script execution.

In the meantime I figured out how to approach this.

My first assumption was wrong that Tomcat does not support Spring Beans. I was confused with EJB (Java Enterprise Beans). But Spring Beans are in fact supported.

I decided to share my findings as using spring beans together with freemarker is hardly documented but very powerful to use in your templates. So in case anyone would like to to the same and load template via beans, please be advised:

In the end, in the freemarker template it shall be enough to say

${textbausteine.load('id_textbaustein')}

and to output then the template loaded from a database.

To make that happen, you have to create a spring bean with the ID textbausteine and a method called “load” that accepts the ID of the template as parameter.

package org.myorg.beans.textbausteine;

@Service
public class TextbausteineLoader {
    public String load(String textbausteinID) {
        return template_loaded_from_database;
    }
}

Then in your workflow project add two files under src/main/webapp/WEB-INF the files web.xml and applicationContext.xml that shall look like this:

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

</web-app>

applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans.xsd
                         http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<context:annotation-config />
       <bean id="textbausteine" class="org.myorg.beans.textbausteine.TextbausteineLoader" />
</beans>

Don’t forget to include Spring dependencies in the POM.XML

<dependency>
	<groupId>org.camunda.bpm</groupId>
	<artifactId>camunda-engine-spring</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>

Then it should work and you will get the loaded result.

P.S. What is still an issue are nested spring beans, please see here for the discussion https://forum.camunda.io/t/nested-spring-beans-in-freemarker/4039

1 Like

Thanks for sharing the solution. Always appreciated!