I'm trying to make an annotation-based event system where like you would register a class implementing an interface and then you can use the events that have an #interface above the methods that are called. Like so:
Wherever.java
EventManager.callEvent(new HelloEvent);
EventManager.register(new ClassThatImplementsListeenr);
#EventHandler
public void onHello(HelloEvent event) {
event.sayHello();
}
Ok I understand a lot of this like registering (adds them to arraylist) and making a listener interface plus Event interface. New Events will implement Event, and an #Interface called EventHandler that will only work with methods. THE MAIN part is what I don't get. How to invoke and check for the annotation.
EDIT I JUST MADE THIS, WOULD IT WORK?
Public class EventManager {
private static List<Listener> registered = new ArrayList<Listener>();
public static void register(Listener listener) {
if (!registered.contains(listener)) {
registered.add(listener);
}
}
public static void unregister(Listener listener) {
if (registered.contains(listener)) {
registered.remove(listener);
}
}
public static List<Listener> getRegistered() {
return registered;
}
public static void callEvent(final Event event) {
new Thread() {
public void run() {
call(event);
}
}.start();
}
private static void call(final Event event) {
for (Listener listener : registered) {
Method[] methods = listener.getClass().getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(EventHandler.class)) {
try {
method.invoke(listener.getClass().newInstance(), event);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
}
}
You can check for annotations that have been added to a method by
Retrieving all the methods that are available on a class:
public void registerListeners(T handler){
Method[] allMethods = handler.getClass().getMethods();
}
Check all the methods that have your desired annotation (although I would imagine only one method in any given class should be designated with an event listener-type annotation)
List<Method> listenerMethods = new ArrayList<Method>();
for (Method aMethod: allMethods){
if(aMethod.isAnnotationPresent(EventHandler.class)){
listenerMethods.add(aMethod);
}
}
Given the specific methods that have the annotation, you could call Method#invoke on the shortlist of methods to execute the listener.
Related
I have to use an 3th party library to create a java driven plc. in this library you have to define the IO's etc and then you will auto generate some code to acces the IO. this will generate a lot of code which i want to split up to keep readable.
The BIhcs_Io class is where everything on the event driven plc is executed. Each time a value of a property changes (see example below of property) it will run the doExecute() method.
What i want to do is that when this method is called, instead i want to execute it on the child class.
any help would be greatly appreciated!
public class BIhcs_IO extends BComponent implements Runnable {
//Example of a created property for a PLC IO
public static final Property bool_1 = newProperty(Flags.EXECUTE_ON_CHANGE | Flags.OPERATOR | Flags.SUMMARY, ((BBoolean)((BValue)BBoolean.TYPE.getInstance())).getBoolean(), BFacets.tryMake(null));
public boolean getBool_1() { return getBoolean(bool_1); }
public void setBool_1(boolean v) { setBoolean(bool_1, v, null); }
public static final Action execute = newAction(Flags.ASYNC, null);
public void execute() { invoke(execute, null, null); }
#Override
public Type getType() { return TYPE; }
public static final Type TYPE = Sys.loadType(BIhcs_IO.class);
public BComponent getComponent() {
return this;
}
public void started() throws Exception {
}
//When the Property bool_1 changes it wil execute the doExecute() method below
public void changed(final Property prop, final Context cx) {
super.changed(prop, cx);
if (!this.isRunning()) {
return;
}
if (Flags.isExecuteOnChange((BComplex) this, (Slot) prop)) {
this.execute();
}
}
public void run() {
System.out.println("Source BProgram did not override run(). Exiting thread.");
}
//This is called when a property changes value. When this is called, instead of executing this i want to execute the code in BIhcsMain()
public void doExecute() throws Exception {
setDebug_1("called parent")
}
public void stopped() throws Exception {
}
}
Below is the child class that extends the parent class. Each time the doExecute() in the parent is called i want to override it and execute the one in the child class instead.
public class BIhcsMain extends BIhcs_IO {
#Override
public void doExecute(){
setDebug_2("called child");
}
}
Consider a method
public void doSomething(String actionID){
switch (actionID){
case "dance":
System.out.print("I'm dancing");
break;
case "sleep":
System.out.print("I'm sleeping");
break;
default:
System.out.print("I've no idea what I'm doing");
}
The implementation of the method depends on the value of the parameter. Is there a more elegant way to do this, or a different design pattern to replicate the behaviour?
If the caller decides what logic is executed by passing different strings, then why not just have them call different methods:
public void doSomething(String actionID) {...}
...
doSomething("dance");
doSomething("sleep");
VS.:
public void dance() {...}
public void sleep() {...}
...
dance();
sleep();
It seems like you're unnecessarily funnelling all the calls into doSomething
But the strings might not always be literals. What if you're taking them from the console?
You could provide static mappings from the strings to the corresponding functions:
class MyClass {
private static final Map<String, Consumer<MyClass>> map = new HashMap<>();
static {
map.put("sleep", MyClass::sleep);
map.put("dance", MyClass::dance);
}
public void doSomething(String actionID) {
map.getOrDefault(actionID, MyClass::doNothing).accept(this);
}
public void dance() {
System.out.print("I'm dancing");
}
public void sleep() {
System.out.print("I'm sleeping");
}
private void doNothing() {
System.out.println("I've no idea what I'm doing");
}
}
This makes scenarios where you have a lot of switch cases a lot cleaner.
Introduce an interface, e.g.
public interface HumanState {
public void tellMeWhatYouAreDoing();
}
encapsulate the logic in different implementations
public class DancingState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I'm dancing");
}
}
public class SleepingState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I'm sleeping");
}
}
public class UnknownState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I've no idea what I'm doing");
}
}
and use a map. E.g.
public class HumanStateExample {
public static void main(String[] args) {
HumanStateExample humanStateExample = new HumanStateExample();
humanStateExample.doSomething("dance");
humanStateExample.doSomething("sleep");
humanStateExample.doSomething("unknown");
}
private final HashMap<String, HumanState> humanStateMap;
public HumanStateExample(){
humanStateMap = new HashMap<String, HumanState>();
humanStateMap.put("dance", new DancingState());
humanStateMap.put("sleep", new SleepingState());
}
public void doSomething(String action) {
HumanState humanState = humanStateMap.get(action);
if(humanState == null){
humanState = new UnknownState();
}
humanState.tellMeWhatYouAreDoing();
}
}
I'm not sure how the pattern is called, but it is very useful if you need to delegate the method call based on more than one parameter:
Create a lot of handlers where each one knows when it is responsible for handling a call. Then just loop through them and invoke the first one matching the parameter.
edit: I renamed the class from FancyParameterActionFactory to FancyParameterActionUtility: it is not a factory, the name was misleading
//Your method, but this time with a complex object, not with a simple string.
public void doSomething(FancyParameterObject fpo){
FancyParameterActionUtility.invokeOn(fpo);
}
//The utility which can handle the complex object and decides what to do.
public class FancyParameterActionUtility{
public Interface FPAHandler{
void invoke(FancyParameterObject fpo);
boolean handles(FancyParameterObject fpo);
}
//Omitted: Different implementations of FPAHandler
public static List<FPAHandler> handlers = new LinkedList<>();
static{
handlers.add(new DanceHandler());
handlers.add(new SleepHandler());
//Omitted: Different implementations of FPAHandler
}
public static void invokeOn(FancyParameterObject fpo){
for(FPAHandler handler:handlers){
if (handler.handles(fpo)){
handler.invoke(fpo);
return;
}
}
//Default-Behavior
}
}
Here is a simple implementation of the command pattern based your sample problem. I define a general AbstractCommand abstract class which contains two methods. The first method, createCommand(), instantiates a command class based on an input string name. This is how you can delegate your string input to create the right type of command. The second method is doAction(), and this is left undefined, to be implemented later on by specific concrete command classes.
public abstract class AbstractCommand {
public static AbstractCommand createCommand(String name) {
try {
String clsName = name + "Command";
Class<?> cls = Class.forName(clsName);
AbstractCommand command = (AbstractCommand) cls.newInstance();
return command;
}
catch (Exception e) {
System.out.println("Something went wrong.");
}
}
public abstract void doAction();
}
public class DanceCommand extends AbstractCommand {
public void doAction() {
System.out.println("I'm dancing");
}
}
public class TestCommandPattern {
public void doSomething(String actionID) {
AbstractCommand cmd = AbstractCommand.createCommand(actionID);
cmd.doAction();
}
public static void main(String[] args) {
TestCommandPattern test = new TestCommandPattern();
test.doSomething("Dance"); // should print "I'm dancing"
}
}
Now that this framework has been setup, you could easily add other commands for the various types of actions in your original problem. For example, you could create a SleepCommand class which would output I'm sleeping, or do whatever action you wish.
I have an abstract class Action with children like SendMessageAction.
I would like to run these actions in a service but how could I force implementation of each child ?
For example I would like to implement an abstract method : void run(Action action)
and methods "run" for each possible Action with an error if some methods are missing.
Any idea ?
Something like below should help you to get started. Happy coding!
Action.java
public abstract class Action {
protected abstract void runAction();
}
MessageSenderAction.java
public class MessageSenderAction extends Action {
public void runAction() {
//send message
}
}
SomeOtherAction.java
public class SomeOtherAction extends Action {
public void runAction() {
//do something else
}
}
ActionHandler.java
public class ActionHandler {
private final static ActionHandler INSTANCE = new ActionHandler();
private ActionHandler() {}
public static ActionHandler getInstance() {
return INSTANCE;
}
private List<Action> allActions = new ArrayList<Action>();
public void addAction(Action action) {
allActions.add(action);
}
public void runAllActions() {
for(Action action: allActions) {
//just to handle exception if there is any. Not to hamper other actions in case of any failures
try {
action.runAction();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
ActionDemo.java
public class ActionDemo {
public static void main(String... args) {
ActionHandler actionHandler = ActionHandler.getInstance();
Action msgSenderAction = new MessageSenderAction();
Action someOtherAction = new SomeOtherAction();
actionHandler.addAction(msgSenderAction);
actionHandler.addAction(someOtherAction);
actionHandler.runAllActions();
}
}
I'm working on a game engine, and the last question I had regarding this was what good way I can use to make "observers" or listeners. A user suggested that I should use Java's EventObject class to inherit from and make a Listener interface. However, this didn't provide me with good flexibility.
Here is the Handler annotation to state that a method is an event handler in a listener:
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.METHOD)
public #interface Handler {}
Here is the base class for Event, which is basically the same as EventObject (but I'll add abstract methods sooner or later):
public abstract class Event {
private Object source;
public Event(Object source) {
this.source = source;
}
public Object getSource() {
return source;
}
}
Here is the Listener class, which is empty:
public interface Listener {}
Here is the ListenerHandler class, used to handle all listeners. You register and unregister them here. I'll edit the register/unregister methods later for a better use:
public class ListenerHandler {
private ArrayList<Listener> listeners;
public ListenerHandler() {
this.listeners = new ArrayList<Listener>();
}
public void registerListener(Listener l) {
listeners.add(l);
}
public void unregisterListener(Listener l) {
listeners.remove(l);
}
public void onEvent(Event event) {
for(Listener l : listeners) {
Class<?> c = l.getClass();
Method[] methods = c.getDeclaredMethods();
for(Method m : methods) {
if(m.isAccessible()) {
if(m.isAnnotationPresent(Handler.class)) {
Class<?>[] params = m.getParameterTypes();
if(params.length > 1) {
continue;
}
Class<?> par = params[0];
if(par.getSuperclass().equals(Event.class)) {
try {
m.invoke(this, event);
}catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
From what I heard, it's a use of a lot of memory in order to get all methods of a class. I'm not going to assume this is the case, but I'm sure there is a better way as this will be a game engine with many components and such.
I'd like to know the best way to implement this, or if I'm doing it right. I'd also like to know if anyone can help me improve this in any way without hogging memory usage by the game (as of now it's not a big deal -- the "game engine" is not even close to rendering anything yet)
I tried to keep it a very simple example and will comment with different ideas to it:
First meet the Achievement class:
import java.util.Observable;
public class Achievement extends Observable {
public static class AchievementDetails {}
public Achievement() {
addObserver(EventsListener.getInstance());
}
public void achievementReached() {
AchievementDetails achievemetDetails = null;
setChanged();
notifyObservers(achievemetDetails);
}
}
And then the events listener class:
import com.test.Achievement.AchievementDetails;
public class EventsListener implements Observer {
private static EventsListener instance = new EventsListener();
public static EventsListener getInstance() {
return instance;
}
#Override
public void update(Observable o, Object arg) {
if(o instanceof Achievement) {
AchievementDetails achievemetDetails = (AchievementDetails) arg;
//do some logic here
}
}
}
The only one thing that is missing is to create an instance of your achievement (which register the EventsListener to itself) and handle the life cycle of it.
I have an addProductButton, click it and it brings up a DialogBox containing bookNameTextBox, bookCategoryTextBox and addBookButton. Click addBookButton, it inserts the bookNameTextBox and bookCategoryTextBox contents into a database. If successful, it should hide the DialogBox and updateList()
The following code works to accomplish that but I'm not sure if it's proper or if there is a better way to achieve the same results.
Main class
addProductButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
//display addBookDialogBox
AddBookDialog abd = new AddBookDialog();
abd.displayDialog(new Callback() {
#Override
public void onSuccess() {
updateList();
}
public void onFailure() {
}
});
}
});
public void updateList() {
}
AddBookDialog class
public class AddBookDialog extends DialogBox {
private Callback callback;
private static AddBookDialogUiBinder uiBinder = GWT
.create(AddBookDialogUiBinder.class);
interface AddBookDialogUiBinder extends UiBinder<Widget, AddBookDialog> {
}
public AddBookDialog() {
setWidget(uiBinder.createAndBindUi(this));
}
public void displayDialog(Callback callback2) {
callback = callback2;
this.center();
}
#UiHandler("addBookButton")
void onAddBookButtonClick(ClickEvent event) {
//save book to database
Database db = Database.openDatabase("Store", "1.0", "My Store", 5 * 1024 * 1024);
db.transaction(new TransactionCallback() {
public void onTransactionStart(SQLTransaction tx) {
tx.executeSql("INSERT INTO products (bookName, bookCategory) VALUES (?, ?)", new Object[] { bookNameTextBox.getText().toString(), bookCategoryTextBox.getText().toString() });
}
public void onTransactionFailure(SQLError error) {
}
public void onTransactionSuccess() {
callback.onSuccess();
}
});
this.hide();
}
}
Callback interface
public interface Callback {
void onSuccess();
void onFailure();
}
I don't see the use of it here, why don't you just put updateList(); inside the onTransactionStart() method ?
CallBacks are used for Asynchronism, and the TransactionCallback here already does that, so I don't see why you would use another callback inside.
And by the way, if you did need a callback, why don't you use the AsyncCallback provided by gwt?
EDIT :
Then the appropriate way is to make an interface with your updateList() method. Make your main class implement it, and change the parameter type of your displayDialog() method to your interface type instead of CallBack type.