JavaFX Implementing 2 different MapChangeListeners [duplicate] - javafx

This question already has answers here:
How to make a Java class that implements one interface with two generic types?
(9 answers)
Closed 8 years ago.
I have the following interface, which I want to implement multiple times in my classes:
public interface EventListener<T extends Event>
{
public void onEvent(T event);
}
Now, I want to be able to implement this interface in the following way:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
{
#Override
public void onEvent(LoginEvent event)
{
}
#Override
public void onEvent(LogoutEvent event)
{
}
}
However, this gives me the error: Duplicate class com.foo.EventListener on the line:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
Is it possible to implement the interface twice with different generics? If not, what's the next closest thing I can do to achieve what I'm trying to do here?

Is it possible to implement the interface twice with different generics
Unfortunately no. The reason you can't implement the same interface twice is because of type erasure. The compiler will handle type parameters, and a runtime EventListener<X> is just a EventListener
If not, what's the next closest thing I can do to achieve what I'm trying to do here?
Type erasure can work in our favor. Once you know that EventListener<X> and EventListener<Y> are just raw EventListener at run-time, it is easier than you think to write an EventListener that can deal with different kinds of Events. Bellow is a solution that passes the IS-A test for EventListener and correctly handles both Login and Logout events by means of simple delegation:
#SuppressWarnings("rawtypes")
public class Foo implements EventListener {
// Map delegation, but could be anything really
private final Map<Class<? extends Event>, EventListener> listeners;
// Concrete Listener for Login - could be anonymous
private class LoginListener implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
System.out.println("Login");
}
}
// Concrete Listener for Logout - could be anonymous
private class LogoutListener implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
System.out.println("Logout");
}
}
public Foo() {
#SuppressWarnings("rawtypes")
Map<Class<? extends Event>, EventListener> temp = new HashMap<>();
// LoginEvents will be routed to LoginListener
temp.put(LoginEvent.class, new LoginListener());
// LogoutEvents will be routed to LoginListener
temp.put(LogoutEvent.class, new LogoutListener());
listeners = Collections.unmodifiableMap(temp);
}
#SuppressWarnings("unchecked")
#Override
public void onEvent(Event event) {
// Maps make it easy to delegate, but again, this could be anything
if (listeners.containsKey(event.getClass())) {
listeners.get(event.getClass()).onEvent(event);
} else {
/* Screams if a unsupported event gets passed
* Comment this line if you want to ignore
* unsupported events
*/
throw new IllegalArgumentException("Event not supported");
}
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo instanceof EventListener); // true
foo.onEvent(new LoginEvent()); // Login
foo.onEvent(new LogoutEvent()); // Logout
}
}
The suppress warnings are there because we are "abusing" type erasure and delegating to two different event listeners based on the event concrete type. I have chosen to do it using a HashMap and the run-time Event class, but there are a lot of other possible implementations. You could use anonymous inner classes like #user949300 suggested, you could include a getEventType discriminator on the Event class to know what do to with each event and so on.
By using this code for all effects you are creating a single EventListener able to handle two kinds of events. The workaround is 100% self-contained (no need to expose the internal EventListeners).
Finally, there is one last issue that may bother you. At compile time Foo type is actually EventListener. Now, API methods out of your control may be expecting parametrized EventListeners:
public void addLoginListener(EventListener<LoginEvent> event) { // ...
// OR
public void addLogoutListener(EventListener<LogoutEvent> event) { // ...
Again, at run-time both of those methods deal with raw EventListeners. So by having Foo implement a raw interface the compiler will be happy to let you get away with just a type safety warning (which you can disregard with #SuppressWarnings("unchecked")):
eventSource.addLoginListener(foo); // works
While all of this may seem daunting, just repeat to yourself "The compiler is trying to trick me (or save me); there is no spoon <T>. Once you scratch your head for a couple of months trying to make legacy code written before Java 1.5 work with modern code full of type parameters, type erasure becomes second nature to you.

You need to use inner or anonymous classes. For instance:
class Foo {
public EventListener<X> asXListener() {
return new EventListener<X>() {
// code here can refer to Foo
};
}
public EventListener<Y> asYListener() {
return new EventListener<Y>() {
// code here can refer to Foo
};
}
}

This is not possible.
But for that you could create two different classes that implement EventListener interface with two different arguments.
public class Login implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
// TODO Auto-generated method stub
}
}
public class Logout implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
// TODO Auto-generated method stub
}
}

Related

Is it possible to delay-load PRISM / Xamarin Forms components that aren't immediately needed?

I have the following AppDelegate which takes quite some time to load:
Syncfusion.ListView.XForms.iOS.SfListViewRenderer.Init();
new Syncfusion.SfNumericUpDown.XForms.iOS.SfNumericUpDownRenderer();
Syncfusion.SfCarousel.XForms.iOS.SfCarouselRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfSegmentedControlRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfCheckBoxRenderer.Init();
new Syncfusion.XForms.iOS.ComboBox.SfComboBoxRenderer();
//Syncfusion.XForms.iOS.TabView.SfTabViewRenderer.Init();
new Syncfusion.SfRotator.XForms.iOS.SfRotatorRenderer();
new Syncfusion.SfRating.XForms.iOS.SfRatingRenderer();
new Syncfusion.SfBusyIndicator.XForms.iOS.SfBusyIndicatorRenderer();
What options should I consider when I know some of these components aren't needed for the main screen, but for subscreens?
I am using PRISM, and it appears that every tab is pre-loaded immediately before allowing display or interaction with the end user. What can I do to delay the pre-rendering that the Prism TabView does prior to showing the interface?
Should I use Lazy<T>? What is the right approach?
Should I move these components to another initialization section?
There are a number of ways you could ultimately achieve this, and it all depends on what your real goals are.
If your goal is to ensure that you get to a Xamarin.Forms Page as fast as possible so that you have some sort of activity indicator, that in essence says to the user, "it's ok I haven't frozen, we're just doing some stuff to get ready for you", then you might try creating a "SpashScreen" page where you do additional loading. The setup might look something like the following:
public partial class AppDelegate : FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(new iOSInitializer()));
return base.FinishedLaunching(app, options);
}
}
}
public class iOSInitializer : IPlatformInitializer, IPlatformFinalizer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterInstance<IPlatformFinalizer>(this);
}
public void Finalize()
{
new Syncfusion.SfNumericUpDown.XForms.iOS.SfNumericUpDownRenderer();
Syncfusion.SfCarousel.XForms.iOS.SfCarouselRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfSegmentedControlRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfCheckBoxRenderer.Init();
}
}
public class App : PrismApplication
{
protected override async void OnInitialized()
{
await NavigationService.NavigateAsync("SplashScreen");
}
}
public class SplashScreenViewModel : INavigationAware
{
private IPlatformFinalizer _platformFinalizer { get; }
private INavigationService _navigationService { get; }
public SplashScreenViewModel(INavigationService navigationService, IPlatformFinalizer platformFinalizer)
{
_navigationService = navigationService;
_platformFinalizer = platformFinalizer;
}
public async void OnNavigatedTo(INavigationParameters navigationParameters)
{
_platformFinalizer.Finalize();
await _navigationService.NavigateAsync("/MainPage");
}
}
If you're working with Modules you could take a similar approach though any Modules that would initialize at Startup would still be making that call to Init the renderers before you've set a Page to navigate to. That said, working with Modules does give you a number of benefits here as you only ever would have to initialize things that the app actually requires at that point.
All of that said I'd be surprised if you see much in the way of gain as these Init calls are typically empty methods only designed to prevent the Linker from linking them out... if you aren't linking or have a linker file you could simply instruct the Linker to leave your Syncfusion and other libraries alone.

SysOperation Framework - CanGoBatchJournal

When canGoBatchJournal returns true, a RunBaseBatch can be created in Ax via the System administartion > Inquiries > Batch > New > Task > New >[ClassName:MyRunBaseBatch].
I have a couple of features which have been created using the SysOperation framework however. This method doesn't inherit the canGoBatchJournal method. Is there a way to make them visible in the above mentioned menu as well?
I took a dive into how to form control retrieves it's data. There is an SysOperationJournaledParametersAttribute attribute which you can use.
Below is an example of how the attribute would be applied to a controller. This example shows how the controller calls the custom service. The controller can then be used in as a batch task or you could call the controller from a menu to get the batch dialog to display.
[SysOperationJournaledParametersAttribute(true)]
class YourCustomController extends SysOperationServiceController
{
public void new()
{
super();
this.parmClassName(classStr(YourCustomService));
this.parmMethodName(methodStr(YourCustomService,processOperation));
this.parmDialogCaption("dialog caption");
}
public ClassDescription caption()
{
return "class description";
}
public static void main(Args args)
{
YourCustomController controller;
controller = new YourCustomController();
controller.startOperation();
}
}
Below would be the custom service the controller calls.
class YourCustomToolService extends SysOperationServiceBase
{
public void processOperation()
{
// Call your code to do run your custom logic
}
}
If you implement the SysOperation framework, it should already be good as SysOperationController implements the Batchable interface.
You can refer to this white paper: https://www.microsoft.com/en-us/download/details.aspx?id=29215

Simple UnityContainerExtension

I'm working on an application that is using the bbv EventBrokerExtension library. What I'm trying to accomplish is that I want to have unity register the instance that are instantiated through the container with the EventBroker. I'm planning on doing this through a UnityContainerExtension and implementing the IBuilderStrategy. The problem is that the methods for the interface seem to be called for each parameter in the constructor. The problem is when Singleton instances get resolved when building an object they will be registered multiple times.
For instance suppose you had
class Foo(ISingletonInterface singleton){}
class Foo2(ISingletonInterface singleton){}
and you resolve them via unity using
var container = new UnityContainer();
container.AddNewExtension<EventBrokerWireupStrategy>();
container.RegisterInstance<IEventBroker>(new EventBroker());
container.RegisterInstance(new Singleton());
var foo = container.Resolve<Foo>();
var foo2 = container.Resolve<Foo2>();
Then the UnityContainerExtension will call postbuildup on the same singleton object. Here is my naive implementation of UnityContainerExtension.
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.ObjectBuilder;
using bbv.Common.EventBroker;
using System.Collections.Generic;
namespace PFC.EventingModel.EventBrokerExtension
{
public class EventBrokerWireupExtension : UnityContainerExtension, IBuilderStrategy
{
private IEventBroker _eventBroker;
private List<object> _wiredObjects = new List<object>();
public EventBrokerWireupExtension(IEventBroker eventBroker)
{
_eventBroker = eventBroker;
}
protected override void Initialize()
{
Context.Strategies.Add(this, UnityBuildStage.PostInitialization);
}
public void PreBuildUp(IBuilderContext context)
{
}
public void PostBuildUp(IBuilderContext context)
{
if (!_wiredObjects.Contains(context.Existing))
{
_eventBroker.Register(context.Existing);
_wiredObjects.Add(context.Existing);
}
}
public void PreTearDown(IBuilderContext context)
{
}
public void PostTearDown(IBuilderContext context)
{
}
}
}
After further investigation it appears that the problem has to do with the EventBrokerExtension. If I subscribe them in a certain order then some of them don't get registered with the event broker.
UPDATE:
Wanted to update this question really quick with the answer in case anyone else witnesses similar behavior when using the bbv EventBroker library. The behavior I was seeing was that a subscriber would get events for a while but then would stop receiving events. By design the EventBroker only maintains weak references to the publishers and subscribers that have been registered. Since the eventbroker was the only class referencing the objects they were getting garbage collected at an indeterminate time and wouldn't receive events anymore. The solution was simply to create a hard reference somewhere in the application besides the EventBroker.

Send object to VIewModel with mvvm-light

I'm pretty new to MVVM light world, and after searches I can't find what I want to do.
My WP7 application contains a pivot, each pivot item content is View1 and viewmodel is VM1.
When loading my application, I'd like to create every pivot item with the same view and view model but with different parameter.
example :
PivotItem 1 -> send param "car" to the view model
PivotItem 2 -> send param "truck" to the view model, etc.
Google told me to use messaging but if I send 2 messages from my MainViewModel, both PivotItem1 and PivotItem2 ViewModel will receive these messages.
Am I wrong with this approach ?
Is there another solution to succeed ?
Thank you in advance for your answer.
PS : be indulgent, english is not my native language, don't hesitate to ask for further information.
Regards,
Aymeric Lagier
To seperate the messages use the second constructor signature whereby you can pass a token. This token can be anything but I generally use an enum to store all my message types within the system.
Create a static class in a common library and reference this in all projects where you need to send or receive messages.
The following code hopefully shows this approach, notice I am sending a string as a value within the message but this can be anything, even a complex object such as one of your business objects.
namespace MyProject.Common
{
public static class AppMessages
{
enum MessageTypes
{
ViewmodelA,
ViewmodelB
}
public static class ViewModelAUpdate
{
public static void Send(string value)
{
Messenger.Default.Send(value, MessageTypes.ViewmodelA);
}
public static void Register(object recipient, Action<string> action)
{
Messenger.Default.Register(recipient, MessageTypes.ViewmodelA, action);
}
}
public static class ViewModelBUpdate
{
public static void Send(string value)
{
Messenger.Default.Send(value, MessageTypes.ViewmodelB);
}
public static void Register(object recipient, Action<string> action)
{
Messenger.Default.Register(recipient, MessageTypes.ViewmodelB, action);
}
}
}
}
How about using a method to set the message you want to receive. (this could be done as a parameter in the constructor or a property as well)
public void RegisterForAppMessage(AppMessages.MessageTypes messageType)
{
switch (messageType)
{
case AppMessages.MessageTypes.PivotViewItem1Message:
AppMessages.PivotViewItem1Message.Register(this,DoSomethingWhenIRecievePivotViewItem1Messages)
break;
case AppMessages.MessageTypes.PivotViewItem2Message:
AppMessages.PivotViewItem2Message.Register(this,DoSomethingWhenIRecievePivotViewItem2Messages)
break;
}
}
private void DoSomethingWhenIRecievePivotViewItem2Messages(string obj)
{
// TODO: Implement this method
throw new NotImplementedException();
}
private void DoSomethingWhenIRecievePivotViewItem1Messages(string obj)
{
// TODO: Implement this method
throw new NotImplementedException();
}
Messaging sounds a bit heavy for this purpose. Could you simply inject a parameter into your ViewModel. If you already have MVVMLight you also have support for SimpleIOC. Maybe let the view locate its ViewModel when the view is resolved and there decide which parameter to use on the view model?
You can see an example of it here

