How to use a freemarker resource template without getting "Value too long for column"

Hi,

I’m passing a FreeMarker template to a SendTask as an input parameter. The template is passed as an
external resource, i.e. using its path. When the template is big enough I’m getting the following error:

Error flushing statements. Cause: org.apache.ibatis.executor.BatchExecutorException: org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity.insertHistoricVariableInstance (batch index #1) failed. Cause: org.h2.jdbc.JdbcBatchUpdateException: Value too long for column “TEXT_ VARCHAR(4000) SELECTIVITY 14”: “STRINGDECODE('\n<html lang="“en"”>\n\n\n \n <meta http-equiv="“Content-Type"” content=… (37942)”; SQL statement:…

The same process works well with a shorter template.

To work around this problem I tried two different approaches:

  1. calling execution.removeVariableLocal(“paramName”) before returning from execute()
  2. passing the path as a string, loading the template dynamically and then create context and evaluating the template using API.

Option (1) didn’t work. I was getting the same exception even after removing the parameter.
Option (2) seems promising, but I couldn’t find an example how to use Camunda API to programmatically evaluate templates.

Does anyone have an experience working with bigger than 4Kb FreeMarker templates? Any ideas how to make it work?

abc.bpmn (3.7 KB)

See: Freemarker Script: Greater than 4000 char, exceeding historic variable instance DB insert

Many thanks, @StephenOTT, with your help I was able to make it work!

Here is the function that gets a path to freemarker template (needs to be on the classpath) and returns a file rendered using the current process context.

private String evalTemplate(DelegateExecution execution, String resourcePath) {
	String rendered = null;
	Scanner scanner = null;
	try {
		ScriptingEngines scriptingEngines = Context.getProcessEngineConfiguration().getScriptingEngines();
		ScriptEngine freemarker = scriptingEngines.getScriptEngineForLanguage("freemarker");
		Bindings bindings = scriptingEngines.createBindings(freemarker, execution);
		
		File file = new File(ProcessConfig.class.getClassLoader().getResource(resourcePath).getFile());
		scanner = new Scanner(file);
		String template = scanner.useDelimiter("\\Z").next();
		rendered = (String)freemarker.eval(template, bindings);
	} catch (FileNotFoundException e) {
		e.printStackTrace(); // TODO
	} catch (ScriptException e) {
		e.printStackTrace(); // TODO
	} finally {
		if(scanner != null) {
			scanner.close();
		}
	}
	
	return rendered;
}