Return original exception to the client instead of returning CamelExecutionException Apache Camel - exception

I have a camel context defined inside an XML based spring context file.
There is one route, which is being invoked by the SOAP(XML) web service client bean.
While calling the route, it throws some exception and the client receives Camel Exception, instead of the original exception.
Camel response to the client on exception is shown below
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Exception occurred during execution on the exchange: Exchange[ID-CZC4101XJV-53724-1497351782614-9-2]</faultstring>
</soap:Fault>
Expected response should be the original exception message on
any exception
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>blah blah blah Number Not valid, I am the original exception</faultstring>
</soap:Fault>
Here is my camel route definition
<route>
<from uri="direct:remove" />
<to uri="bean:removeBean?method=validationNubmer" />
<to uri="bean:removeBean?method=checkBusiness" />
<to uri="bean:removeBean?method=triggerRemove" />
</route>
And below the SOAP bean operation which sends an XML request to the
route
public void removeMe(String id) {
RemoveRequest request = new RemoveRequest();
request.setId(id);
producer.requestBody("direct:remove", request);
}
I read the exception clause topic from the Apache Camel documentation, but I couldn't find any information on how to return the original exception to the client, sad!! any help?
I tried using camel onException but no luck :(
<onException>
<exception>java.lang.Exception</exception>
<redeliveryPolicy maximumRedeliveries="0" />
<handled>
<constant>true</constant>
</handled>
<transform>
<simple>Error Occurred: ${exception.message}</simple>
</transform>
</onException>

You can turn on handleFault to let exceptions automatic be transformed to SOAP faults. See Camel in Action 2 book, chapter 11, which has a little example: https://github.com/camelinaction/camelinaction2/tree/master/chapter11/errorhandler#1136---handling-faults
Or you need to use <setFaultBody> instead of <transform> to tell Camel you are setting the message body as a SOAP fault.

Related

exception handling in apache servicemix

I am new to ServiceMix am trying on exception handling in ServiceMix.
when I try to print the exception, it also contains the body of the request in it. Is there any way that I can extract only the errors from exception?
<from uri="activemq:topic://topic1"/>
<!-- Schema validationm for the request received from Biblio -->
<doTry>
<to uri="validator:http://localhost/employee.xsd"/>
<doCatch>
<exception>java.lang.Exception</exception>
<log message="${exception.message}"/>
</doCatch>
</doTry>
below is the logged exception:
org.apache.xerces.jaxp.validation.SimpleXMLSchema#a0059b5
errors: [
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'asd' is not a valid value for 'integer'., Line : -1, Column : -1
org.xml.sax.SAXParseException: cvc-type.3.1.3: The value 'asd' of element 'empnumber' is not valid., Line : -1, Column : -1
]. Exchange[ID-GBSMIXDEV01-uk-oup-com-46713-1511957485149-83-2][Message: <empRecord>
<employee>
<empnumber>asd</empnumber>
<surname>PM</surname>
<firstname>Abhinay</firstname>
</employee>
</empRecord>]
I am getting the correct exception but I dont want the below part in the exception.
Is there any way I can remove these from the exception message?
Exchange[ID-GBSMIXDEV01-uk-oup-com-46713-1511957485149-83-2][Message: <empRecord>
<employee>
<empnumber>asd</empnumber>
<surname>PM</surname>
<firstname>Abhinay</firstname>
</employee>
</empRecord>]
That message is coming from the exception, so you can manipulate the string inside a Processor.
Write a simple class to do this:
private static final Logger logger_ = LoggerFactory
.getLogger(ExceptionMsgProcessor.class);
public void process(Exchange exchange) {
Exception e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
String msg = e.getMessage();
// manipulate the string here
log.info("Exception message: {}", msg);
}
And then send the Exception to this bean
<doTry>
<to uri="validator:http://localhost/employee.xsd"/>
<doCatch>
<exception>java.lang.Exception</exception>
<to uri="bean:exceptionMsgProcessor" />
</doCatch>
</doTry>

Modify the handled exception fault message in Apache camel

In my camel route, I am making a direct-vm call to an existing bundle. In that service, they have handled the exception and setting up some custom fault message. When any exception occurs in that service they are sending fault message like below.
{
"errorCode": "400",
"errorMessage": "Unknown error"
}
But I need to form my own custom fault message based on the fault message received. But once an exception occurs in second bundle, i am not able to recive the fault message and modify it. below is how my route looks.
<route handleFault="true" streamCache="true" id="route1">
<from uri="cxfrs://bean://testCxf?synchronous=true"/>
<log message="The consumer message ${body}"/>
<bean ref="requestValidator" method="validateRequest"/>
<to uri="direct-vm:retrieveData"/>
<bean ref="validateResponse" method="validate"/>//need to manipulate the fault message coming from bundle 2 in this bean.
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<bean ref="faultMapper" method="mapFault"/>
</onException>
</route>
Below is the existing direct:vm route.
<route handleFault="true" streamCache="true" id="route2">
<from uri="direct-vm:retrieveData"/>
<bean ref="manipulateData" method"manipulate"/>
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<bean ref="faultMapper1" method="mapFault1"/>
</onException>
</route>
i need to intercept the fault that is mapped in the class faultmapper1, in my route1 after the direct-vm call.How to acheive this?. I will not be allowed to change anything in the existing 2nd bundle. Thanks in advance.
After some research found that this is not possible. To achieve the requirement, I have made the handled constant as false in the second route and added a , block in the first route. So that I can catch the exception thrown and handled it with some custom fault mapping.

How to log exceptions with network targets in NLog

I am using the NLog logging framework and am trying to get exception and stacktrace information showing up in any UDP logger appliaction, such as Sentinel and Log2Console, but can only get the log message part displayed. Outputting to a file works well as most examples do just that, so the problem revolves around using network targets with NLog.
Bonus if a custom format can be applied on inner exceptions and stacktrace, but this is not required. Exception.ToString() would go a long way.
Note on the example code: With Log2Console I found an article on how to send exception as a separate log entry. Although this worked, I was not happy with the solution.
Example exception logging code:
Logger Log = LogManager.GetCurrentClassLogger();
try
{
throw new InvalidOperationException("My ex", new FileNotFoundException("My inner ex1", new AccessViolationException("Innermost ex")));
}
catch (Exception e)
{
Log.ErrorException("TEST", e);
}
Example NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets async="true">
<!-- Send by UDP to Sentinel with NLogViewer protocol -->
<target name="network" xsi:type="NLogViewer" address="udp://192.168.1.3:9999" layout="${message}${onexception:inner=${newline}${exception:format=tostring}}" />
<!-- Send message by UDP to Log2Console with Chainsaw protocol -->
<target name="network2" xsi:type="Chainsaw" address="udp://192.168.1.3:9998" appinfo="Grocelist"/>
<!-- Send exception/stacktrace by UDP to Log2Console with generic network protocol -->
<target name="network2ex" xsi:type="Network" address="udp4://192.168.1.3:9998" layout="${exception:format=ToString}" />
<target name="logfile" xsi:type="File" layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=tostring}"
createDirs="true"
fileName="${basedir}/logs/${shortdate}.log"
/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
<logger name="*" minlevel="Debug" writeTo="network" />
<logger name="*" minlevel="Debug" writeTo="network2" />
<logger name="*" minlevel="Warn" writeTo="network2ex" />
</rules>
</nlog>
Some links:
http://nlog-project.org
http://nlog-project.org/wiki/Targets
http://nlog-project.org/wiki/Exception_layout_renderer
http://nlog-project.org/2011/04/20/exception-logging-enhancements.html
http://nlog-project.org/wiki/How_to_properly_log_exceptions%3F
How to tell NLog to log exceptions?
https://stackoverflow.com/a/9684111/134761
http://nlog-forum.1685105.n2.nabble.com/How-to-send-stacktrace-of-exceptions-to-Chainsaw-or-Log2Console-td5465045.html
Edit:
After searching some more this seems to be a limitation on NLog's end. A recent patch is apparently out there: log4jxmlevent does not render Exception
Edit2:
I rebuilt NLog with patch, but it did not seem to help in Sentinel or Log2Console apps. I might have to try log4net to make sure those apps really do support what I am trying to achieve.
Edit3:
I currently use string.Format() to join and format message and exception text myself. This works well, but is not what I'm looking for here.
You can also extend NLog to include exceptions for network logging.
Create an extended layout:
[Layout("Log4JXmlEventLayoutEx")]
public class Log4JXmlEventLayoutEx : Log4JXmlEventLayout
{
protected override string GetFormattedMessage(LogEventInfo logEvent)
{
string msg = logEvent.Message + " ${exception:format=Message,Type,ToString,StackTrace}";
msg = SimpleLayout.Evaluate(msg, logEvent);
LogEventInfo updatedInfo;
if (msg == logEvent.Message) {
updatedInfo = logEvent;
} else {
updatedInfo = new LogEventInfo(
logEvent.Level, logEvent.LoggerName,
logEvent.FormatProvider, msg,
logEvent.Parameters, logEvent.Exception);
}
return base.GetFormattedMessage(updatedInfo);
}
}
Create a target that uses that layout
[Target("NLogViewerEx")]
public class NLogViewerTargetEx : NLogViewerTarget
{
private readonly Log4JXmlEventLayoutEx layout = new Log4JXmlEventLayoutEx();
public override Layout Layout { get { return layout; } set {} }
}
Update NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<extensions>
<add assembly="Assembly.Name.That.Contains.Extended.Target"/>
</extensions>
<targets>
<target name="logViewer"
xsi:type="NLogViewerEx"
address="udp://localhost:7071">
</targets>
...
</nlog>
A few years later and this is pretty trivial, try adding
includeSourceInfo="true"
to your target file, so it looks like;
<target name="viewer"
xsi:type="NLogViewer"
includeSourceInfo="true"
address="udp://127.0.0.1:9999" />
Gives you Source File, Line, Class and Method info.
I had this problem, and just updated my NLog nuget package to 2.0.1.2
Now I have exceptions coming through to Log2Console just fine.
Have you tried the latest developer snapshot of Chainsaw? It will display stack traces and supports log4net/UDP appenders, and according to NLog you can use it as well:
http://nlog-project.org/wiki/Chainsaw_target
Try the latest developer snapshot, has a ton of features: http://people.apache.org/~sdeboy
Just download and build the latest (NLog-Build-2.0.0.2007-0-g72f6495) sources from GitHub: https://github.com/jkowalski/NLog/tree/
This issue is fixed there by NLog developer.
In your NLog.config modify the target like the following.
<target name="file" xsi:type="File" fileName="log.txt" layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}" />
The part that you are looking for is
${exception:format=message,stacktrace:separator=*}
For more information on this look here.

