Rebus - Execute action before message is handled - log4net

Is there a way on Rebus of executing an action before the IHandleMessages.Handle is called?
Particulary I want to set a correlation id of my logs for log4net and I'm having really difficult times to get this working.
I have an activity pattern converter to get a Guid from
System.Diagnostics.Trace.CorrelationManager.ActivityId = Guid.NewGuid()
But I want to be able to set this before each handle is activated.
I'm using Autofac as container with Rebus

An easy and convenient way to achieve this would be to include the Rebus.Events package, which allows for setting up an event delegate to be invoked before each message is handled like this:
Configure.With(...)
.(...)
.Events(e =>
{
e.BeforeMessageHandled += (bus, headers, message, context, args) =>
{
// do what you want in here :)
};
});

Related

How to mock EntityBus.rxSend()

The io.vertx.reactivex.core.eventbus.EventBus.rxSend() method has the following signature:
public <T> Single<Message<T>> rxSend(String address,
Object message,
DeliveryOptions options)
What is the correct way to mock this so that it returns a Single containing a real object? The issue is that the Message class has no constructor apart from one which which takes another Message object.
So the following will compile:
Mockito.when(eventBus.rxSend(Mockito.isA(String.class),
Mockito.isA(JsonObject.class),
Mockito.isA(DeliveryOptions.class))).thenReturn(Single.just(new Message<Object>(null)));
but of course Single.just(new Message<Object>(null))does not contain a real object which can then be passed on to test the next handler in the verticle.
Thanks
like i mentioned in my comment, i don't have an answer to your immediate question, but i'd instead like to recommend a different approach to getting the results you're looking for.
mocking types that you don't own is generally discouraged for a variety of reasons. the two that resonate most with me (as i've fallen victim) are:
if the real implementation of the mocked dependency changes, the mock's behavior will not automatically reveal any forward-breaking changes.
the more mocks a test introduces, the more cognitive load the test carries. and some tests require a lot of mocks in order to work.
there are lots of articles on the topic with more detailed viewpoints and opinions. if you're interested, refer to the Mockito wiki, or just Google around.
given all that, rather than mocking EventBus, why not use an actual instance and receive real reply Messages composed by the framework? sure, strictly speaking this becomes more of an integration test than a unit test, but is closer to the type of testing you want.
here's an example snippet from a test i wrote in an existing project with some added comments. (the code refers to some non-standard types with an -"Ext" suffix, but they aren't salient to the approach).
private EventBus eventBus;
#Before
public setUp(#NotNull TestContext context) {
eventBus = Vertx.vertx().eventBus()
}
#Test
public void ping_pong_reply_test(#NotNull TestContext context) {
final Async async = context.async();
// the following is a MessageConsumer registered
// with the EventBus for this specific test.
// the reference is retained so that it can be
// "unregistered()" upon completion of this test
// so as not to affect other tests.
final MessageConsumer<JsonObject> consumer = eventBus.consumer(Ping.class.getName(), message -> {
// here is where you would otherwise place
// your mock Message generation.
MessageExt.replyAsJsonObject(message, new Pong());
});
final Ping message = new Ping();
final DeliveryOptions options = null;
// the following uses an un-mocked EventBus to
// send an event and receive a real Message reply.
// created by the consumer above.
EventBusExt.rxSendJsonObject(eventBus, message, options).subscribe(
result ->
// result.body() is JSON that conforms to
// the Pong type
consumer.unregister();
async.complete();
},
error -> {
context.fail(error);
}
);
}
i hope this at least inspires some new thinking around your problem.

Getting an event for aggregator message group expiry with Spring Integration DSL?

