MvvmCross Messenger Plugin Purging subscriptions - mvvmcross

I'm using the Messenger Plugin in my MvvmCross application and have noticed that it sometimes purges my subscriptions ("One or more listeners failed - purge scheduled"). This is causing an error in my application. By default I am using the weak reference for the subscriptions and I am not unsubscribing from the message.
Do I need to be Unsubscribing? Isn't the point of a weak reference to allow it to be garbage collected?
My BaseView is subscribing in the constructor as shown below.
public BaseView()
{
_messenger = Mvx.Resolve<IMvxMessenger>();
_messenger.Subscribe<MyMessage>(s => Method());
}
Below is my Broadcast Receiver publishing my message.
var _messenger = Mvx.Resolve<IMvxMessenger>();
_messenger.Publish<MyMessage>(new MyMessage(this));
I have an idea of trying to unsubscribe in the onDestroy.
If you could give me some insight as to why this is happening and a possible resolution I would be grateful.
Thanks in advance.

When using weak references, it's important to store the returned subscription token in a class-level field.
private IDisposable _token;
public BaseView()
{
_messenger = Mvx.Resolve<IMvxMessenger>();
_token = _messenger.Subscribe<MyMessage>(OnMyMessage);
}
private void OnMyMessage(MyMessage msg)
{
// code
}
If you don't do this, then the GarbageCollector is free to collect the subscription.
For more on this, please see the section on "This GC-based unsubscription will occur whenever the subscription token returned from Subscribe is Garbage Collected" in the wiki - https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#messenger

Related

Should my Domain Exceptions be thrown from Application Layer?

