You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Matt Raible <ma...@raibledesigns.com> on 2014/05/22 17:41:34 UTC

Email Error on Route Exception

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

Re: Email Error on Route Exception

Posted by Claus Ibsen <cl...@gmail.com>.
On Fri, May 23, 2014 at 4:27 PM, Matt Raible <ma...@raibledesigns.com> wrote:
> That worked - thanks!
>
> .setHeader("subject", simple("Message Broker Error ({{ESB_ENV}}) - ${exception.class.simpleName}"))
> .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=${headers.subject})");
>

Well what you are trying to do is a dynamic to
http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html

Which you should really use the recipient list eip with an expression
that define the dynamic uri.

But its better to use a static uri, and then provide subject, to, and
what else is dynamic for the mailer, as headers, as this allows Camel
to reuse the same endpoint.

Otherwise with dynamic to, its a new endpoint per different
combination that would yield. And that could potential lead to more
resources used by Camel.

So for some Camel components its better to reuse same base endpoint.
And provide the dynamic details as headers. eg which you would do in
emails as the content is body + headers. And you send that to the same
mail sender (eg camel endpoint).

So btw it only worked above because you named the header subject,
which is what the email sender supports.

eg if you called the header, foobar
.setHeader("foobar", simple("Message Broker Error ({{ESB_ENV}}) -

And then &subject=${headers. foobar})") then that ought to not work.






> On May 23, 2014, at 8:08 AM, Claus Ibsen <cl...@gmail.com> wrote:
>
>> You can set the subject as a header, then the smtp will use that
>>
>> Something like this (not wrote the code in this email)
>> .setHeader("subject", simple("Message Broker Error
>> ${exception.getClassName()}"))
>>
>> On Fri, May 23, 2014 at 3:45 PM, Matt Raible <ma...@raibledesigns.com> wrote:
>>> 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 <cl...@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 <ch...@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 <ma...@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 <ma...@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/
>>>
>>
>>
>>
>> --
>> 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/
>



-- 
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/

Re: Email Error on Route Exception

Posted by Matt Raible <ma...@raibledesigns.com>.
That worked - thanks!

.setHeader("subject", simple("Message Broker Error ({{ESB_ENV}}) - ${exception.class.simpleName}"))
.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=${headers.subject})");

On May 23, 2014, at 8:08 AM, Claus Ibsen <cl...@gmail.com> wrote:

> You can set the subject as a header, then the smtp will use that
> 
> Something like this (not wrote the code in this email)
> .setHeader("subject", simple("Message Broker Error
> ${exception.getClassName()}"))
> 
> On Fri, May 23, 2014 at 3:45 PM, Matt Raible <ma...@raibledesigns.com> wrote:
>> 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 <cl...@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 <ch...@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 <ma...@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 <ma...@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/
>> 
> 
> 
> 
> -- 
> 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/


Re: Email Error on Route Exception

Posted by Claus Ibsen <cl...@gmail.com>.
You can set the subject as a header, then the smtp will use that

Something like this (not wrote the code in this email)
.setHeader("subject", simple("Message Broker Error
${exception.getClassName()}"))

On Fri, May 23, 2014 at 3:45 PM, Matt Raible <ma...@raibledesigns.com> wrote:
> 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 <cl...@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 <ch...@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 <ma...@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 <ma...@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/
>



-- 
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/

Re: Email Error on Route Exception

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <cl...@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 <ch...@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 <ma...@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 <ma...@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/


Re: Email Error on Route Exception

Posted by Claus Ibsen <cl...@gmail.com>.
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 <ch...@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 <ma...@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 <ma...@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/

Re: Email Error on Route Exception

Posted by Charles Moulliard <ch...@gmail.com>.
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 <ma...@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 <ma...@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

Re: Email Error on Route Exception

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <ma...@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