Error / Exception handling in AbstractBpmnActivityBehavior.signal() - bpmn

Errpr / Exception handling in AbstractBpmnActivityBehavior.signal() is not the same as in AbstractBpmnActivityBehavior.execute(). An exception being thrown in execute() is properly handled by creating an incident (task with async-before). For signal() this is not the case.
public class Example extends AbstractBpmnActivityBehavior {
#Override
public void execute(ActivityExecution execution) {
throw new RuntimeException(); // creates an incident
}
#Override
public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {
throw new RuntimeException(); // doesn't create an incident
}
}
I think the reason is that while in execute() a job exists for execution.getId() but in signal() it doesn't. This has been checked with the following query.
Context.getProcessEngineConfiguration().getManagementService().createJobQuery().executionId(execution.getId()).list()
Am I doing something wrong or is it just not possible to automatically create a failedJob incident by throwing an exception in signal()?

Related

Spring Data Redis Error handling with Repository and Cache Configurer

Can I use Spring Data Redis #Repositories, and a CachingConfigurer to implement error handling? For instance -
#Override
public CacheErrorHandler errorHandler() {
return new RedisCacheError();
}
Using the CacheConfigurer above along with the repository as defined below, note the use of CrudRepository operations.
#Repository
public interface ObjectRepository extends CrudRepository<object, String>
I notice that CrudRepository has operations such as save, wondering if that is doing a redis.add() in the background? And basically whether or not the ErrorHandler see below, will actually catch errors on the save operation.
public class RedisCacheError implements CacheErrorHandler {
#Override
public void handleCacheGetError(RuntimeException exception,
Cache cache, Object key) {
log.info("caught error in here: " + exception );
}
#Override
public void handleCachePutError(RuntimeException exception, Cache cache,
Object key, Object value) {
log.info("caught error in here: " + exception );
}
#Override
public void handleCacheEvictError(RuntimeException exception, Cache cache,
Object key) {
//Do something on error while Evict cache
}
#Override
public void handleCacheClearError(RuntimeException exception,Cache cache){
//Do something on error while clearing cache
}
}

WebApplicationException is not showing the error message

I created my custom exception class by extending WebApplicationException class of jax-rs api. I am throwing this exception on wrong inputs.
public class RestException extends WebApplicationException {
public RestException(String message, Response.Status status) {
super(message, status);
}
}
When I used above exception in my application, it is returning the status code correctly, but it is not returning the error message i set in the constructor.
If i use jersey instead of cxf, it is showing both error message and status code. Any help on this....
I get rid of the problem by changing the signature of RestException constructore like below.
public class RestException extends WebApplicationException {
public RestException(String message, Response.Status status) {
super(Response.status(status).entity(message).type(MediaType.TEXT_PLAIN).build());
}
}

Nsb for certain type of exceptions: skip SLR + ability to ignore error queue

I want to have a central place to implement exceptions handling logic for specific type of exception.
If specific exception type occurs, I'd like to be able to run one of the following depending on internal configuration:
send message to error queue immediately without further second level retries;
hide the message, not sending it to both processing queue or error queue;
I've found this topic which covers first case but not second one, as a message would be put into error queue if we return TimeSpan.MinValue:
NServiceBus error handling
So how could I implement 2nd case? better both to be be implemented in one place, one class
Prior to version 6 of NServiceBus, you could use IManageMessageFailures to manage message failures. You can handle the case of a serialization exception or - more relevant to your problem at hand - when a message can not be handled gracefully after first-level retries are attempted.
Here's how to implement a custom FaultManager that'd ignore exceptions of certain type or send failed messages with other errors back to the error queue. Note that the First-Level retires still happens and this kicks-in instead of Second-Level retry.
public class IssueOrder : ICommand
{
public bool NotFound { get; set; }
public bool HasFaulted { get; set; }
}
public class OrderHandler : IHandleMessages<IssueOrder>
{
public void Handle(IssueOrder message)
{
if(message.NotFound)
throw new OrderNotFoundException();
if(message.HasFaulted)
throw new ApplicationException();
}
}
public class OrderNotFoundException : Exception
{
}
public class CustomFaultManager : IManageMessageFailures
{
private ISendMessages sender;
private MessageForwardingInCaseOfFaultConfig config;
private BusNotifications notifications;
private static ILog Logger = LogManager.GetLogger<CustomFaultManager>();
public CustomFaultManager(ISendMessages sender, IProvideConfiguration<MessageForwardingInCaseOfFaultConfig> config)
{
this.sender = sender;
this.config = config.GetConfiguration();
}
public void SerializationFailedForMessage(TransportMessage message, Exception e)
{
}
public void ProcessingAlwaysFailsForMessage(TransportMessage message, Exception e)
{
if (e is OrderNotFoundException)
{
//Ignore the exception;
Logger.WarnFormat("OrderNotFoundException was thrown. Ignoring the message Id {0}.", message.Id);
}
else
{
//Check if you have performed enough retries, ultimately send to error queue
SendToErrorQueue(message, e);
}
}
private void SendToErrorQueue(TransportMessage message, Exception ex)
{
message.TimeToBeReceived = TimeSpan.MaxValue;
sender.Send(message, new SendOptions(config.ErrorQueue));
Logger.WarnFormat("Message {0} will was moved to the error queue.", message.Id);
}
public void Init(Address address)
{
}
}
And to register the custom FaultManager:
var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
{
c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
});
In Version 6 of NServiceBus however, the IManageMessageFailures interface is deprecated. The new Recoverability api in version 6 allows for better customization, althrough there's no direct way of ignoring/muting an exception. For that purpose you need a custom behavior in the NServiceBUs pipeline and run it in a step between one of the known steps (e.g. before a message is moved to the error queue).