I'm reading Vaughn Vernon Book - Implementing Domain Driven Design. There is an example of a Project Management Application. There are aggregates like BacklogItem, Sprint, etc. If I have BacklogItemNotFoundException defined in Domain layer. Should my Rest adapter catch it and transform into NotFoundHttpResult? Or any other broken invariant exceptions like: EmailPatternBrokenException or TooManyCharactersForNameException or whatever should be handled in Rest adapter(ports&adapters architecture) and re-transformed into rest responses? If yes, it means that RestAdapter should have a reference to Domain layer? This is what bothers me...
The question is a contradiction. If it is a Domain Exception, it means that it is thrown by the domain.
Anyway, exceptions thrown by the domain should be handled by the application layer.
I have an exception handler decorator for the command bus, that catch any domain exception and translates it into an Application Exception.
This application exception is thrown to the adapters.
Adapters know about application exceptions, not domain exceptions.
UPDATE
My domain exception is an abstract base class from which the concrte domain exceptions inherit
public abstract class DomainException extends RuntimeException {
private static final long serialVersionUID = 1L;
private ErrorMessage mainErrorMessage;
private List<ErrorMessage> detailErrorMessages;
protected DomainException ( List<ErrorMessage> aDetailMessages, Object... aMainMessageArgs ) {
this.mainErrorMessage = new ErrorMessage(this.getClass().getSimpleName(), aMainMessageArgs );
this.detailErrorMessages = ( (aDetailMessages==null) ? new ArrayList<ErrorMessage>() : aDetailMessages );
}
public ErrorMessage mainErrorMessage() {
return this.mainErrorMessage;
}
public List<ErrorMessage> detailErrorMessages() {
return this.detailErrorMessages;
}
}
ErrorMessage has a key and a list of args. The messages are in a property file where the key is the name of the concrete domain exception class.
Application exception is just one type, which holds the concrete text message.
public class ApplicationException extends Exception {
private static final long serialVersionUID = 1L;
private String mainMessage;
private String[] detailMessages = new String[0];
public ApplicationException ( String aMainMessage, Throwable aCause, String... aDetailMessages ) {
super ("Main Message = "+aMainMessage+" - DetailMessages = "+Utils.toString(aDetailMessages), aCause );
this.mainMessage = aMainMessage;
this.detailMessages = ( (aDetailMessages==null) ? (new String[0]) : aDetailMessages );
}
public String mainMessage() {
return this.mainMessage;
}
public boolean hasDetailMessages() {
return (this.detailMessages.length > 0);
}
public String[] detailMessages() {
return this.detailMessages;
}
}
I have a decorator (wraps the execution of every command) for handling domain exceptions:
public class DomainExceptionHandlerDecorator extends Decorator {
private final DomainExceptionHandler domainExceptionHandler;
public DomainExceptionHandlerDecorator (DomainExceptionHandler domainExceptionHandler) {
this.domainExceptionHandler = domainExceptionHandler;
}
#Override
public <C extends Command> void decorateCommand(Mediator mediator, C command) throws ApplicationException {
try {
mediator.executeCommand(command);
} catch ( DomainException de ) {
this.domainExceptionHandler.handle (de);
}
}
}
And I have a domain exception handler that takes a domain exception, translates it into an app exception by reading properties file (TextMessageService does the job) and throw the app exception.
public class TranslatorDomainExceptionHandler implements DomainExceptionHandler {
private final TextMessageService configurationService;
public TranslatorDomainExceptionHandler ( TextMessageService aConfigurationService ) {
this.configurationService = aConfigurationService;
}
#Override
public void handle ( DomainException de ) throws ApplicationException {
ErrorMessage mainErrorMessage = de.mainErrorMessage();
List<ErrorMessage> detailErrorMessages = de.detailErrorMessages();
String mainMessage = this.configurationService.mensajeDeError ( mainErrorMessage );
String[] detailMessages = new String [ detailErrorMessages.size() ];
int i = 0;
for ( ErrorMessage aDetailErrorMessage : detailErrorMessages ) {
detailMessages[i] = this.configurationService.mensajeDeError ( aDetailErrorMessage );
i++;
}
throw new ApplicationException ( mainMessage, de, detailMessages);
}
}
The adapter (an UI for example) will catch the app exception and show its message to the user. But it doesn't know about domain exceptions.
I try to avoid domain exceptions as much as I can and prefer to make invalid states unreachable instead. The first reason is that exceptions are for exceptional, unexpected things, the second that I don't like my code to be cluttered with fine-grained try/catches for every little business-ish thing that could go wrong.
BacklogItemNotFoundException
To me this is typically your Repository or query service returning null or an empty list. No need for a domain exception.
EmailPatternBrokenException
TooManyCharactersForNameException
I let the validation feature of my web framework handle these. You could also check it in the Domain but it will rarely reach that point and you don't really need to handle that kind of error specifically.
As a result, the two typical scenarios are:
+-----------------------+--------------------+-------------------------------------------------+
| Domain | Application | Presentation |
+-----------------------+--------------------+-------------------------------------------------+
| Expected failure case | Return Result.Fail | Clean error message |
+-----------------------+--------------------+-------------------------------------------------+
| Exception | - | Caught in catch-all clause > 500 error or other |
+-----------------------+--------------------+-------------------------------------------------+
I will add my 2 cents about error handling, not specifically related to DDD.
The exception are part of the contract you expose to the consumer. If you're expected to for example add an item to a shopping cart, the exception you may explicitly throw include itemNotAvailable, shoppingCartNotExisting, etc...
Technical exception on the other hand are not part of the contract, they may occurs but shouldn't be explicitly handled as no one can do anything about it, they must imply the operation interruption (and the rollback of the current unit of work).
A rest interface is a contract for an operation on a resource. When using rest over http the terms of the contract are related to the http protocol.
Typical operation described above (adding ie. post an item on a cart resource) would be translated to, for example, 404 for shoppingCartNotExisting and 409 for itemNotAvailable (conflict ie. the update on the resource is no more possible because some state has changed meantime).
So yes all "domain" exception (expected exceptions as part of the contract) should be explicitly mapped by the rest adapter, all unchecked ones should result in a 500 error.
TLDR; It is OK if the Application or Presentation layer has a dependency to the Domain layer, the other way is not recommended.
Idealy, there should not exist any dependency from one layer to another but that is impossible or the software would not be usable. Instead you should try to minimize the number and the direction of the dependencies. The general rule or best practice to a clean architecture is to keep the Domain layer agnostic of the infrastructure or the Application layer. The Domain objects (Aggregates, Value objects etc) should not care about a specific persistence or Rest or HTTP or MVC, just like the domain experts don't care about these things.
In real world, the Domain layer may be influenced by technology (like frameworks). For example we put annotations to mark some Domain objects as behaving in some specific way when persisted instead of using external XML or JSON files just because it is at hand, it is easier to maintain them. We need, however, to limit these influences to a minimum.
The application layer is business-specific domain itself. So your application layer should handle the domain exception based on what the application/business expects. The application(eg. client facing web application, mobile, an internal CRM app, or a backend-for-frontend API) is probably not the only client of the domain layer(eg. a rest api, a jar library). There might be certain domain exceptions that you don't want to expose to the end-user so the application has to wrap these exceptions specifically or handle exceptions globally.

