JBehave
  1. JBehave
  2. JBEHAVE-812

OutcomesTable with date values makes an error in freemarker

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 3.6.8
    • Fix Version/s: 3.6.9, 3.7
    • Component/s: Core
    • Labels:
    • Environment:
      Maven 2
    • Number of attachments :
      0

      Description

      When using OutcomesTable with some date values to validate, there's a problem with the freemarker plugin.
      Freemarker seems to expect the .ftl file to include the date part to render, as specified in the exception.
      AFAIK, i don't have any control under the ftl generation...

      java.lang.RuntimeException: ftl/jbehave-xml-output.ftl
      at org.jbehave.core.reporters.TemplateableOutput.write(TemplateableOutput.java:182)
      at org.jbehave.core.reporters.TemplateableOutput.afterStory(TemplateableOutput.java:171)
      at org.jbehave.core.reporters.DelegatingStoryReporter.afterStory(DelegatingStoryReporter.java:49)
      at org.jbehave.core.reporters.ConcurrentStoryReporter.afterStory(ConcurrentStoryReporter.java:125)
      at org.jbehave.core.embedder.StoryRunner.runCancellable(StoryRunner.java:316)
      at org.jbehave.core.embedder.StoryRunner.run(StoryRunner.java:211)
      at org.jbehave.core.embedder.StoryRunner.run(StoryRunner.java:172)
      at org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:229)
      at org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:201)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
      at java.util.concurrent.FutureTask.run(FutureTask.java:138)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:662)
      Caused by: org.jbehave.core.reporters.FreemarkerProcessor$FreemarkerProcessingFailed: Freemarker failed to process template ftl/jbehave-xml-output.ftl using configuration freemarker.template.Configuration@44f942c4 and data model

      {story=org.jbehave.core.reporters.TemplateableOutput$OutputStory@488e753c, keywords=org.jbehave.core.reporters.TemplateableOutput$OutputKeywords@b2db5b}

      at org.jbehave.core.reporters.FreemarkerProcessor.process(FreemarkerProcessor.java:25)
      at org.jbehave.core.reporters.TemplateableOutput.write(TemplateableOutput.java:179)
      ... 13 more
      Caused by: freemarker.template.TemplateModelException: Can't convert the date to string, because it is not known which parts of the date variable are in use. Use ?date, ?time or ?datetime built-in, or ?string.<format> or ?string(format) built-in with this date.
      at freemarker.core.Environment.formatDate(Environment.java:765)
      at freemarker.core.Expression.getStringValue(Expression.java:105)
      at freemarker.core.Expression.getStringValue(Expression.java:93)
      at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
      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.IteratorBlock$Context.runLoop(IteratorBlock.java:167)
      at freemarker.core.Environment.visit(Environment.java:417)
      at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
      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.Macro$Context.runMacro(Macro.java:172)
      at freemarker.core.Environment.visit(Environment.java:603)
      at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106)
      at freemarker.core.Environment.visit(Environment.java:210)
      at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
      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.Macro$Context.runMacro(Macro.java:172)
      at freemarker.core.Environment.visit(Environment.java:603)
      at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106)
      at freemarker.core.Environment.visit(Environment.java:210)
      at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:167)
      at freemarker.core.Environment.visit(Environment.java:417)
      at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
      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.IfBlock.accept(IfBlock.java:82)
      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.IteratorBlock$Context.runLoop(IteratorBlock.java:167)
      at freemarker.core.Environment.visit(Environment.java:417)
      at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
      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.jbehave.core.reporters.FreemarkerProcessor.process(FreemarkerProcessor.java:23)
      ... 14 more

        Activity

        Mauro Talevi made changes -
        Field Original Value New Value
        Fix Version/s 3.6.9 [ 18650 ]
        Hide
        Mauro Talevi added a comment -

        This may happen if the object in the OutcomesTable is a Date. Freemarker does not have a default way of handling it.

        Can you provide an example of the data that caused the error.

        Workaround is create Outcomes using their String representation, e.g.

        new Outcome("A date", new SimpleDateFormat("dd/MM/YYYY").format(new Date()), equalTo("01/01/2011")) 
        
        Show
        Mauro Talevi added a comment - This may happen if the object in the OutcomesTable is a Date. Freemarker does not have a default way of handling it. Can you provide an example of the data that caused the error. Workaround is create Outcomes using their String representation, e.g. new Outcome( "A date" , new SimpleDateFormat( "dd/MM/YYYY" ).format( new Date()), equalTo( "01/01/2011" ))
        Hide
        Ghislain Nadeau added a comment -

        Here's a simple working example:

        Story:

        Scenario: Outcome fail
        Given nothing
        When nothing
        Then the result should be 2001-01-01
        

        Steps:

        public class OutcomesDateFailSteps {
            @Given("nothing")
            @When("nothing")
            public void nothing() {
            }
        
            @Then("the result should be $date")
            public void result(@Named("date") Date result) {
                OutcomesTable out = new OutcomesTable();
        
                out.addOutcome("A failing date", result, Matchers.equalTo(new Date()));
        
                out.verify();
            }
        
            @AsParameterConverter
            public Date createDate(String name) throws ParseException {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                return sdf.parse(name);
            }
        }
        
        Show
        Ghislain Nadeau added a comment - Here's a simple working example: Story: Scenario: Outcome fail Given nothing When nothing Then the result should be 2001-01-01 Steps: public class OutcomesDateFailSteps { @Given("nothing") @When("nothing") public void nothing() { } @Then("the result should be $date") public void result(@Named("date") Date result) { OutcomesTable out = new OutcomesTable(); out.addOutcome("A failing date", result, Matchers.equalTo(new Date())); out.verify(); } @AsParameterConverter public Date createDate(String name) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.parse(name); } }
        Hide
        Alexander Lehmann added a comment - - edited

        the easiest way to fix this would be to add outcome.value.toString() so that freemarker doesn't handle the Date conversion.

        Not sure if this is the smartest way, though

        Show
        Alexander Lehmann added a comment - - edited the easiest way to fix this would be to add outcome.value.toString() so that freemarker doesn't handle the Date conversion. Not sure if this is the smartest way, though
        Hide
        Alexander Lehmann added a comment -

        toString() changes the display of other types as well, so this may not be the best solution (e.g. floats get displayed with xxx.0)

        Show
        Alexander Lehmann added a comment - toString() changes the display of other types as well, so this may not be the best solution (e.g. floats get displayed with xxx.0)
        Hide
        Ghislain Nadeau added a comment -

        i think the right solution is to produce a valid .ftl file that includes a default ?datetime format for dates, which could be customizable in the OutcomesTable

        Show
        Ghislain Nadeau added a comment - i think the right solution is to produce a valid .ftl file that includes a default ?datetime format for dates, which could be customizable in the OutcomesTable
        Hide
        Mauro Talevi added a comment -

        I agree, freemarker template should detect date object values and render them appropriately.

        Show
        Mauro Talevi added a comment - I agree, freemarker template should detect date object values and render them appropriately.
        Mauro Talevi made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Assignee Mauro Talevi [ maurotalevi ]
        Resolution Fixed [ 1 ]
        Hide
        Ghislain Nadeau added a comment -

        Thanks for the quick fix!

        It seems that the test you modified makes the build to fail if my system is in another language.
        Since you compare xml files generated with an expected one, and that the default system date converter is used, the text shall not be the same on all developpers systems;

        Your output:

        <value>A wrong date</value><value>Sat Jan 01 12:00:00 CET 2011</value><value>&lt;Sun Jan 02 00:00:00 CET 2011&gt;</value><value>No</value>
        

        My output (french)

        <value>A wrong date</value><value>sam. janv. 01 12:00:00 EST 2011</value><value>&lt;Sun Jan 02 00:00:00 EST 2011&gt;</value><value>No</value>
        
        Show
        Ghislain Nadeau added a comment - Thanks for the quick fix! It seems that the test you modified makes the build to fail if my system is in another language. Since you compare xml files generated with an expected one, and that the default system date converter is used, the text shall not be the same on all developpers systems; Your output: <value>A wrong date</value><value>Sat Jan 01 12:00:00 CET 2011</value><value>&lt;Sun Jan 02 00:00:00 CET 2011&gt;</value><value>No</value> My output (french) <value>A wrong date</value><value>sam. janv. 01 12:00:00 EST 2011</value><value>&lt;Sun Jan 02 00:00:00 EST 2011&gt;</value><value>No</value>
        Hide
        Mauro Talevi added a comment -

        Fixed unit tests to use locale-independent formats. Please pull latest and try building.

        Show
        Mauro Talevi added a comment - Fixed unit tests to use locale-independent formats. Please pull latest and try building.
        Mauro Talevi made changes -
        Fix Version/s 3.7 [ 18390 ]

          People

          • Assignee:
            Mauro Talevi
            Reporter:
            Ghislain Nadeau
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: