10-27-2016 06:41 AM
Hello,
I'm creating a custom form control and to render it I need to add custom java objects in the FreeMarker Model. From the documentation at Template models | Alfresco Documentation it seems to be possible to add this objects from a Spring Configuration. I've tried to search through Alfresco Source Code, and found some example of how the default model is added to Freemarker in repository/config/alfresco/template-services-context.xml.
So in my repo project I added:
<bean id="jsonToModelTemplateExtension" parent="baseTemplateImplementation" class="x.x.x.x.JsonTemplateExtension">
<property name="extensionName">
<value>jsonToModel</value>
</property>
</bean>
The java code is:
public class JsonTemplateExtension extends BaseTemplateProcessorExtension implements TemplateMethodModelEx {
private static final Log LOG = LogFactory.getLog(JsonTemplateExtension.class);
@Override
public Object exec(List arguments) throws TemplateModelException {LOG.warn(arguments);
return "Hello World!";
}
}
Then in my share project I've tried to use the Template Model Method like this:
<#assign mytext = jsonToModel('Teste')>
${mytext}<br/>
And I'm getting this error:
Caused by: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> jsonToModel [in template "org/alfresco/components/form/controls/conteudoSolicitacao.ftl" at line 4, column 26]
Any idea of what I am doing wrong?
Thanks,
Cedric.
10-28-2016 05:23 PM
I've taken your Spring bean, your Java class, and your freemarker snippet and ran them successfully unchanged, all within the repo tier.
It looks like you may be defining your bean in the repo tier, but then you are trying to run freemarker in the Share tier. Those are two completely different web applications, so if you want to use your Freemarker extension in the Share tier, you need to put your context file in the Share web app instead of the repo.
10-27-2016 11:32 AM
Where did you put your Spring context file and your compiled class?
Were there any errors reported in the log other than the InvalidReferenceException?
10-27-2016 12:07 PM
Hi,
The Spring context file is in classpath:alfresco/module/${project.artifactId}/context/service-context.xml and the compiled class had been packed in a jar in the generated amp file.
I've put a breakpoint in org.alfresco.repo.processor.BaseProcessorExtension#register() and saw that the TemplateExtension I created was registered against the FreeMarkerProcessor as are the standard ones (xmldate for instance).
public void register()
{
this.processor.registerProcessorExtension(this);
}
Thanks,
Cedric.
10-27-2016 06:12 PM
10-28-2016 05:23 PM
I've taken your Spring bean, your Java class, and your freemarker snippet and ran them successfully unchanged, all within the repo tier.
It looks like you may be defining your bean in the repo tier, but then you are trying to run freemarker in the Share tier. Those are two completely different web applications, so if you want to use your Freemarker extension in the Share tier, you need to put your context file in the Share web app instead of the repo.
10-29-2016 02:42 PM
Hi Jeff,
DOH!
You're right. They really are two different beasts!
In Share the only way I've found until now to customize the template is to override webscripts.container:
<bean id="webscripts.container" parent="webscripts.abstractcontainer" class="org.springframework.extensions.webscripts.LocalWebScriptRuntimeContainer">
<property name="name"><value>Surf Container</value></property>
<property name="registry" ref="webscripts.registry" />
<property name="searchPath" ref="webframework.webscripts.searchpath" />
<property name="templateProcessorRegistry" ref="webframework.webscripts.registry.templateprocessor" />
<property name="scriptProcessorRegistry" ref="webframework.webscripts.registry.scriptprocessor" />
<property name="scriptParameterFactoryRegistry" ref="webscripts.web.scriptparameterfactoryregistry" />
<property name="configService" ref="web.config" />
<property name="scriptObjects">
<map merge="true">
<entry key="remote" value-ref="webframework.webscripts.scriptremote" />
</map>
</property>
<property name="processorModelHelper" ref="processor.model.helper"/>
<property name="extensibilityModuleHandler" ref="webscripts.extensibility.handler"/>
<property name="urlModelFactory" ref="url.model.factory"/>
<!-- Override default Template Model -->
<property name="templateObjects">
<map merge="true">
<entry key="jsonToModel">
<bean class="br.gov.mpog.pocpdc.JsonTemplateExtension" />
</entry>
</map>
</property>
</bean>
I've seen that Spring Surf overrides the webscripts.container in spring-surf/src/main/resources/org/springframework/extensions/surf/spring-surf-application-context.xml that is already defined in Spring WebScripts spring-webscripts/src/main/resources/org/springframework/extensions/webscripts/spring-webscripts-application-context.xml, so this is why I'm using LocalWebScriptRuntimeContainer to override webscripts.container.
Thanks for your time!
Tags
Find what you came for
We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.