Freemarker 日期分配看似有效日期失败

发布于 2024-12-24 17:03:12 字数 2312 浏览 4 评论 0原文

我遇到了一个奇怪的问题,似乎并不总是发生,但是当它发生时,它看起来像这样:

Error: on line 60, column 31 in foo/bar.ftl
Expecting a date here, found: 2011-12-29 04:37AM
The problematic instruction:
----------
==> assignment: createDate=project.createdTime?datetime("yyyy-MM-dd hh:mma") [on line 60, column 9 in foo/bar.ftl]
----------

Java backtrace for programmers:
----------
freemarker.template.TemplateModelException: Error: on line 60, column 31 in foo/bar.ftl
Expecting a date here, found: 2011-12-29 04:37AM
    at freemarker.core.BuiltIn$dateBI$DateParser.parse(BuiltIn.java:334)
    at freemarker.core.BuiltIn$dateBI$DateParser.get(BuiltIn.java:305)
    at freemarker.core.BuiltIn$dateBI$DateParser.exec(BuiltIn.java:316)
    at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
    at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
    at freemarker.core.Assignment.accept(Assignment.java:90)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.Environment.process(Environment.java:190)
    at freemarker.template.Template.process(Template.java:237)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
    at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
...

bar.ftl 中失败的行看起来像这样:

<#assign createDate = project.createdTime?datetime("yyyy-MM-dd hh:mma")>

Project.java 代码中的 getter看起来像这样:

private Date createdTime;
...
public String getCreatedTime() {
    SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd hh:mma");
    return createdTime == null ? null : sm.format(createdTime);
}

所以对我来说,看起来一切都正确返回,并且代码设置正确。我正在使用 FreeMarker 2.3.16 和 Spring MVC。它似乎大部分时间都有效,但有时会失败......

想法?

I'm running into a weird problem that doesn't seem to happen all the time, but when it does, it looks like this:

Error: on line 60, column 31 in foo/bar.ftl
Expecting a date here, found: 2011-12-29 04:37AM
The problematic instruction:
----------
==> assignment: createDate=project.createdTime?datetime("yyyy-MM-dd hh:mma") [on line 60, column 9 in foo/bar.ftl]
----------

Java backtrace for programmers:
----------
freemarker.template.TemplateModelException: Error: on line 60, column 31 in foo/bar.ftl
Expecting a date here, found: 2011-12-29 04:37AM
    at freemarker.core.BuiltIn$dateBI$DateParser.parse(BuiltIn.java:334)
    at freemarker.core.BuiltIn$dateBI$DateParser.get(BuiltIn.java:305)
    at freemarker.core.BuiltIn$dateBI$DateParser.exec(BuiltIn.java:316)
    at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
    at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
    at freemarker.core.Assignment.accept(Assignment.java:90)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.MixedContent.accept(MixedContent.java:92)
    at freemarker.core.Environment.visit(Environment.java:210)
    at freemarker.core.Environment.process(Environment.java:190)
    at freemarker.template.Template.process(Template.java:237)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
    at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
...

The line in bar.ftl where it's failing looks like this:

<#assign createDate = project.createdTime?datetime("yyyy-MM-dd hh:mma")>

The getter in the Project.java code looks like this:

private Date createdTime;
...
public String getCreatedTime() {
    SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd hh:mma");
    return createdTime == null ? null : sm.format(createdTime);
}

So to me, it looks like everything is getting returned correctly, and that the code is setup correctly. I'm using FreeMarker 2.3.16 and Spring MVC. It seems to work most of the time, but fails sometimes...

Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猛虎独行 2024-12-31 17:03:12

该错误消息意味着 DateFormat.parse 在内部抛出了 java.text.ParseException。由于异常消息中给出的字符串应该用该模式解析正常(我希望你的示例是准确和真实的),并且由于它只是有时发生,所以它就像日期格式周围的并发(多线程)问题一样缓存。如果您可以构建一个独立的测试来证明这一点,那么可以更快地找到它(我几乎负责维护 FM)。快速查看源代码,我什么也没注意到……同步就在那里。

编辑:另一个可能的原因是有时 FreeMarker“区域设置”设置不是英语。对于非英语,“AM”/“PM”后缀是不同的,因此会导致此错误。

The error message means that, internally, DateFormat.parse has thrown java.text.ParseException. Since the string given in the exception message should be parsed OK with that pattern (and I hope your example is exact and real), and since it happens only sometimes, it stinks like a concurrency (multi-threading) issue around the date-format cache. If you could construct a standalone test that demonstrates this, that would make finding it quicker (I'm in charge of maintaining FM, pretty much). Quickly looking at the source code nothing jumps at me... the syncs are there.

Edit: Another possible reason is that sometimes the FreeMarker "locale" setting is not English. The "AM"/"PM" postfix is different for non-English, and so it causes this error.

浅唱ヾ落雨殇 2024-12-31 17:03:12

你的代码看起来有效,我不知道为什么它会失败 - 特别是“有时”。

然而,让我觉得奇怪的一件事是,您首先将日期转换为字符串(在 getCreatedTime() 内),只是为了在 FreeMarker 模板中解析它。为什么不首先将其作为日期传递呢?像这样的东西:

// Project.java
public Date getCreatedTime() {
    return this.createdTime;
}

// bar.ftl
<#assign createDate = project.createdTime?datetime>

Your code looks valid, I've no idea why it fails - especially "sometimes".

One thing that strikes me as odd, however, is that you're converting your date to string first (inside getCreatedTime()) only to parse it back within FreeMarker template. Why not pass it as date to begin with? Something like:

// Project.java
public Date getCreatedTime() {
    return this.createdTime;
}

// bar.ftl
<#assign createDate = project.createdTime?datetime>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文