RhinoMocks Event Subscription

Being new to RhinoMocks and Unit Testing, I have come accross an issue that I cannot seem to find a resolution to (no matter how much documentation I read).
The issue is this: I have created an Interface that exposes 5 Events (to be used for a view in ASP.NET and the MVP Supervisory Controller pattern..... I know, I should be using MVC, but that's a whole other issue). Anyway, I want to test that when a certain event fires on the view, we'll call it "IsLoaded", that a method inside of my Presenter is called and, using Dependency Injection, a value is returned from the Dependency and set to the view. Here is where the problem starts: when I use Expect.Call(Dependency.GetInfo()).Return(SomeList), the Call never executes (without the mock.ReplayAll() method being invoked). Well, when I invoke the ReplayAll method, I get ExpectationExceptions because of the Subscription by the Presenter object to the other Events exposed by the View Interface.
So, for me to test that IView.IsLoaded has fired, I want to verify that IView.ListOfSomething has been updated to match the list I passed in via the Expect.Call(). However, when I set the expectation, the other Event subscriptions (which occur straight out of the constructor for the Presenter) fail the #0 Expectations of the test. What I get is, view.Save += this.SaveNewList tosses up a RhinoMocks ExpectationViolationException.
My million dollar question is this: Is it necessary I set expectations for ALL of my events (via [Setup]), or is there something that I'm missing/not understanding about how Unit Testing or RhinoMocks works?
Please bear in mind I am extremely new to Unit Testing, and therefore RhinoMocks. If it appears I don't know what I'm talking about, please feel free to point that out.
I'm working on a project where we used MVP and rhino mocks as well. What we did was simply expect all event subscriptions in every test.
private void SetupDefaultExpectations()
{
_mockView.Initializing += null; LastCall.IgnoreArguments();
_mockView.SavingChanges += null; LastCall.IgnoreArguments();
}
Then we built a extension method on IMockedObject (from RhinoMocks) to trigger events in the unit tests and un-wrap exceptions so that they can be expected in the standard NUnit way.
static class IMockedObjectExtension
{
public static void RaiseEvent(this IMockedObject mockView, string eventName, EventArgs args)
{
EventRaiser eventraiser = new EventRaiser(mockView, eventName);
try
{
eventraiser.Raise(mockView, args);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
public static void RaiseEvent(this IMockedObject mockView, string eventName)
{
RaiseEvent(mockView, eventName, EventArgs.Empty);
}
}
This could then be used from the unit test like this
using(_mocks.Record())
{
Expect.Call(dependency.GetInfo()).Return(someList);
}
using(_mocks.Playback())
{
Presenter presenter = new Presenter(_mockView, dependency);
(_mockView as IMockedObject).RaiseEvent("SavingChanges");
}
To eliminate duplication between presenter tests we have refactored this to a BasePresenterTest base class which sets up this basic structure for all presenter tests and exposes helper methods to the sub class.
public abstract class BasePresenterTest<VIEW> where VIEW : IBaseView
{
protected MockRepository _mocks;
protected VIEW View { get; private set; }
protected abstract void SetUp();
protected abstract void TearDown();
protected abstract void SetupDefaultExpectations();
[SetUp]
public virtual void BaseSetUp()
{
_mocks = new MockRepository();
View = _mocks.CreateMock<VIEW>();
SetUp();
}
[TearDown]
public virtual void BaseTearDown()
{
TearDown();
View = null;
_mocks = null;
}
protected virtual void BaseSetupDefaultExpectations()
{
//Setup default expectations that are general for all views
SetupDefaultExpectations();
}
protected virtual IDisposable Record()
{
IDisposable mocksRecordState = _mocks.Record();
BaseSetupDefaultExpectations();
return mocksRecordState;
}
protected virtual IDisposable Playback()
{
return _mocks.Playback();
}
protected void RaiseEventOnView(string eventName)
{
(View as IMockedObject).RaiseEvent(eventName);
}
}
This eliminates alot of code from the tests in our project.
We still use a old version of RhinoMocks but I will try to update this once we move to a later version.

Resources