0

I have a problem with camel route using IMAP.

from("imap://mail.server?username=aaa&password=zzz&copyTo=out&delete=true&unseen=false&folderName=in&mapMailMessage=false")
.tracing()
.setHeader("copyTo", simple("works"))
.bean(MyTest.class, "setBodyWithHardcodedJson")
.unmarshal(new JacksonDataFormat(Reply.class))
.log("copyTo=${header[copyTo]}")

The call to setBodyWithHardcodedJson override the body with a valid json, the unmarshall is done correctly.

The last instruction prints me null value. (My header is lost between the unmarshall and the log steps)

I tried the same route, but replacing the from(imap) with a from(direct) and send something from unit test. The last instruction prints me "works" value, as expected.

Please, can somebody explain me why the exchange loose the headers i set by code when i start the route with a mail ?

EDIT : Here is a reduced version of my code to show the problem.

public class MyTest extends CamelTestSupport {
@Test
public void testInjectRequest() throws Exception {
    //just here to start the route and wait result...
    String response = "x";
    MockEndpoint mock = getMockEndpoint("mock:result");
    mock.expectedMessageCount(1);
    template.sendBody("direct:start", response);
    assertMockEndpointsSatisfied();
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            // activate next line to start with direct -> works
            //from("direct:start")
            // activate next line to start with mail : test fails (not important) 
            // BUT PROBLEM : different result of .log("copyTo=${header[copyTo]}")
            from("imap://server?username=aaa&password=bbb&copyTo=out&delete=true&unseen=false&folderName=in&mapMailMessage=false")
                .tracing()
                     .onException(Exception.class)
                     .log("exception here ${exception.message}")
                .end()
                .setHeader("copyTo", simple("works"))
                .bean(MyTest.class, "hardcodeJson")
                .unmarshal(new JacksonDataFormat(Reply.class))
                .log("body=${body.id}")
                .log("copyTo=${header[copyTo]}")
            ;
        }
    };
}
protected void hardcodeJson(Exchange exchange) {
    String jsonInputString = "{\n" +
            "   \"id\": \"Corresp_Rest:3e9a525d-fc64-\"\n" +
            "}";
    exchange.getIn().setBody(jsonInputString);
}
}

public class Reply {
String id;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}
}

Info following questions from @kladderradatsch

in the traces i find :

INFO  route1 - body=Corresp_Rest:3e9a525d-fc64-
INFO  route1 - copyTo=

if i do it with from(direct) i have

INFO  route1 - body=Corresp_Rest:3e9a525d-fc64-
INFO  route1 - copyTo=works

I hardcoded the json body in the bean to be sure it should unmarshal the same way, independent of the from().

After the unmarshal, the body is a Reply object with the content OK, but the headers modified are resetted only on from("imap"), not on from("direct").

Maybe i'm wrong, but i imagine the unmarshall provoques something in camel-mail to recreate the exchange from original message, losing the changes in headers made by my code...

Seazor
  • 1
  • 2
  • You have a discrepancy between your real imap email and your contrived email in your test. The deserialization/unmarshalling causes an exception so it doesn't reach the log node. Fix your unmarshalling or handle the exceptions/errors accordingly so the exchange goes to the next node. – kladderradatsch Oct 04 '22 at 14:09
  • Read about Camel's Error Handler: https://camel.apache.org/manual/error-handler.html – kladderradatsch Oct 04 '22 at 14:14
  • It goes to the next node. All the process in the rest of the route is executing OK, BUT the content of headers modified during the beginning of the route are resetted/lost. – Seazor Oct 04 '22 at 14:22
  • I do not know your error handler but the default error handler is configured with these settings, according to the book Camel in Action: No redelivery, Exceptions are propagated back to the caller – kladderradatsch Oct 04 '22 at 14:36
  • added `.onException(Exception.class).log("exception here ${exception.message}").end()` after .tracing, not found this line in console. No evidence of an Exception when executing this route. – Seazor Oct 04 '22 at 16:26
  • Can you debug what's going on in `.bean()`and `.unmarshal()` while the imap message flows through the route? – kladderradatsch Oct 04 '22 at 17:47
  • No exception. I used `isUseDebugger() return true` to print `.getHeader("copyTo", "null")` before & after each steps... `Before SetHeader[copyTo, simple{works}],copyTo ? null After SetHeader[copyTo, simple{works}],copyTo ? works Before Bean[],copyTo ? works After Bean[],copyTo ? works Before Unmarshal[],copyTo ? works After Unmarshal[],copyTo ? works Before Log[copyTo=${header[copyTo]}],copyTo ? null` It's lost between the unmarshall and the log, where it's not my code. – Seazor Oct 05 '22 at 08:18
  • It would be more revealing if you could post your source code of `MyTest.java`, `JacksonDataFormat.jar` and `Reply.java`. – kladderradatsch Oct 05 '22 at 12:18
  • `isUseDebugger()` reveals that your are debugging your unit test. I suggested to debug the real imap message because this is the issue here. You can do this via remote debugging. – kladderradatsch Oct 05 '22 at 13:26
  • Modified question to add code sample. – Seazor Oct 06 '22 at 08:48
  • Let run your route with `imap` but retain `.bean(MyTest.class, "hardcodeJson")` in your route. When this works, then you know the reason to loose your headers lies in the body/payload emanates from the `imap` producer. – kladderradatsch Oct 06 '22 at 10:35
  • If i run with IMAP and comment the unmarshal, the header remains, and the mail is copied in the subfolder as expected. I'll try, but i'm not confortable enough to debug camel-mail.jar... I think i'll post this to Camel team mailing list. (maybe a bug report ?) – Seazor Oct 06 '22 at 13:26
  • There is no bug in `imap` (camel-mail.jar) otherwise the route would fail immediately. The issue is in the *unmarshal* process, i.e. the message/body must be different than `{"id": "any930904id"}` so it cannot be mapped/unmarshalled/deserialized to `Reply.class`. Why do you cannot debug the message/body/payload when `imap` is in use? – kladderradatsch Oct 06 '22 at 18:28
  • added some infos in question – Seazor Oct 07 '22 at 05:33
  • When the message/exchange leaves `.from("imap:...")` then it has no further influence of the subsequent flow which is taken over by the other components. However, I see that you have called the header `copyTo` but `copyTo` is also an option of the component. Hence rename your header in your route so it doesn't clash with any option of the mail component. https://camel.apache.org/components/3.18.x/mail-component.html – kladderradatsch Oct 07 '22 at 20:25

1 Answers1

0

Rename your header copyTo to any other name because copyTo is an option of the imap: component so this clashes.

kladderradatsch
  • 596
  • 5
  • 18
  • But i want to use copyTo for what the option does ! In my complete work, i want to override the destination of copyTo as it's expected, but after the unmarshal, the value is lost. What i have recently found is that it works corectly without mapMailMessage in the from(imap), but if i remove it, i'll have to refactor all my parsing of the mail in the bean, because if i do that, Camel doesn't give the mail with the way... – Seazor Oct 08 '22 at 15:36
  • I see, then open a ticket that `copyTo` doesn't work: https://issues.apache.org/jira/browse/CAMEL-5159?jql=project%20%3D%20CAMEL%20AND%20text%20~%20%22copyTo%22 – kladderradatsch Oct 08 '22 at 17:05