Serializable exception and WCF

if i made my exception Serializable like this article from msdn , so can my exception serialized over WCF ?
Yes you can serialize exceptions and return them with WCF. I wrote an app where it was necessary for the WCF client to have the real exception that occurred on the server; not just a high level fault.
Here are the steps to implement what we have done:
1 - Declare a class EncodedException with a single string property
public class EncodedException
{
public string SerializedException {get;set;}
}
2 - On your service contract add the attribute to indicate that your service could return a FaultException exception.
[ServiceContract()]
public class MyService
{
[OperationContract]
[FaultContract(typeof(EncodedException),
ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public string Method1 ();
}
3 - In you service implementation add a try/catch in all service operations:
public void Method1()
{
try
{
// some code here
}
catch( Exception ex)
{
EncodedException encodedException = Helper.SerializeException( ex );
throw new FaulException<EncodedException>();
}
}
4 - In your client code catch the exception and unwrap it:
public void someMethod()
{
try
{
serviceClient.Method1();
}
catch( FaulException<EncodedException> ex)
{
Exception decodedException = Helper.DeserializeException( ex );
throw new decodedException();
}
}
5 - Write the Helper to serialize/deserialize the exception. If you need help with that part too, let me know.
I hope this helps.
I don't see why not, if you've successfully created an object that can be serialized over classic asmx, then it be fine in WCF.

Did i understood MsmqPoisonMessageException wrong?

If i got a service definition like this:
[PoisonErrorBehavior]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MsgQueue: IMsgQueue
{
public void ProcessMsg(CustomMsg msg)
{
throw new Exception("Test");
}
}
( where ProcessMsg is the registered method for incoming msmq-messages )
and i want to handle the exception with my error handler ( i took the code from msdn as a template for mine ):
public sealed class PoisonErrorBehaviorAttribute : Attribute, IServiceBehavior
{
MsmqPoisonMessageHandler poisonErrorHandler;
public PoisonErrorBehaviorAttribute()
{
this.poisonErrorHandler = new MsmqPoisonMessageHandler();
}
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(poisonErrorHandler);
}
}
}
class MsmqPoisonMessageHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
}
public bool HandleError(Exception error)
{
string test = error.GetType().ToString();
//
// The type of the exception is never MsmqPoisonMessageException !!!
//
MsmqPoisonMessageException poisonException = error as MsmqPoisonMessageException;
if (null != poisonException)
{
long lookupId = poisonException.MessageLookupId;
Console.WriteLine(" Poisoned message -message look up id = {0}", lookupId);
}
}
then i got the problem that the exception is never of type MsmqPoisonMessageException. I would have expected .NET to magically encapsulate my "new Exception("Test")" in a MsmqPoisonMessageException, but the exception catched in my errorhandler is always of the same type as the exception i threw.
Am i missunderstanding this whole poison message behavior? I thought if an unhandled exception was thrown by my message-handling-code then the exception would turn out to be a MsmqPoisonMessageException, because otherwise i would'nt have a chance to get the lookup-id of msg in the queue.
Thank you all.
WCF encapsulates exceptions in a fault exception.
http://msdn.microsoft.com/en-us/library/system.servicemodel.faultexception.aspx
You must also specify which exceptions are to be thrown in the Interface / Contract.
First of all, you need to be retrieving the messages inside of a transaction, otherwise they won't be put back to the queue when there is an exception thrown from your code. Add this to the ProcessMessage function:
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
Also, you need to make sure that binding is set to fault when poison messages are detected, and that the retry count and time are small enough that you'll see it in your testing.
Try these steps (using VS 2008):
Open the WCF Configuration tool for your app.config file
Select Bindings in the tree, and click "New Binding Configuration" in the tasks area
Select the binding type of your endpoint (probably netMsmqBinding or msmqIntegrationBinding)
Set the name of the new binding configuration
Set the ReceiveErrorHandling property to "Fault"
Set the ReceiveRetryCount property to 2
Set the RetryCycleDelay to "00:00:10"
Select the endpoint to your service and set the binding configuration to the name you specified in step 4.
(You will probably want different values for ReceiveRetryCount and RetryCycleDelay for your production configuration.)