Xamarin.Forms Plugin.Geofence giving System.InvalidCastException: Specified cast is not valid

I am using Plugin.Geofence i Implemented its interface,Installed its dependencies i.e. .NETStandard 2.0 and Xamarin.GooglePlayServices.Location.
I am getting this exceptions System.InvalidCastException: Specified cast is not valid. when i run StartMonitoring method.
I am calling this method in the App() Constructor.
public App ()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
CrossGeofence.Current.StartMonitoring(new GeofenceCircularRegion("MyRegion", 31.475085, 74.305833, 200)
{
//To get notified if user stays in region for at least 5 minutes
NotifyOnStay = true,
StayedInThresholdDuration = TimeSpan.FromMinutes(5)
});
}
Tried everything but couldn't resolve this
For anyone looking for a solution to this, ensure that before calling "CrossGeofence.Current" that the correct permissions have been requested and granted. If not, you'll see this error.

AppWarp Implementation

I am trying to implement AppWarp into a game I am making. I followed a tutorial exactly as it was written but I am getting about a dozen errors at "NetworkPeer implements". Some of the errors are:
Error: Interface method onConnectDone in namespace com.shephertz.appwarp.listener:ConnectionRequestListener not implemented by class NetworkPeer.
Error: Interface method onDisConnectDone in namespace com.shephertz.appwarp.listener:ConnectionRequestListener not implemented by class NetworkPeer.
And so on...
Any help is greatly appreciated!
public class NetworkPeer implements ConnectionRequestListener, RoomRequestListener, NotificationListener
{
public var roomID:String = "Room";
private var apiKey:String = "API_ID"
private var secretKey:String = "Secret_Key";
private var localUsername = Math.random().toString();
public function NetworkPeer()
{
WarpClient.initialize(apiKey, secretKey);
WarpClient.getInstance().setConnectionRequestListener(null);
WarpClient.getInstance().setRoomRequestListener(null);
WarpClient.getInstance().setNotificationListener(null);
}
private function connect_click(e:MouseEvent):void
{
if (WarpClient.getInstance().getConnectionState() == ConnectionState.disconnected)
{
WarpClient.getInstance().connect(localUsername);
Main.connectbtn.text = "Connecting..";
}
}
}
You are getting this error because, you have implemented listeners like ConnectionRequestListener to NetWorkPeer class but not defined corresponding callback methods like onConnectDone in NetworkPeer.
The AppWarp APIs are developed to be used asynchronously, and in order to receive responses and updates from the AppWarp Server, you need to add corresponding request listeners to the WarpClient instance.
In the code snippets, you are adding null as listener which is not needed. You only need to add the listeners and its callback methods which you want to receive in your game.
For example, if you call connect API then you need to add ConnectionRequestListener and define onConnectDone callback method to get the response from the AppWarp Server.
You can have a look at this sample to know more about the integration of AppWarp into your ActionScript project.
You can also go through the AppWarp Getting Started page for Action Script to know more about the necessary steps which need to be done.
If you face any further problems , you can always write on our Forum or on support#shephertz.com.

MVVMCross ViewModel construction failure notifications

