OnWave Annotation

31 views
Skip to first unread message

Darko Čvagić

unread,
Sep 18, 2015, 8:07:19 AM9/18/15
to JRebirth Users
Hello,

This is my first post in this group, so excuse me if I missed something.

I'm trying to use JRebirth in my business applications, and have success (littler or more) so far. 
Now, I'm working on application with heavily use of Waves.

Current status definition:
I have a model in which I want to receive some data from wave.

Wave definition: (the wave is defined in ErrorPageService.class)

public static final Wave MESSAGE_WAVE = Builders.wave().waveGroup(WaveGroup.RETURN_DATA);
public static final WaveType MESSAGE_WAVE_TYPE = Builders.waveType("GET_MESSAGE")
            .items(JRebirthItems.voidItem)
            .returnAction("GET_MESSAGE_DONE")
            .returnItem(ERROR_MESSAGE);

In my model I have to define function 
public void doGetMessageDone(String message, final Wave wave){ 
 ....
}
somewhere in init model have to call 
listen(ErrorPageService.MESSAGE_WAVE_TYPE.returnWaveType());
and finally when I want to receive a message I have to call
getModel().returnData(ErrorPageService.class, ErrorPageService.MESSAGE_WAVE_TYPE);


if I have to listen for more waves, I have to call listen method for every wave type, and define method for listening every wave. 
I tried to use OnWave annotation, and this is very good approach.  Now I don't need to call listen method for every wave because it is already done in model construction.

Just define : 
@OnWave(value="GET_MESSAGE_DONE")
public void doGetMessageDone(String message, final Wave wave){ 
 ....
}
and it is registered for listening wave.

Problem definition:

If I have more similar waves with different types of messages, I have to create different method for receiving every of them, and they must have name like doGetMessage1Done, doGetMessage2Done....etc.
Why OnWave annotation don't understand its annotated method, why annotated methods must have strict names?
Then I could write something like

@OnWave(value="GET_MESSAGE1_DONE")
public void getMessage1(String message, final Wave wave){
.....
}
@OnWave(value="GET_MESSAGE2_DONE")
public void getMessage2(String message, final Wave wave){
.....
}

and more likely 
@OnWaves( 
      { 
          @OnWave(value="GET_MESSAGE1_DONE"),
          @OnWave(value="GET_MESSAGE2_DONE")
      } 
 )
(value="GET_MESSAGE_DONE")
public void getMessage(String message, final Wave wave){
.....
}


OK, I found partial solution in ComponentEnhancer class, you have method
public static void manageOnWaveAnnotation(final Component<?> component) {
        // Retrieve class annotations (Java 8 add support for repeatable annotations)
        for (final OnWave clsOnWave : component.getClass().getAnnotationsByType(OnWave.class)) {
            manageUniqueWaveTypeAction(component, clsOnWave.value(), null);
        }
        // Iterate over each annotated Method and all annotations
        for (final Method method : ClassUtility.getAnnotatedMethods(component.getClass(), OnWave.class)) {
            for (final OnWave clsOnWave : method.getAnnotationsByType(OnWave.class)) {
                manageUniqueWaveTypeAction(component, clsOnWave.value(), null);
            }
        }
    }
In second part of the method you have to change
manageUniqueWaveTypeAction(component, clsOnWave.value(), null);
into
manageUniqueWaveTypeAction(component, clsOnWave.value(), method);
 
this solves the problem of naming receiving methods.
now you can define 
@OnWave(value="GET_MESSAGE1_DONE")
public void whatEverName(String message, final Wave wave){
.....
}

But, what with multiple wave listener method (Method which listen multiple waves types), like I mention in @OnWaves annotation?


Uff, this post is long, but I think it is clear, and maybe someone will learn from it, like I am, reading other posts.

Tnx.

Darko

Sebastien Bordes

unread,
Sep 18, 2015, 9:05:30 AM9/18/15
to jrebirth-users
Hi Darko,

Welcome aboard ! I'm always pleased to hear about new JRebirth users writing nice JavaFX applications.

I understand the confusion around OnWaves used on methods, it was primarly designed for type usage (on the top of the class).

So I will reviewed your proposition to handle several WaveType by a same annotated method, I will check if the omission of method parameter was a bug or wanted (it's certainly a copy/paste bug).


However I do'nt understand why you don't use a generic Wave Type for the returned Wave sent by all your services like this:


WaveType STRING_WAVE_TYPE = Builders.waveType("STRING")
            .items(JRebirthItems.stringItem);

WaveType SERVICE1_WAVE_TYPE = Builders.waveType("GET_SERVICE1")
            .returnWaveType(STRING_WAVE_TYPE)
            .returnItem(ERROR_MESSAGE);

Thus a unique WaveType handler will be required.

@OnWave(value="STRING")

public void whatEverName(String message, final Wave wave){
.....
}

Let me know your thoughts.

Seb

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "JRebirth Users".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse jrebirth-user...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.



--

Sebastien Bordes

unread,
Sep 18, 2015, 9:12:14 AM9/18/15
to jrebirth-users
Definitely the code mentionned has a bug (fixed in bold like you wrote) !

public static void manageOnWaveAnnotation(final Component<?> component) {
        // Retrieve class annotations (Java 8 add support for repeatable annotations)
        for (final OnWave clsOnWave : component.getClass().getAnnotationsByType(OnWave.class)) {
            manageUniqueWaveTypeAction(component, clsOnWave.value(), null);
        }
        // Iterate over each annotated Method and all annotations
        for (final Method method : ClassUtility.getAnnotatedMethods(component.getClass(), OnWave.class)) {
            for (final OnWave clsOnWave : method.getAnnotationsByType(OnWave.class)) {
                manageUniqueWaveTypeAction(component, clsOnWave.value(), method);
            }
        }
    }

You can send a pull request if you want to contribute, otherwise I will push it this evening on 8.x-hotfixes branch for future 8.0.4 version

Thanks for your report

Seb

Darko Čvagić

unread,
Sep 18, 2015, 11:01:45 AM9/18/15
to JRebirth Users
Hi Sebastien,


However I do'nt understand why you don't use a generic Wave Type for the returned Wave sent by all your services like this:


WaveType STRING_WAVE_TYPE = Builders.waveType("STRING")
            .items(JRebirthItems.stringItem);

WaveType SERVICE1_WAVE_TYPE = Builders.waveType("GET_SERVICE1")
            .returnWaveType(STRING_WAVE_TYPE)
            .returnItem(ERROR_MESSAGE);

Thus a unique WaveType handler will be required.

@OnWave(value="STRING")
public void whatEverName(String message, final Wave wave){
.....
}

Let me know your thoughts.


Yes, you are wright!
It is just another approach of the same problem. If I knew  this, maybe I would write this post.  :)