I have an aggregator configured via the Java DSL in a Spring Integration flow, and I want to throw an exception that goes to the global error channel when a group timeout occurs.
The discard channel is no good for me because discard messages are at the group member level, rather than for the whole group.
I've tried using the application event publisher as follows, but the publisher object doesn't seem to get invoked:
.aggregate(new Consumer<AggregatorSpec>() {
#Override
public void accept(AggregatorSpec aggregatorSpec) {
try {
aggregatorSpec
.outputProcessor(groupPublishStrategy())
.correlationStrategy(groupPublishStrategy())
.releaseStrategy(groupPublishStrategy())
.groupTimeout(groupTimeout)
.get().getT2().setApplicationEventPublisher(myGroupExpirationPublisher());
}
catch (Exception e) {
e.printStackTrace();
}
}
})
Is there a recommended way to get notification for this use case? Any ideas why the above doesn't seem to work?
I suppose I could extend the AggregatorSpec class to get the message handler configured the way I want, but I wanted to see if I could do this with stock SI classes.
Have just tested and ApplicationEventPublisher is populated properly on the bean initialization phase.
The expireGroup(Object correlationKey, MessageGroup group) is enough big to demonstrate it here, but you can find its code on GitHub. So, MessageGroupExpiredEvent is always published when we reach this method.
Of course if discardMessage(message); doesn't throw exception.
OTOH the exprireGroup() is reachable only in this case:
if (this.releaseStrategy.canRelease(groupNow)) {
completeGroup(correlationKey, groupNow);
}
else {
expireGroup(correlationKey, groupNow);
}
So, please, be sure that your groupPublishStrategy() has proper logic and doesn't return true when your group isn't completed yet.
Well, it really would be better if you debug AbstractCorrelatingMessageHandler for your use-case. If you are sure that your group isn't completed during some groupTimeout, the forceComplete(MessageGroup group) is a good place for you to start debugging.
Otherwise, please, share DEBUG logs for the org.springframework.integration category, when you think that an event has to be emitted.

ServiceStack - Simulating a stronger Scope for IRequestLogger

This is not a question about the RequestLogsService or the RequestLogFeature. It is about the ServiceRunner's call to a IRequestLogger (if one is registered at the app container).
My app has regular logging in place, I dump the app's flow to log a file.
I am now implementing a database log, inspired by the RequestLogsService. This log will contain one line per request, containing all the Request and Response data.
However my endpoint produces outputs at 4 different levels:
Custom auth filter
Validation
Service
AppHostExceptionHandler
From those 4, only the Service outputs are covered by the IRequestLogger, because its ServiceRunner related. Is there any way I can cover my 4 scenarios transparently? I want to minimize the complexity introduced in the pipeline.
Thanks
I encountered a similar problem recently and resolved it as follows:
Custom Auth filter
There are 2 possibilities with this one based upon the type of logging you would like. If you throw an exception in here, you can catch it by setting up an ServiceExceptionHandler in AppHost:
this.ServiceExceptionHandler = (httpRequest, request, exception) =>
{
LogData(httpRequest, exception);
return DtoUtils.HandleException(this, request, exception);
};
If that approach won't work for you or you don't throw an exception during auth, you will have to instead create a logging filter either before or after the auth filter is run. This can be done in a few different locations using either a PreRequestFilter or a RequestFilter depending on when exactly you need it to run (see ServiceStack's Order of Operations).
Validation
I'll assume you are using ServiceStack's built in FluentValidation to perform your validation. In this case, you can hook into the plugin's ErrorResponseFilter like so. Note that if you require the IHttpRequest and IHTTPresponse objects in this method, you may have to do a hack-y workaround and stash them somewhere as they aren't supplied.:
Plugins.Add(new ValidationFeature { ErrorResponseFilter = ValidationErrorResponseFilter});
...
private object ValidationError(ValidationResult validationResult, object o)
{
var httpError = o as HttpError;
LogData(httpError);
}
AppHostExceptionHandler
If the exception occurs in setup of the AppHost, you may have to settle with a simple try/catch. If the exception occurs in AppHost during the request processing however, you can use the ExceptionHandler similar to the ServiceExceptionHandler above:
this.ExceptionHandler = (httpReq, httpRes, operationName, ex) =>
{
LogData(httpReq, httpRes);
}
In conclusion, if all of this doesn't work or is too much code in too many places, you can instead resort to overriding one or more methods in ServiceRunner to get what you need. In my case I overrode OnAfterExecute to log every request that made it to the service handler and then only had to add the exception handler to FluentValidation as noted above.

Accessing WinForm UI from Rhino Service Bus consumer [duplicate]

This question already has answers here:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
(8 answers)
Closed 9 years ago.
I have a WinForm screen that is also a message consumer (using Rhino ESB). If I try to update anything on the screen when I receive a message, nothing happens. A call to Invoke gives me an error that the handle is not created. The form is definitely created though, I'm firing a message on button click on the form and the background process sends a message back. It's with this return message I want to update the UI.
THIS IS NOT A DUPLICATE QUESTION, NONE OF THE SUGGESTED SOLUTIONS WORK.
I believe the difference here may be because I'm using Rhino Service bus. Rhino may be constructing a separate instance of my form rather than the one I'm using. I think what I probably need to do is to have Rhino use my instance of the form as the consumer by passing my instance into the IoC container Rhino is using. Another alternative is to move the Consumer off to it's own class and inject my Form into the consumer, and put a public method on my Form for the Consumer to use. This may work fine with my app because this is the main form and will never be disposed unless the app is closed. This would become problematic on another form that may be instantiated multiple times. Perhaps I could have my form "observe" another static object that a separate Consumer class updates. Please give suggestions as to the best approach.
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
// This does nothing!
txtLogs.Text = "\nJob completed!";
}
}
This throws an error:
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
ERROR: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
It seems that you're consuming a JobCompleted event before the window handle is created. You could try the following:
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
if (!this.HandleCreated)
return;
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
}
}

SignalR Wait for result

Trying to push a message into UI and receive some result to return in synchronous way from web-service.
Method code goes as follows.
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
string decaptcha = null;
hub.On("captchaDecyphered", decyphered =>
{
decaptcha = decyphered;
});
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
return decaptcha;
}
The issue is that method finishes before value is obtained from hub's captchaDecyphered. However the expression { decaptcha = decyphered; } triggers fine from server after method exits.
Adding ManualResetEvent flag and WaitOne() for it doesn't solve the problem freezing the execution and preventing hub.On("captchaDecyphered" from firing.
Any ideas how to synchronize this?
UPDATE#1 Small notice. Cannot avoid using the intermediate synchronous WCF web-service acting as SignalR client, because of pretty specific robots sitting behind, which are able to interact with outer world only by calling webservices synchronously. Basically in this scenario when robot faces captcha it calls the web-service passing it via SignalR to UI for manual recognition.
UPDATE#2 Thanks to #Ken's inspiring advice got it working by enclosing the connection establishing and hub method invocation into separate 'Thread' followed by waiting with 'ManualResetEvent':
new Thread(() =>
{
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
}).Start();
sync.WaitOne();
Have previously been trying to start from 'Task' supposing it would run on separate thread implicitly, but with no luck.
You could have the DecypherCaptcha hub method on the SignalR server return the deciphered captcha as a Task<string> instead on invoking captchaDecyphered.
You may want to use a TaskCompletionSource to help you create the appropriate task. Basically you could call tcs.SetResult(deciphered) and return tcs.Task instead of calling Clients.Caller.captchaDecyphered(deciphered).
Then your client-side code code would simply be:
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
connection.Start().Wait();
return hub.Invoke<string>("DecypherCaptcha", captcha).Result;
}
You've got several options.
(1) Spin off the request to the SignalR hub onto a separate thread, probably using the static ThreadPool class, and then add in all the ManualResetEvent stuff. That way it won't block when you're waiting on the SignalR method to return.
(2) Make the DecypherCaptcha method asynchronous. It looks to me like the DecypherCaptcha() is intended to be a WCF method that in turn wraps a SignalR method. If that's the case, forgetting for a moment whether this is a wise approach, you could still call a WCF method on the client when the captchaDecyphered SignalR method completes. But if it's not intended to be a WCF method, then you could have DecypherCaptcha() either (a) return a Task<T>, and only flag the Task to be complete when the captchaDecyphered completes; or (b) pass in a Func<T> as a continuation parameter, and call that when the captchaDecyphered completes.
In general, one of the things that makes asynchronous programming difficult is that except for the very top-level method, you generally need to make every method that calls an asynchronous method itself asynchronous, all the way up and down the stack, either through the Async pattern (nasty), or continuation passing (better) or through a Task object + async/await (probably best). So adding in a single asynchronous method often results in significant changes to your application, all the way through. That's one of the many reasons why the new async and await keywords in .NET 4.5 are so helpful, because they help to encapsulate the necessary changes when you start making your application asynchronous.
You can use the generic Invoke method where you can specify the type of result you expect. With the method you CAN use .Result to wait for the result.
string result = IHubProxy.Invoke<string>("GetString").Result;

Resources