We've noticed a couple of times in our mobile applications that users have reported the application hanging or seeming to become unresponsive between views / rare crashes when switching between views. We've tracked down these cases to when our view model constructors throw uncaught exceptions.
We want to put a solution in place so that if a view model fails to construct for some reason then we can notify the user and provide some message that will be useful to us when it's logged through support.
I've been taking a look at doing this but haven't found a reliable way to achieve this.
The first thing we tried was at the IMvxViewModelLocator level. We already have a custom implementation of IMvxViewModelLocator so we've modified this. We allow all exceptions to be thrown and then we have an IErrorHandler interface which each platform implements. We then call this to attempt to show a dialog. This has proved to be unreliable and the dialog does not always display. Something along the lines of: (note - here ResolveViewModel will always return true or throw)
public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel)
{
try
{
return ResolveViewModel(viewModelType, parameterValues, savedState, out viewModel);
}
catch (Exception exception)
{
_errorHandler.HandleViewModelConstructionException(viewModelType, exception);
viewModel = null;
return false;
}
}
What we would ideally like to do is intercept any failure to construct a view model and then re-request an ErrorViewModel. We've tried to do this 2 ways:
1)
We've tried defining a custom IMvxViewDispatcher for each platform and we're trying to intercept failures as below but if an exception in the constructor is thrown we never get back this far:
public class TouchDispatcher : MvxTouchUIThreadDispatcher, IMvxViewDispatcher
{
private readonly IMvxTouchViewPresenter _presenter;
public TouchDispatcher(IMvxTouchViewPresenter presenter)
{
_presenter = presenter;
}
public bool ShowViewModel(MvxViewModelRequest request)
{
Action action = () =>
{
_presenter.Show(request);
};
try
{
bool success = RequestMainThreadAction(action);
return !success ? HandleError() : success;
}
catch (Exception)
{
return HandleError();
}
}
// Other bits
}
2)
We thought we might have more success at the presenter level. We modified our ViewPresenter for each platform and we have overridden void Show(MvxViewModelRequest request). This has not proved to be successful either as exceptions don't propagate back this far.
This leaves me thinking that maybe we are better attempting this at the IMvxViewModelLocator level again.
Has anyone found a way to reliably intercept failures to construct view models and then ideally re-request a different view model / present some dialog to the user?
It seems you've identified that the core of the problem is when: "view model constructors throw uncaught exceptions."
This is going to be slightly problematic as the ViewModel's are generally constructed during View lifecycle overrides like ViewDidLoad, OnCreate or NavigatedTo - which is generally after the Presenter has finished requesting presentation.
As you've already found an easy place to identify when ViewModel construction has failed is in a custom IMvxViewModelLocator - others likeIMvxViewModelLoader are also possible. This is probably the easiest place to catch the error and to trigger the error handling - you can then get hold of the IMvxViewDispatcher (or presenter) there in order to change the display. However, you will still need to make sure your Views can handle null created ViewModels - as the ViewDidLoad, etc calls will still need to complete.

How can I manually handle any subscribed to message type in NServiceBus?

I'm trying to build a layer over NServiceBus to make it simpler for other developers to use.
I'm trying to do without the config file and managed to get the publisher to work:
public class NServiceBusPublisher
{
private IBus _Bus { get; set; }
public void NServiceBusPublisher(string argInputQueue, string argErrorQueue)
{
Configure configure = NServiceBus.Configure.With().DefaultBuilder();
var transport = configure.Configurer.ConfigureComponent<MsmqTransport>(ComponentCallModelEnum.Singleton);
transport.ConfigureProperty(t => t.InputQueue, argInputQueue);
transport.ConfigureProperty(t => t.ErrorQueue, argErrorQueue);
transport.ConfigureProperty(t => t.NumberOfWorkerThreads, 1);
transport.ConfigureProperty(t => t.MaxRetries, 5);
_Bus =
configure
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.MsmqSubscriptionStorage()
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
}
public void Publish(NServiceBus.IMessage argMessage)
{
_Bus.Publish(argMessage);
}
}
I also want to have an NServiceBus Subscriber and make it possible for developers to subscribe to any number of message types as long as the message inherits from NServiceBus.IMessage:
public class NServiceBusSubscriber
{
private IBus _Bus { get; set; }
public void NServiceBusSubscriber(string argInputQueue, string argOutputQueue, string argErrorQueue, string messagesAssembly)
{
Configure configure = NServiceBus.Configure.With().DefaultBuilder();
var transport = configure.Configurer.ConfigureComponent<MsmqTransport>(ComponentCallModelEnum.Singleton);
transport.ConfigureProperty(t => t.InputQueue, argInputQueue);
transport.ConfigureProperty(t => t.ErrorQueue, argErrorQueue);
transport.ConfigureProperty(t => t.NumberOfWorkerThreads, 1);
transport.ConfigureProperty(t => t.MaxRetries, 5);
var ucb = configure.Configurer.ConfigureComponent<NServiceBus.Unicast.UnicastBus>(ComponentCallModelEnum.Singleton);
ucb.ConfigureProperty(u => u.MessageOwners, new Dictionary<string,string>()
{
{messagesAssembly, argOutputQueue}
});
_Bus =
configure
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.MsmqSubscriptionStorage()
.UnicastBus()
.ImpersonateSender(false)
.DoNotAutoSubscribe()
.CreateBus()
.Start();
}
public void Subscribe<T>() where T : NServiceBus.IMessage
{
_Bus.Subscribe<T>();
}
}
The problem is that I couldn't find any way to attach an event handler to a particular message type.
Could you please help me figure this out?
Its been a while since the question has been asked, so I am not sure if the problem has been solved, but here's one way you can do it using Bus.Subscribe (although as has been said by other respondents this is not the prescribed way of doing it NServiceBus)
Subscribe the to the message type using the subscribe overload
void Subscribe(Type messageType, Predicate<IMessage> condition);
Then you can handle the message in the delegate
private bool Handle(NServiceBus.IMessage nsbMsg)
{
//you get the message instance that you can handle
//return true
}
So, your code would then be
class MySubscriber
{
public IBus Bus {get; set;}
public void Subscribe()
{
Bus.Subscribe(typeof(MyMessage), Handle);
}
public void Handle(NServiceBus.IMessage nsbMsg)
{
var msg = nsbMsg as MyMessage;
//your code
return true;
}
}
However please note that by doing this you have to manage the lifetime of the handler yourself, which otherwise would have been managed for you by NServiceBus using the IOC framework of your choice.
You will also have to pass the reference to IBus explicitly which would be injected for you automatically if you were just implementing the IHandleMessage interface.
An architectural point here is that NSB is a full fledged 'ESB', its not just a messaging layer. Adding another layer over your ESB is IMHO an abstraction too many.
I think you are missing the concept behind NServiceBus.
Based on the code you show I get the impression that you envision services that publish messages and others that process those messages. In my experience most processes do both: they subscribe to events or process incoming commands and in result publish new events and send new commands.
In your setup you would need to have publisher and subscriber instances for each of these message types.
NServiceBus is built for the situation I describe. You configure and start 1 bus instance and that orchestrates the complete application.
If you want to make it easier for developers to use NServiceBus I would concentrate on the configuration part only. In our company I have created a ServicebusConfigurator class that configures NServiceBus according our company standards and extracted that in a framework and a simple extension method for the .NET Core generic host. The only code our developers need to write to create a Windows Service that hosts an NServiceBus endpoint is something like this:
internal static class Program
{
private static int Main(string[] args)
{
return (int)Host.CreateDefaultBuilder(args) //.NET Core generic host
.WithNServiceBus() //configure NServiceBus according to our standards and start it.
.UseTopshelf<Worker>() // use Worker as the actual service doing the work.
.EnableNsbInstallersDuringInstall() // Execute any NServiceBus transport specific installation code during install of the service.
.Run(); // Run the thing.
}
}
Since you are not auto-subscribing the first thing you will need to do is subscribe to the message type via Bus.Subscribe(). Others could do this at the IWantToRunAtStartUp extension point(implement the interface in a class somewhere). From there, each subscriber will implement the IHandleMessages<T> interface. Implementing this interface wires you to a message where "T" is the message type.
When NSB starts up it will scan the local bin dir and find all your interface implementations and wire them up on your behalf internally. From there it will dispatch to the correct handler when a message of that type arrives.
NServiceBus automatically handles the subscription of messages. When you invoke Configure.With()....Start(); NServiceBus will scan to determine which assemblies implement IHandleMessages(SomeMessage) and it will send a subscription request to the publisher.
When you add "DoNotAutoSubscribe", you've got to manually get all messages being handled and do a Bus.Subscribe() for each of them.
Beyond that, NServiceBus will automatically handle the routing of an incoming message to the appropriate handler. In your subscriber code above, are you receiving an error message or are the messages disappearing from the queue?