简体   繁体   中英

Camel Freemarker Example - Template Returns Null

The Problem:

I am trying to run the Camel Freemarker Example from the Camel website here , so I can understand how they work together. However, I'm having a bit of trouble.

As you can see in the code below, everything is pretty much the same as what's in the documentation. I changed where the template goes, the "from" endpoint directory, and where the ftl file is. When I run the code, I get the following error:

FreeMarker template error:
The following has evaluated to null or missing:
==> headers.lastName [in template...]

Stack trace adds tips to find errors, then continues...

FTL Stack trace ("~" means nesting-related):
 - Failed at: ${headers.lastName} [in template...]

My Logic/What I've Tried:

Now, I don't understand why headers.lastName is being found null. I thought that the msg.setHeader("lastName", "Ibsen"); part was supposed to set that to Ibsen. I thought maybe I should try setting the name to msg.setHeader("headers.lastName", "Ibsen"); , but that didn't work.

After that, I am not quite sure what else to look for. I am fairly new to both Camel and Freemarker. I think that something is not getting sent during the exchange, but I'm not sure what. Can someone please explain why this isn't working?

Any advice is appreciated.

Code:

Here is the ftl:

Dear ${headers.lastName}, ${headers.firstName}

Thanks for the order of ${headers.item}.

Regards Camel Riders Bookstore
${body}

Here is the Java code:

public class FreemarkerExample  extends CamelTestSupport{

    private static Configuration cfg = null;

    static {
        cfg = new Configuration(new version("2.3.0"));
    }

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.enableHangupSupport();
        main.addRouteBuilder(new FreemarkerExample().new MyRouteBuilder());
        main.run();
    }

    private Exchange createLetter() throws IOException, TemplateException{
        Exchange exchange = context.getEndpoint("direct:a").createExchange();

        Message msg = exchange.getIn();
        msg.setHeader("firstName", "Claus");
        msg.setHeader("lastName", "Ibsen");
        msg.setHeader("item", "Camel in Action");
        msg.setBody("PS: Next beer is on me, James");

        return exchange;
    }

    @Test
    public void testFreemarkerLetter() throws Exception {
        MockEndpoint mock = getMockEndpoint("mock:result");
        mock.expectedMessageCount(1);
        mock.message(0).body().contains("Dear Ibsen, Claus");
        mock.message(0).body().contains("Thanks for the order of Camel in Action.");

        template.send("file:C:\\freemarkerExampleFile", createLetter());

        mock.assertIsSatisfied();
    }

    class MyRouteBuilder extends RouteBuilder {

        public void configure() throws Exception {
            from("file:C:\\freemarkerExampleFile\\templates")
                    .to("freemarker:file:C:\\freemarkerExampleFile\\templates\\letter.ftl")
                    .to("mock:result");
        }

    }

}

This test can't work because of the "file" consumer.

A file consumer send a GenericFile into the route as a Body, and headers like CamelFileName or CamelFileLastModified .

When you are doing :

template.send("file:C:\\freemarkerExampleFile", createLetter());

You are creating a file in the folder "freemarkerExampleFile". This file will have a generated name, and the content of the file is the body of your message (ie, "PS: Next beer is on me, James"). The headers are lost.

Then, when you are polling with from("file:C:\\\\freemarkerExampleFile") , you read each file on this folder, send a GenericFile, and apply on this GenericFile your template : it fails.

Il you want a route which take an Exchange, and write the template to a file, you can write :

CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {

  @Override
  public void configure() throws Exception {
    from("direct:test")
        .to("freemarker:classpath:/resources.fm")
        .to("file:target"); 
  }
});
context.start();

Map<String, Object> headers = new HashMap<String, Object>();
headers.put("firstName", "Claus");
//...
context.createProducerTemplate().sendBodyAndHeaders(
        "direct:test", 
        "PS: Next beer is on me, James",
        headers);

Then you can send your exchange to the endpoint "direct:test"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM