camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Matt Raible <m...@raibledesigns.com>
Subject Re: Email Error on Route Exception
Date Fri, 23 May 2014 13:45:18 GMT
I was able to figure out how to set headers and retrieve those variables in the FreeMarker
template. However, I'm still unable to access them in the SMTP endpoint. Also, if I set the
"exception", I can't call ${exception.stacktrace} in FreeMarker like I can in a simple transform.
Here's what I have now.

.setHeader("routeId", property(Exchange.FAILURE_ROUTE_ID))
.setHeader("endpoint", property(Exchange.FAILURE_ENDPOINT))
.setHeader("exception", property(Exchange.EXCEPTION_CAUGHT))
.transform(simple("${exception.message}\n\nStacktrace Details:\n\n${exception.stacktrace}"))
.to("freemarker:/templates/mail/error.ftl")
.to("smtp://{{mail.host}}?contentType=text/plain&to={{ESB_ALERT_EMAIL}}" +
		"&from={{mail.from}}&subject=Message Broker Error ({{ESB_ENV}} - ${exception.className})");

The main thing I'd like to change is to send the Exception class name in the subject. Currently,
it prints:

Message Broker Error (mraible - ${exception.className})

On May 23, 2014, at 12:53 AM, Claus Ibsen <claus.ibsen@gmail.com> wrote:

> Hi
> 
> Yeah a good idea is to check the unit tests for camel-freemarker for examples.
> 
> Also take a note that Camel stores various information from the
> Exchange etc. and provides that to freemarker in the process method.
> https://github.com/apache/camel/blob/master/components/camel-freemarker/src/main/java/org/apache/camel/component/freemarker/FreemarkerEndpoint.java#L122
> 
> eg that is what we say on the page, at the section _freemarker context_
> http://camel.apache.org/freemarker
> 
> So I would assume you can use the freemarker syntax to access those
> and retrieve the caused exception, headers, and what else you need.
> 
> On Fri, May 23, 2014 at 8:21 AM, Charles Moulliard <ch007m@gmail.com> wrote:
>> Matt,
>> 
>> You ca retrieve using ${body} and ${headers.xxxx} within the freemarker
>> template (
>> https://github.com/apache/camel/blob/master/components/camel-freemarker/src/test/resources/org/apache/camel/component/freemarker/letterWithoutHeader.ftl#L21)
>> the content of your body or headers/properties like also fields of an
>> object (
>> https://github.com/apache/camel/blob/master/components/camel-freemarker/src/test/resources/org/apache/camel/component/freemarker/BodyAsDomainObject.ftl#L19
>> ).
>> 
>> Have you try this syntax --> ${headers.operationName} ?
>> 
>> Regards,
>> 
>> Charles
>> 
>> 
>> On Thu, May 22, 2014 at 10:12 PM, Matt Raible <matt@raibledesigns.com>wrote:
>> 
>>> I figured out a solution for this. First of all, I changed my route to be
>>> a Spring bean so dependency injection would work:
>>> 
>>> @Component
>>> public class FooRoute extends RouteBuilder {
>>> }
>>> 
>>> Then I changed my Camel configuration to use Spring annotations and
>>> @ComponentScan. I also configured things so properties from my Spring
>>> property placeholder would be available to Camel.
>>> 
>>> @Configuration
>>> @ImportResource("classpath:META-INF/cxf/cxf.xml")
>>> @ComponentScan("com.foo.app")
>>> public class CamelConfig extends CamelConfiguration {
>>> 
>>>        @Override
>>>        protected void setupCamelContext(CamelContext camelContext) throws
>>> Exception {
>>>                PropertiesComponent pc = new PropertiesComponent();
>>>                pc.setLocation("classpath:application.properties");
>>>                camelContext.addComponent("properties", pc);
>>>                super.setupCamelContext(camelContext);
>>>        }
>>> }
>>> 
>>> That was enough to solve the problem below. However, I figured I'd take it
>>> a step further and use Camel to send the email instead of my own Spring
>>> bean.
>>> 
>>>                onException(Exception.class)
>>>                                .transform(simple("There was a problem due
>>> ${exception.message} and the \n" +
>>>                                                "stracktrace is
>>> ${exception.stacktrace}"))
>>> 
>>> .to("smtp://{{mail.host}}?contentType=text/plain&to={{mail.to}}" +
>>> 
>>> "&from={{mail.from}}&subject=Message Broker Error");
>>> 
>>> This worked, until I wanted to add a corporate disclaimer in the footer.
>>> For this, I turned to FreeMarker. It seems I still need the transform if I
>>> want to get the stacktrace as I was unable to get it from the exception in
>>> FreeMarker.
>>> 
>>>                onException(Exception.class)
>>> 
>>> .transform(simple("${exception.stacktrace}"))
>>>                                .to("freemarker:/error.ftl")
>>> 
>>> .to("smtp://{{mail.host}}?contentType=text/plain&to={{ESB_ALERT_EMAIL}}"
+
>>> 
>>> "&from={{mail.from}}&subject=Message Broker Error ({{ESB_ENV}})");
>>> 
>>> In error.ftl, I have:
>>> 
>>> ----
>>> <#assign exception = exchange.properties.CamelExceptionCaught>
>>> ${exception.message}
>>> 
>>> Stacktrace Details:
>>> 
>>> ${body}
>>> 
>>> For full trace of input message and exceptions, please check the Message
>>> Broker Logs.
>>> 
>>> IMPORTANT CONFIDENTIALITY NOTICE
>>> 
>>> Lots of corporate legal-eze here.
>>> ----
>>> 
>>> The only thing I'd like to know now is if it's possible to get the
>>> serviceName and operationName to put in the subject. I tried
>>> ${header.operationName}, but it just prints the raw value. The application
>>> I'm trying to replace had a number of system properties included in the
>>> email as well, so I'd be interested in knowing how to include those in the
>>> FreeMarker template too.
>>> 
>>> Thanks,
>>> 
>>> Matt
>>> 
>>> On May 22, 2014, at 9:41 AM, Matt Raible <matt@raibledesigns.com> wrote:
>>> 
>>>> Hello all,
>>>> 
>>>> I'm getting up to speed on Apache Camel and trying to replace a "message
>>> flow" that was originally written for IBM Message Broker 6.1. The flow
>>> involves receiving input from a SOAP service, looking up a value in a
>>> database, and returning that to the client (again, via SOAP). I have a
>>> route that works and now I'm trying to add exception handling to it.
>>> Ideally, an email can be generated when an exception occurs.
>>>> 
>>>> Here's my Route:
>>>> 
>>>> public class FooRoute extends RouteBuilder {
>>>> 
>>>>      private String uri = "cxf:/foo?serviceClass=" +
>>> FooService.class.getName();
>>>> 
>>>>      private Log log = LogFactory.getLog(FooRoute.class);
>>>> 
>>>>      @Autowired
>>>>      private MailSender mailSender;
>>>> 
>>>>      @Autowired
>>>>      private SimpleMailMessage mailMessage;
>>>> 
>>>>      @Override
>>>>      public void configure() throws Exception {
>>>>              onException(Exception.class)
>>>>                              .process(new Processor() {
>>>>                                      public void process(Exchange
>>> exchange) throws Exception {
>>>>                                              Exception exception =
>>> (Exception) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
>>>>                                              // email error
>>>>                                              mailMessage.setTo("
>>> mraible@apache.org");
>>>> 
>>> mailMessage.setSubject("ERROR!!");
>>>> 
>>> mailMessage.setText("WTF?!\n\n " + exception.getMessage());
>>>> 
>>> mailSender.send(mailMessage);
>>>>                                      }
>>>>                              });
>>>>              from(uri)
>>>>                              .to("log:input")
>>>>                                              // send the request to the
>>> route to handle the operation
>>>>                                              // the name of the
>>> operation is in that header
>>>> 
>>> .recipientList(simple("direct:${header.operationName}"));
>>>>              from("direct:findById")
>>>>                              .process(new Processor() {
>>>>                                      public void process(Exchange
>>> exchange) throws Exception {
>>>>                                              // get the id from the
>>> input
>>>>                                              String id =
>>> exchange.getIn().getBody(FooRequest.class).getId();
>>>> 
>>> exchange.getOut().setBody(id);
>>>>                                      }
>>>>                              })
>>>>                              .to("sql:select value from table where id
>>> = #?dataSource=ds")
>>>>                              .to("log:output")
>>>>                              .process(new Processor() {
>>>>                                      public void process(Exchange
>>> exchange) throws Exception {
>>>>                                              // get the value from the
>>> input
>>>>                                              List<HashMap> data =
>>> (ArrayList<HashMap>) exchange.getIn().getBody();
>>>>                                              // todo: handle value is
>>> empty
>>>>                                              FooResponse response = new
>>> FooResponse();
>>>> 
>>> response.setGpi(String.valueOf(data.get(0).get("value")));
>>>> 
>>> exchange.getOut().setBody(response);
>>>>                                      }
>>>>                              }).end();
>>>>      }
>>>> }
>>>> 
>>>> The problem that I'm experiencing is that the Autowired dependencies
>>> from Spring are not getting set. Do I need to do something special to allow
>>> Spring dependencies in my route or is there an easier way to send exception
>>> emails?
>>>> 
>>>> Here's how I have my routes configured using Spring's JavaConfig:
>>>> 
>>>> @Configuration
>>>> @ImportResource("classpath:META-INF/cxf/cxf.xml")
>>>> public class CamelConfig extends CamelConfiguration implements
>>> InitializingBean {
>>>> 
>>>>      /**
>>>>       * Returns the CamelContext which support Spring
>>>>       */
>>>>      @Override
>>>>      protected CamelContext createCamelContext() throws Exception {
>>>>              return new SpringCamelContext(getApplicationContext());
>>>>      }
>>>> 
>>>>      @Override
>>>>      public List<RouteBuilder> routes() {
>>>>              List<RouteBuilder> routes = new ArrayList<>();
>>>>              routes.add(new FooRoute());
>>>>              return routes;
>>>>      }
>>>> 
>>>>      public void afterPropertiesSet() throws Exception {}
>>>> }
>>>> 
>>>> Thanks,
>>>> 
>>>> Matt
>>> 
>>> 
>> 
>> 
>> --
>> Charles Moulliard
>> Apache Committer / Architect @RedHat
>> Twitter : @cmoulliard | Blog :  http://cmoulliard.github.io
> 
> 
> 
> -- 
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: cibsen@redhat.com
> Twitter: davsclaus
> Blog: http://davsclaus.com
> Author of Camel in Action: http://www.manning.com/ibsen
> hawtio: http://hawt.io/
> fabric8: http://fabric8.io/


Mime
View raw message