mikee
mikee

Reputation: 335

Events containing Consumer are ignored

I have been trying to recreate Adam Bein's video Going Asynchronous with CompleteableFuture and JavaEE 7), essentially it's firing an event containing a Consumer and observing it in another class. In the video he is using the "LambdaFish" application server, I couldn't find any other references to this so I tried running the code with WAS Liberty, Glassfish 4 and Wildfly. All produced the same result, i.e. no Consumer event was observed. I tried various other classes in my test case and all worked perfectly, only Consumer appears to demonstrate the problem.

I haven't found a suitable way to trace what is going on "under the covers", my hope was to trace a working and non working event and see where we go "off the rails".

This is a simple problem to recreate using the following code :-

Producer

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.inject.Inject;

@Stateless
@LocalBean
public class Producer {
    @Inject Event<Consumer<String>> ce;
    @Inject Event<List<Object>> oe;
    
    public void produce() {
        Consumer<String> c = (x) -> System.out.println(x.toLowerCase());
        ArrayList<Object> al = new ArrayList<Object>();
        System.out.println("Firing Events");
        ce.fire(c);
        oe.fire(al);
        System.out.println("Events fired");
    }
}

Observer

package event.controller;


import java.util.ArrayList;
import java.util.function.Consumer;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.event.Observes;

@Singleton
@Startup
public class Observer {
    
    public void onStuff(@Observes Consumer<String> cs) {
        System.out.println("consumer event triggered");
        cs.accept("Hi There");
    }
    
    public void onStuff2(@Observes ArrayList<Object> al) {
        System.out.println("ArrayList event triggered");
    }
}

This is just one of many permutations and combinations I have tried; all with no success. I also tried setting up Glassfish tracing as described in this article Glassfish Tracing with log4j, the article seems out of date. I wasn't able to start Glassfish under eclipse using the plugin, when I tried to define a server I got an "internal error".

I also tried the WAS Liberty CDI tracing using =info:JCDI=all:com.ibm.ws.webbeans=all:org.apache.webbeans*=all:org.jboss.weld*=all:com.ibm.ws.cdi*=all:EJBContainer=all:MetaData=all:Injection=all

but there were no trace events triggered during the event.fire().

Is there something fundamentally wrong with what I am doing?

Has anyone managed to fire an event containing a Consumer and observe it successfully?

Does anyone know of any trace tools that can be used to determine why one case works and the other does not?

Thanks in advance for any comments and/or suggestions.

Upvotes: 2

Views: 367

Answers (1)

Siliarus
Siliarus

Reputation: 6753

You are doing it right, but you have stumbled upon a known bug in Weld (CDI reference implementation) which is what all the servers you named above use. I am not sure Open Web Beans (alternative CDI impl) have any better solution for this but you can check.

The relevant Weld tracking issue can be found here and a CDI spec issue linked to it can be found here. Once those are resolved, you should be able to execute your code.

The only "workaround" I can think of is to use raw type observer. That is:

public void onStuff(@Observes Consumer cs) {
        System.out.println("consumer event triggered");
        cs.accept("Hi There");
}

This observer is of course more general and will trigger for any other fired event with Consumer payload, but you are free to do some additional checking inside the method to determine whether you really want to trigger any action or not.

Upvotes: 2

Related Questions