Variable arguments with different types? - java

I have a List of event listeners in my code:
private List<EventListener> listeners = new ArrayList<EventListener>();
listeners.add(new EventListener() {
#Override
public void someEvent(String arg1, MyClass arg2) {
// ...
}
#Override
public void someOtherEvent(AnotherClass arg1, int arg2) {
// ...
}
}
Currently, I am calling the listeners using a for loop:
for (EventListener listener : listeners) {
listener.someEvent("Hello world", (MyClass) myObject);
}
I would like to call it using a single method, like this:
fireEvent("someEvent", "Hello world", (MyClass) myObject);
Or possibly an array or something for the event arguments.
One way to do this would be to create some sort of event object, but I don't particularly want to do this as it seems messy (someone tell me if I'm wrong here; I'm inexperienced with Java). Is there a way to create a fireEvent similar to above? EventListener is an interface, if that helps.

Theoretically, you can do this using java reflection:
public void fireEvent(String name, Object... args) {
Method method = null;
// 1. find method
for (Method m : EventListener.class.getMethods()) {
if (m.getName().equals(name)) {
method = m;
break;
}
}
if (method == null) {
throw new IllegalArgumentException("Unknown event method: " + name);
}
// 2. call method on all listeners
for (EventListener l : listeners) {
try {
method.invoke(l, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalArgumentException(e);
}
}
}
(Note that this is a trivial version that does not cover all eventualities like overloaded event methods etc.)
But I strongly advice do NOT do that! It's not only ugly and hard to read, it also makes your program being NOT typesafe any more! When you use the wrong name String or the wrong number or types of parameters, the compiler won't notice, but the program will break at runtime!
So I suggest to simply have one protected fireXXXEvent method for every event handler method of your listener (using a simple for loop). In your case this would be:
protected void fireSomeEvent(String arg1, MyClass arg2);
protected void fireSomeOtherEvent(AnotherClass arg1, int arg2);
Of course you can also introduce event objects (possibly by subclassing java.util.EventObject). But this might not necessarily reduce the number of methods in your listener (but it can - depends on the types of events you've got).
There are some fancier strategies e.g. using a generic event handler with event type objects and generic event objects as in JavaFX, but I think this is not recommended if you're not very familiar with java.
Sidenote: Use either a CopyOnWriteArrayList for storing your listeners or iterate over a copy of listeners when firing the events otherwise you might get a ConcurrentModificationException if a listeners tries to remove itself from the listener list.

Related

Any design patterns for handling the following case in Java?

I'm new to Java & its design patterns, I have a scenario like this:
Method 1 calls Method 2.
Method 2 looks like the following:
public String createUser(String username, String password) {
someApi.do(config -> {
//code here with respect to someApi.
});
}
now the trick is I need to return the value to caller which is method 1. If there are no exceptions then that is fine. However the code block inside do can throw exception, which will be handled in a separate listener class like this:
public class TestListener implements SomeApiListener {
#Override
public void exception(Throwable cause) {
}
}
Now how should I send back the exception to method 1 from this listener? I'm really confused.
it's not clear what that API do, where the listener is assigned, and what other methods it has, like if there is also onSuccess() ?
what i got from this, is that, you are dealing with async call, which usually do not return a value directly, it deals with a CallBack which in your case is SomeApiListener
So, ... I would make createUser() receives extra arg, SomeApiListener, pass the listener as anonymous inner class (with implementation) when calling the method (from caller).
ex,
public String createUser(String username, String password, SomeApiListener listener) {
someApi.do(config -> {
//code here with respect to someApi.
//somewhere here you are creating a TestListener ?,
//well... don't, and use the one passed from caller (listener)
});
}
Caller part will look like this:
public void method1(){
//..some code ...
createUser(username, password, new SomeApiListener(){
#Override
public void exception(Throwable cause) {
//handle exception...
}
#Override
public void success(Response response) {
//handle response ...
}
});
}
Note: you can still pass TetstListern, if you want, in that case you will have to have a physical class (local class) defined and instantiated, the anonymous-inner-class is somehow a shortcut for that, you don't create a local class, just pass it as an arg.
You can't, at least not in any simple way. I'd expect the documentation for your someApi to demonstrate some common use cases, with exception handling included. If you're combining different ways of programming ("normal" java & functional programming), you can get into tricky situations.
Based on the information you've given, a clumsy solution could look something like this (code obviously not fit for compilation):
public class MyClass implements SomeApiListener {
private Throwable e;
public void exception(Throwable cause) {
e = cause;
}
public void method1() {
createUser("foo", "bar");
if(e != null) {
// Exception was thrown, do something with it
}
}
}
However this is in no way a recommendation. It's clumsy, hacky and bad in every way. A better solution would involve not trying to send the exception back to method1, but instead to modify your code to work in the way that someApi expects.
It depends on your design on how to handle exceptions. Normally, if the method 2 is an utility method then throw the exception back to method 1 and let it handle the exception. Else, if method 2 understands the use case for which it is called then handle the exception there. There are no hard and fast rules, but keep the utility classes clean and send the exception back to the caller so that caller can handle it.

Observable which does not pass anything in onNext()

I would need an Observable, for example to provide a system clock, which does not need to pass anything in onNext(). I couldn't find a signature that would allow me to do that.
Sure, I could use any object and then pass null, but that doesn't make much sense. So my question is if there is a better way to do that.
Observable.create(new Observable.OnSubscribe<Anyobject>() { // use any object in the signature
#Override public void call(Subscriber<? super Anyobject> subscriber) {
subscriber.onNext(null); // then pass null
subscriber.onCompleted();
}
})
You don't need to call onNext if your Observable doesn't emit anything.
You could use Void in your signature and do something like
Observable<Void> o = Observable.create(new Observable.OnSubscribe<Void>() {
#Override
public void call(Subscriber<? super Void> subscriber) {
// Do the work and call onCompleted when you done,
// no need to call onNext if you have nothing to emit
subscriber.onCompleted();
}
});
o.subscribe(new OnCompletedObserver<Void>() {
#Override
public void onCompleted() {
System.out.println("onCompleted");
}
#Override
public void onError(Throwable e) {
System.out.println("onError " + e.getMessage());
}
});
You can define an OnCompletedObserver to simplify your Observer callback so that you don't have to override the onNext since you don't need it.
public abstract class OnCompletedObserver<T> implements Observer<T> {
#Override
public void onNext(T o) {
}
}
If I've understood what you're asking then this should do the trick.
If you need something to be passed to onNext() before onCompleted() is called:
Observable.<Void>just(null)
If you only need onCompleted() to be called:
Observable.empty()
RxJava 2 Wiki:
RxJava 2.x no longer accepts null values and the following will yield
NullPointerException immediately or as a signal to downstream.
...
This means that Observable<Void> can no longer emit any values but
only terminate normally or with an exception. API designers may
instead choose to define Observable<Object> with no guarantee on what
Object will be (which should be irrelevant anyway)
It means that you can't use Void and do Observable.just(null).
Use Object or some other simple type instead:
Observable.just(new Object());
Starting with RxJava 2, the propper way to do this is to use a Completable
From the docs:
Represents a deferred computation without any value but only
indication for completion or exception. The class follows a similar
event pattern as Reactive-Streams: onSubscribe (onError|onComplete)?
One of the light solutions is to use Observable<Boolean>
And then onNext(Boolean.TRUE) which you then just ignore.
But probably you shouldn't use Observable in that case.
Consider using Completable instead
I don't know this will helps you or not.
The code written in RxSwift.
// Create an observable and emit somethings
let myObservable = Observable<Void>.create{ observer in
observer.on(.next(Void()))
return Disposables.create()
}
// Observer subscribe changes
myObservable.subscribe(onNext: {
_ in
print("Hello")
}).disposed(by: disposeBag)
Or use the Variable object
// Create a Variable object that contanins nothing
var myValueWatcher:Variable<Void> = Variable<Void>(Void())
// Observer subscribe changes
myValueWatcher.asObservable().skip(1).subscribe(onNext: {
_ in
print("Changes!")
}).disposed(by: disposeBag)
// The emit code
myValueWatcher.value = Void()

Java remove listener, when callback is executed

I just can't figure out how to remove listener when I have some event executed. I have some leaking issue using websockets, and this can probaly fix it.
final WebSocket w = asyncHttpClient.prepareGet(url)
.execute(new WebSocketUpgradeHandler.Builder().build())
.get();
w.addWebSocketListener(new WebSocketTextListener() {
public void onMessage(String message) {
listener.onMessage(responseMessage);
// Here is the place I want to do my w.removeWebSocketListener(l);
}
#Override
public void onFragment(String s, boolean b) {
}
public void onOpen(WebSocket websocket) {
}
#Override
public void onClose(WebSocket webSocket) {
}
#Override
public void onError(Throwable throwable) {
}
});
The problem is when I create WebSocketTextListener lis = new .... and passing in there is something like one object need other object and other object is dependent on this, and I'm still now allowed to do what I want.
Looks like it is something simple, but can't figure out.
Normally event listeners can be removed with a removeXXXListener method. But it requires that you provide the exact same event listener instance as parameter. You can store the event listener and later remove it using the same reference. But since you, in the onMessage message already are inside the scope of the event listener, using this should work.
Try something like
listener.onMessage(responseMessage);
// Here is the place I want to do my w.removeWebSocketListener(l);
w.removeWebSocketListener(this);
Using "this" in anonumous inner class is the way to solve problem. But, it is muck better to refactor code, to avoid using anonumous classes, for testability and better understanding.

Is it possible to create my own event listener list in Java containing multiple listener types?

I'm implementing a client-server system where the client is in a continuous blocking read loop listening for messages from the server. When a message is received I'd like to raise an "event" based on the type of the message, which other GUI classes may add listeners to. I'm more familiar with C# events so I am still getting used to the Java way of doing things.
There will be many message types so I will need an interface for each, call it MessageTypeAListener, MessageTypeBListener, etc., each of which will contain one handle method, which my GUI classes will implement. However, there will be be many types and instead of maintaining a list of listeners per type and having several "fire" methods I wanted to have one big listener list and a typed fire method. Then the fire method could say "only fire listeners whose type is what I specify."
So for example (pseudocode):
ListenerList.Add(MessageTypeAListener);
ListenerList.Add(MessageTypeBListener);
<T> fire(message) {
ListenerList.Where(type is T).handle(message)
}
...
fire<MessageTypeAListener>(message);
However, type erasure seems to be making this difficult. I could try casting and catching exceptions but that seems wrong. Is there a clean way of implementing this or is it just wiser to keep a separate list of listeners for every type, even though there will be tons of types?
I implemented something like this, cause I have a visceral dislike of Java's EventListenerList. First, you implement a generic Listener. I defined the listener based upon the Event it was receiving, with basically one method
interface GenericListener<T extends Event> {
public void handle(T t);
}
This saves you having to define ListenerA, ListernerB etc... Though you could do it your way with ListenerA, ListenerB, etc, all extending some base like MyListener. Both ways have plusses and minuses.
I then used a CopyOnWriteArraySet to hold all these listeners. A set is something to consider cause all too often listeners get added twice by sloppy coders. YMMV. But, effectively you have a Collection<GenericListener<T extends Event>> or a Collection<MyListener>
Now, as you've discovered, with type erasure, the Collection can only hold one type of listener. That is often a problem. Solution: Use a Map.
Since I'm basing everything upon the event, I used
Map<Class<T extends Event>, Collection<GenericListener<T extends Event>>>
based upon the class of the event, get the list of listeners who want to get that event.
Your alternative is to base it upon the class of the listener
Map<Class<T extends MyListener>, Collection<MyListener>>
There's probably some typos above...
Old-fashioned pattern approach, using Visitor pattern:
class EventA {
void accept(Visitor visitor) {
System.out.println("EventA");
}
}
class EventB {
void accept(Visitor visitor) {
System.out.println("EventB");
}
}
interface Visitor {
void visit(EventA e);
void visit(EventB e);
}
class VisitorImpl implements Visitor {
public void visit(EventA e) {
e.accept(this);
}
public void visit(EventB e) {
e.accept(this);
}
}
public class Main {
public static void main(String[] args) {
Visitor visitor = new VisitorImpl();
visitor.visit(new EventA());
}
}
More modern approach is just to have Map between classes of events, which should not derive each other, and respective handlers of these events. This way you avoid disadvantages of Visitor pattern (which is, you'll need to change all your visitor classes, at least, base of them, every time you add new Event).
And another way is to use Composite pattern:
interface Listener {
void handleEventA();
void handleEventB();
}
class ListenerOne implements Listener {
public void handleEventA() {
System.out.println("eventA");
}
public void handleEventB() {
// do nothing
}
}
class CompositeListener implements Listener {
private final CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<Listener>();
void addListener(Listener l) {
if (this != l)
listeners.add(l);
}
public void handleEventA() {
for (Listener l : listeners)
l.handleEventA();
}
public void handleEventB() {
for (Listener l : listeners)
l.handleEventB();
}
}
After going through iterations of just about everyone's suggestions here, I ended up going a very slightly modified route of the standard Listener interfaces and listener lists. I started with Swing's EventListenerList, only to be disappointed with the amount of add/remove methods for dozens of message types. I realized this could not be condensed while still maintaining a single EventListenerList, so I started thinking about a separate list for each type. This makes it similar to .NET events where each event holds its own list of delegates to fire when raised. I wanted to avoid tons of add/remove methods, so I made a quick Event class that just looks like this:
public class Event<T extends EventListener> {
private List<T> listeners = new ArrayList<T>();
public void addListener(T listener) {
listeners.add(listener);
}
public void removeListener(T listener) {
listeners.remove(listener);
}
public List<T> getListeners() {
return listeners;
}
}
Then I keep several instances of this class around, each typed according to a listener, so Event<MessageTypeAListener>, etc. My classes can then call the add method to add themselves to that particular event. I would've like to be able to call a generic Raise method on the Event instance to then fire all the handlers, but I did not want them to all have to have the same "handle" method, so this was not possible. Instead, when I'm ready to fire the listeners, I just do
for (MessageTypeAListener listener : messageTypeAEvent.getListeners())
listener.onMessageTypeA(value);
I'm sure this is not a new idea and has probably been done before and in better/more robust ways, but it's working great for me and I'm happy with it. Best of all, it's simple.
Thanks for all the help.
If you only have simple events, i.e. events without data or where all events have the same data types, enum could be a way forward:
public enum Event {
A,
B,
C
}
public interface EventListener {
void handle(Event event);
}
public class EventListenerImpl implements EventListener {
#Override
public void handle(Event event) {
switch(event) {
case A:
// ...
break;
}
}
}
public class EventRegistry {
private final Map<Event, Set<EventListener>> listenerMap;
public EventRegistry() {
listenerMap = new HashMap<Event, Set<EventListener>>();
for (Event event : Event.values()) {
listenerMap.put(event, new HashSet<EventListener>());
}
}
public void registerEventListener(EventListener listener, Event event) {
Set<EventListener> listeners = listenerMap.get(event);
listeners.add(listener);
}
public void fire(Event event) {
Set<EventListener> listeners = listenerMap.get(event);
for (EventListener listener : listeners) {
listener.handle(event);
}
}
}
Comments:
The switch statement in the EventListnerImpl may be omitted if it is only registered to a single event, or if it should always act in the same way regardless of which Event it receives.
The EventRegister has stored the EventListener(s) in a map, meaning that each listener will only get the kind of Event(s) that it has subscribed to. Additionally, the EventRegister uses Sets, meaning that an EventListener will only receive the event at most once (to prevent that the listener will receive two events if someone accidentally registers the listener twice).

How can I add similar functionality to a number of methods in java?

I have a lot of methods for logging, like logSomeAction, logAnotherAction etc.
Now I want all these methods make a small pause after printing messages (Thread.sleep).
If I do it manually, I would do something like this:
//before:
public static void logSomeAction () {
System.out.println (msg(SOME_ACTION));
}
//after:
public static void logSomeAction () {
System.out.println (msg(SOME_ACTION));
try {
Thread.sleep (2000);
} catch (InterruptedException ignored) { }
}
I remember that Java has proxy classes and some other magic-making tools. Is there any way avoid copy-n-pasting N sleep-blocks to N logging methods?
You could use Aspects to add extra "orthogonal" functionality to your methods.
If that sounds too esoteric, a simpler, down-to-earth solution would be to add the sleep in a separate method, then call that method in each of your logging methods. The first time you do this, you need to touch each method, but the next time if you want to modify the extra behaviour or add something else, you can do it in one single place.
It looks like you want to use Aspect Oriented Programming. You could use Spring for AOP, or AspectJ.
The OP mentions in a comment that the preferred solution is to use plain java proxies. The current code is implemented as static methods - for java proxies to be of any use, the logger class will need to be reworked as an interface. Something like this:
public interface SomeActionLogger
{
void logSomeAction();
void logSomeOtherAction();
// etc..
}
You then create your concrete implementation
public class SystemOutActionLogger implements SomeActionLogger
{
public void logSomeAction () {
System.out.println (msg(SOME_ACTION));
}
}
You can then have Java proxies wrap the SomeActionLogger interface
class DelayAfterInvocationHandler implements InvocationHandler
{
private Object delegate;
private int duration;
DelayAfterInvocationHandler(Object delegate, int duration)
{
this.delegate = delegate;
this.duration = duration;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
Object returnValue = method.invoke(delegate, args);
Thread.sleep(duration);
// you may want to catch InterruptedEception
return returnValue;
}
}
To hide some of the not-so-pretty proxy code, you can then have a method that wraps your logger to create the delay, e.g.
public ActionLogger addDelay(SomeActionLogger logger, int delay)
{
return (ActionLogger)Proxy.newProxyInstance(
impl.getClass().getClassLoader(),
new Class[] { SomeActionLogger.class },
new DelayAfterInvocationHandler(logger, delay));
}
So you then write
SomeActionLogger log = addDelay(new SystemOutActionLogger(), 2000);
Note that the DelayInvocationHandler is orthogonal to the logging interface - it can be used to add delay to any interface. You might then create a generic wrapping method like this:
public <T> T addDelay(T delegate, int delay, Class<T> interfaceType)
{
return (T)Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
new Class[] { type },
new DelayAfterInvocationHandler(delegate, delay));
}
Make a utility class that has a static SleepFor method which includes your try ... catch block and call that from every method you want a sleep in?
Replace all the System.out.println(msg(SOME_ACTION)); with printAndWait(SOME_ACTION);
You should be able to do that with find and replace.
Then create a method
public static void printAndWait(Object someAction) {
System.out.println (msg(someAction));
try {
Thread.sleep (2000);
} catch (InterruptedException ignored) {
Thread.currentThread.interrupt();
}
}
That way the code appears once and you can change it easily in one place.
Replace all of your logSomeAction() methods with a single logAction(Action a) method. This way, when you add more actions in the future, you will not be repeating your code for handling the action log and the thread sleep.

Categories