Struts2 Application hides my exceptions after adding Interceptor

So I have a Struts2 application that I'm working on. On my front page I have a section that will display any exceptions my application throws. This worked well until I added a custom Interceptor.
Here is my interceptor code:
public String intercept(ActionInvocation actionInvocation) throws Exception {
String result = actionInvocation.invoke();
return result;
}
This is the code in my Action class where the exception gets generated, it occurs where AuthService.Authorize() is called:
if(AuthService.Authorize(username, password)) {
if(AuthService.AdminAuthorized()) {
return "admin";
}
return SUCCESS;
}
This is inside of AuthService.Authorize(), it throws a null point exception when acc is accessed :
try {
acc = profileRepository.WhereSingle("Username", "=", username);
} catch (Exception e) {
return false;
}
if (acc.Password.equals(password)) {
However, when the page is loaded. This is not populated:
<s:property value="%{exception.message}"/>
I have tested it and it would work if I was simply throwing an exception from the Action class. I am not calling a redirectAction or anything
Here is the top of my default package definition which all my other packages extend
<package name="default" namespace="/" extends="struts-default">
<!-- Interceptors -->
<interceptors>
<interceptor name="conversation" class="global.ConversationInterceptor"/>
<interceptor-stack name="dils-stack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="conversation"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="dils-stack"/>
<global-results>
<result name="Exception" >/index.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="Exception"/>
<exception-mapping exception="java.lang.NullPointerException" result="Exception"/>
</global-exception-mappings>
How is your interceptor stack defined for that action? The ExceptionMappingInterceptor should be defined first in the stack. Can you post the interceptor stack configuration from your struts.xml? Your custom interceptor should not be interfering (it does nothing).
Updated:
I was able to reproduce this issue, however it occurs for me with or without your custom interceptor.
The reason is that you are specifically looking for the exception message, which is not set for NullPointerExceptions that are automatically thrown (as in your case). You can confirm this by instead displaying the stack trace, such as: %{exceptionStack}
%{exception.message} is null for the NullPointerException, and so it displays nothing. If instead you were to throw an exception with a message (e.g., throw new RuntimeException("OMG!");), then you will see the message.
Also, note that you must specify more specific exception mappings before less specific mappings in your struts.xml. Because NullPointerException is more specific than Exception, you must list it first. Note that this doesn't really matter in your example, because they map to the same thing. Just know that your NPE will map to the first entry, not the second.

Filter on exception text in elmah

Is there a way to filter exceptions in elma using the exception message?
Examples:
"System.Web.HttpException: Request timed out." I don't want to filter out all HttpException, but only the timed-out requests.
"System.Web.HttpException: Maximum request length exceeded."
What I don't want to do is write own code for that. So is it possible to do this with the buildin-web.config configuration?
Thank you!
Yes you can. Just use a regular expression to interrogate the message. See the example below for details on how to compare the exception message.
<errorFilter>
<test>
<!-- http://groups.google.com/group/elmah/t/cbe82cee76cc6321 -->
<and>
<is-type binding='Exception'
type='System.Web.HttpException, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' />
<regex binding='Exception.Message'
pattern='invalid\s+viewstate'
caseSensitive='false' />
<regex binding='Context.Request.UserAgent'
pattern='Trident/4(\.[0-9])*'
caseSensitive='false' />
</and>
</test>
</errorFilter>
You can set up an event handler in your global.asax to avoid ugly configuration regex settings:
void ErrorMail_Filtering(object sender, Elmah.ExceptionFilterEventArgs e)
{
if (e.Exception.Message.Contains("Request timed out"))
e.Dismiss();
}
See Error Filtering.