2012-06-22 2 views
3

Я пытаюсь выполнить тест модуля freemarker с использованием шаблонов htmlunit, junit и freemarker. Но когда я использовал < @ spring.message «data»>, это дало мне это исключение.Выражение springMacroRequestContext не определено

freemarker.core.InvalidReferenceException: Expression springMacroRequestContext is undefined on line 89, column 134 in spring.ftl. 
at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:125) 
at freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:135) 
at freemarker.core.Dot._getAsTemplateModel(Dot.java:78) 
at freemarker.core.Expression.getAsTemplateModel(Expression.java:89) 
at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:86) 
at freemarker.core.Expression.getAsTemplateModel(Expression.java:89) 
at freemarker.core.Expression.getStringValue(Expression.java:93) 
at freemarker.core.DollarVariable.accept(DollarVariable.java:76) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.IfBlock.accept(IfBlock.java:82) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.Macro$Context.runMacro(Macro.java:172) 
at freemarker.core.Environment.visit(Environment.java:614) 
at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.MixedContent.accept(MixedContent.java:92) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.Macro$Context.runMacro(Macro.java:172) 
at freemarker.core.Environment.visit(Environment.java:614) 
at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.MixedContent.accept(MixedContent.java:92) 
at freemarker.core.Environment.visit(Environment.java:221) 
at freemarker.core.Environment.process(Environment.java:199) 
at freemarker.template.Template.process(Template.java:237) 

Любое представление об этом исключении, как я могу это исправить? Благодарим за помощь заранее.

+0

по крайней мере для меня это происходит только при генерации html внутри java с использованием метода 'freemarker.template.Template.process'. Кажется, что springMacroRequestContext добавляется к позднему модели. «Нормальное» использование freemarker - путем возврата строки с именем шаблона из контроллера - работает без этой проблемы. – freakman

ответ

4

Я не уверен, какой правильный способ справиться с этим, поскольку я просто потратил около часа, пытаясь понять это сам. Но то, что работает для меня является добавление «springMacroRequestContext» вручную модели данных, используя следующие:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); 
model.put("springMacroRequestContext", new RequestContext(request, null, null, null)); 

Обратите внимание, что это все еще должно произойти внутри действительного запроса. Таким образом, это, вероятно, не будет работать в задании cron или запланированной задаче, так как нет текущего запроса.

+0

Вы можете высмеять запрос, если у вас есть доступ к 'WebApplicationContext'. См. Мой ответ. –

1

Вам необходимо настроить свой рефлектор Freemarker View в контроллере SpringContext.xml. В частности, добавить:

<property name="exposeSpringMacroHelpers" value="true"/> 

так это выглядит:

<bean id="freemarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> 
    <property name="cache" value="true"/> 
    <property name="prefix" value=""/> 
    <property name="suffix" value=".ftl"/> 
    <property name="exposeSpringMacroHelpers" value="true"/> 
    <property name="exposeSessionAttributes" value="true"/> 
    <property name="contentType" value="text/html;charset=UTF-8"/> 
</bean> 
+0

Это не работает, если вы пытаетесь использовать 'FreeMarkerTemplateUtils.processTemplateIntoString (Template t, Model m)', чтобы получить только строковый вывод из шаблона FreeMarker. Spring недавно устарела Velocity и предложила своим пользователям использовать FreeMarker для написания электронных писем, поэтому я думаю, что это то, что пытаются сделать многие люди. –

0

Развивая ответ Брэда Паркса вручную добавив springMacroRequestContext:

Достаточно иметь ссылку на WebApplicationContext (который можно легко получить с помощью @Autowired, если ваш объект является компонентом в WebApplicationContext), потому что вы можете высмеять запрос:

// Declare WebApplicationContext as an instance variable 
@Autowired 
WebApplicationContext ctx; 

// Then in the method...: 
    // (The mock object is from the org.springframework.mock.web package) 
    MockHttpServletRequest req = new MockHttpServletRequest(); 
    // secret sauce: 
    req.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); 
    // Create a MacroRequestContext for Freemarker to use 
    model.put("springMacroRequestContext", new RequestContext(req));