2012-06-22 132 views
3

我正在嘗試使用htmlunit,junit和freemarker模板進行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

至少對我來說,它只發生在使用'freemarker.template.Template.process'方法生成java內部的html時。似乎springMacroRequestContext被添加到模型的後期。 freemarker的'正常'用法 - 通過從控制器返回帶有模板名稱的字符串 - 在沒有此問題的情況下工作。 – freakman

回答

4

我不知道處理這個問題的正確方法是什麼,因爲我剛剛花了大約一個小時試圖自己弄清楚這一點。但是,什麼工作對我來說是使用以下手動添加「springMacroRequestContext」數據模型:

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

注意,這仍然有一個有效的請求內發生。所以這可能不會在cron工作或計劃任務中工作,因爲目前沒有請求。

+0

如果您有權訪問「WebApplicationContext」,則可以模擬請求。看到我的答案。 –

1

您需要在您的Spring controllerContext.xml中配置Freemarker View Resolver。具體來說,加上:

<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(模板t,模型m)'來獲取FreeMarker模板的字符串輸出,則這不起作用。 Spring最近棄用了Velocity,並建議其用戶使用FreeMarker編寫電子郵件,所以我想這是很多人試圖做的。 –

0

擴展在布拉德·帕克斯的回答上手動添加springMacroRequestContext

這足以要了WebApplicationContext參考(其中如果您的對象是WebApplicationContext中的bean,則可以使用@Autowired輕鬆訪問),因爲您可以模擬請求:

// 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)); 
相關問題