You just make some 'group type' of returning wave types, and then waves which returns this 'group type'.
In this approach I will receive every wave from what ever type which returns this 'group type'.

In my approach I want to receive just some of them, specially defined on OnWave annotation.
This is just my opinion!

But, read my next post in which I discover the solution!

Tnx 

Sebastien Bordes

unread,
Sep 18, 2015, 11:09:33 AM9/18/15
to jrebirth-users
You can also apply filtering by using WaveChecker

something like this

listen(myWaveChecker, STRING_WAVE_TYPE);


instead of using OnWave annotation.

Let me know if you need another patch than the missing method into manageOnWaveAnnotation


Seb

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "JRebirth Users".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse jrebirth-user...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.
Message has been deleted

Darko Čvagić

unread,
Sep 18, 2015, 11:30:22 AM9/18/15
to JRebirth Users
Let me know if you need another patch than the missing method into manageOnWaveAnnotation


Seb


Thanks to the acceptance of the proposal to correct errors

The second solution for multiple waves on single handler is described here. 
I just analyze the code for @OnWave and @OnWaves annotation and discovered this:
 
Declaration for @OnWave annotation has @Repeatable annotation and it's container is OnWaves. It's target is TYPE and METHOD
This is good to start

declaration for @OnWaves annotation has target set to TYPE and METHOD.
The problem is that in code is never tested annotations OnWaves against methods in some class.
Now it does not metter, because of java 8 testing repeatable annotation.

method getAnnotatedMethods in ClassUtility:


public static List<Method> getAnnotatedMethods(final Class<?> cls, final Class<? extends Annotation> annotationClass) {
        final List<Method> methodList = new ArrayList<>();

        for (final Method m : cls.getDeclaredMethods()) {
            if (m.getAnnotation(annotationClass) != null) {
                methodList.add(m);
            }
        }

        // Add implemented interfaces methods
        for (final Class<?> i : cls.getInterfaces()) {
            methodList.addAll(getAnnotatedMethods(i, annotationClass));
        }

        // Add super class methods
        if (cls.getSuperclass() != null) {
            methodList.addAll(getAnnotatedMethods(cls.getSuperclass(), annotationClass));
        }

        return methodList;
    }

The firs for loop is testing annotation against method in old (pre 8) way. It have to be replaced with:

        for (final Method m : cls.getDeclaredMethods()) {
            Annotation[] annotations = m.getAnnotationsByType(annotationClass);
            if (annotations.length>0) {
                methodList.add(m);
            }
        }

The difference is testing against repeatable annotations. I just tested the code and it works.

TEST1: pre 8 way  WORKS

@OnWaves(
  {
    @OnWave(value="GET_MESSAGE_DONE"),
    @OnWave(value="TEST")
  }
)
public void whatEverName(String message, final Wave wave){
....
}


TEST2: java 8 (repeatable annotations)  WORKS
@OnWave(value="GET_MESSAGE_DONE")
@OnWave(value="TEST")
public void whatEverName(String message, final Wave wave){
....
}

TEST3: the smaller code,  WORKS
@OnWave("GET_MESSAGE_DONE")
@OnWave("TEST")

Darko Čvagić

unread,
Sep 18, 2015, 11:38:24 AM9/18/15
to JRebirth Users

LESS CHANGES IN CODE:
        for (final Method m : cls.getDeclaredMethods()) {
            if (m.getAnnotation(annotationClass) != null) {
                methodList.add(m);
            }
        }

TO
 
        for (final Method m : cls.getDeclaredMethods()) {
            if (m.getAnnotationsByType(annotationClass).length>0) {
                methodList.add(m);
            }
        }

tnx 

Darko Čvagić

unread,
Sep 18, 2015, 11:42:41 AM9/18/15
to JRebirth Users
With these two correction in code, I think both annotation @OnWaves and @OnWave works like charm!
Tnx

Sebastien Bordes

unread,
Sep 19, 2015, 5:37:37 AM9/19/15
to jrebirth-users
I pushed the 2 changes on github 8.x-hotfixes branch, a build has been performed so you can grab 8.0.4-SNAPSHOT version from OJO

Have a nice week-end

Seb

Le 18 septembre 2015 17:42, Darko Čvagić <darko....@gmail.com> a écrit :
With these two correction in code, I think both annotation @OnWaves and @OnWave works like charm!
Tnx

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "JRebirth Users".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse jrebirth-user...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages