4

I am calling rabbitMQ client (and not server) from inside my Java code running in Glassfish V4.0 (build 89) container to connect to rabbitmq server on another machine. As per rabbitmq client document, we should supply a ManagedThreadFactory instance to rabbitmq connection for creating threads.

I tried injecting DefaultManagedThreadFactory using

ctx.lookup("java:comp/DefaultManagedThreadFactory")

That failed with

Lookup failed for 'java:comp/DefaultManagedThreadFactory' in SerialContext...

Trying @Resource(lookup="concurrent/__DefaultManagedThreadFactory") results in NPE.

I am not heavy into java EE and I am using this container just as a frontend for my jersey web services. Clearly I need to do something more/different. However I have been not able to locate much apart from

https://blogs.oracle.com/arungupta/entry/create_managedexecutorservice_managedscheduledexecutorservice_managedthreadfactory_contextservice

http://javahowto.blogspot.in/2011/02/how-to-create-and-look-up-thread-pool.html

Can any Java EE expert tell me the right Voodoo incantations to make this work?

Update-1

@Resource(name = "concurrent/__defaultManagedThreadFactory")
ManagedThreadFactory threadFactory;

// set on rabbitmq connection Factory
factory.setThreadFactory(threadFactory);


java.lang.NullPointerException
at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1312)
at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1233)
at java.util.concurrent.Executors.newFixedThreadPool(Executors.java:114)
at com.rabbitmq.client.impl.ConsumerWorkService.<init>(ConsumerWorkService.java:36)

Update-2

axel - there is nothing special about my case. Just trying a rabbitmq java client inside GFV4 is what I am looking at. so to reproduce the issues

  • You need to run rabbitmq server
  • connect to rabbitmq server using client code that is part of war deployed on GF
  • as per rabbitmq client API guide (https://www.rabbitmq.com/api-guide.html) @see Custom Thread Factory section. They are delegating thread instantiation to the container.
  • rabbitmq java client code is on Github

I can see ManagedThreadFactory name from GF Admin console so it should be there.

update-3

The Managed Thread Factory and Managed executor service can be located using JNDI. However the same resources cannot be injected into my code that uses Jersey web services. The resource injection works with a simple servlet example (e.g. java EE7 example on Github)

is this due to some interplay of jersey/Hk2/CDI/weld etc.? I am looking for an authorative answer to why I cannot make resource injection work?

rjha94
  • 4,292
  • 3
  • 30
  • 37

1 Answers1

1

I'm injecting the default managed thread factory like this in my Java EE projects that run on Glassfish 4:

@Singleton
@Startup
public class Messenger {
    @EJB
    MyMessenger me;

    @Resource(name = "concurrent/__defaultManagedThreadFactory")
    ManagedThreadFactory threadFactory;

    @Resource
    ManagedExecutorService executorService;

    @PostConstruct
    public void postConstruct() {
        me.waitAndInitialize();
    }

    @Asynchronous
    public Future<?> waitAndInitialize() {
        try {
            final AtomicInteger done = new AtomicInteger(0);
            int i = 0;

            while (done.intValue() == 0 && i < 20) {
                i++;
                getExecutorService().submit(
                        new Runnable() {

                            @Override
                            public void run() {
                                int incrementAndGet = done.incrementAndGet();
                            }
                        });

                Thread.sleep(500);
            }

            if (done.intValue() == 0) {
                Logger.getAnonymousLogger().severe("Waited a long time for the ExecutorService do become ready, but it never did. Will not initialize!");
            } else {
                init();
            }
        } catch (Exception e) {
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Exception in waitAndInitialize: " + e.getMessage(), e);
        }

        return new AsyncResult<>(null);
    }

    protected void init() {
        connectionFactory.setExecutorService(executorService);
        connectionFactory.setThreadFactory(threadFactory);

        // connect to rabbit and listen to queues
    }
}

Output of asadmin list-containers

List all known application containers
resources_ear
resources
ejb
weld
weld
grizzly
web
connector
webservices
appclient
jpa
jpa
ear
osgi
security
  • did you need to include any extra jar in your code (say inside eclipse) for compiling? I can try this and will let you know. – rjha94 Feb 05 '15 at 08:56
  • No extra jars, just the standard reference for Java EE 7. I'm using Netbeans by the way. – Per-Axel Felth Feb 05 '15 at 09:14
  • I am on eclipse and I have to manually copy java.enterprise.concurrent-api.jar. Maybe the way my eclipse is setup. Let me try this on GFV4 now. – rjha94 Feb 05 '15 at 10:31
  • hi @per-axel-felth tried but still getting NPE when I try to use the default managed thread factory. I can't ask you to try rabbitmq inside your GFV4, can I ;) – rjha94 Feb 05 '15 at 19:13
  • hi axel can you please post output of $asadmin list-containers from your machine? – rjha94 Feb 05 '15 at 19:58
  • I've updated my answer. Can you post more of your code and the complete stack trace? – Per-Axel Felth Feb 05 '15 at 20:27
  • I'm actually using the RabbitMQ client in Java EE on Glassfish. I updated my answer to include the code I'm using to initialize my app to listen to RabbitMQ queues. The waitAndInitialize method is a workaround for a Glassfish bug. GF behaves very strange when the RabbitMQ client tries to use the injected concurrency resources before the app is properly initialized. – Per-Axel Felth Feb 05 '15 at 21:04
  • Hi axel, my case is even simpler. I just want to write to rabbitmq message queue (producer) from GFv4. my cosumers are also on separate machine. plus I dont have EJB, message bean etc. Let me try again tonight. – rjha94 Feb 06 '15 at 13:28
  • axel I am still trying. So far I have not managed to inject MTF as resource inside my class. I am not sure why. is there any other way I can grab a concrete instance of MTF inside my code from GF apart from resource injection? Also, do you know any way to debug if resource lookup fails? – rjha94 Feb 15 '15 at 19:15
  • Is your jax-rs resource class a stateless EJB? You need to post your class source code for to be able to help you. – Per-Axel Felth Feb 16 '15 at 20:31