google / guice

Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought to you by Google.
https://github.com/google/guice
Apache License 2.0
12.51k stars 1.67k forks source link

GuiceResteasyBootstrapServletContextListener Guice is initialized before resteasy boots up #1315

Closed deepak229 closed 4 years ago

deepak229 commented 4 years ago

Reference: https://stackoverflow.com/questions/61330943/guice-resteasy-jaxrs-integration

I am loading Resteasy Resources through subclass of javax.ws.rs.Application I am using GuiceResteasyBootstrapServletContextListener to initialize Guice So I expect the resteasybootstrap to finish loading before Guice is initialized.

in my module class, I am trying to get all singletons of javax.ws.rs.Application and injectMembers to it.

            MyWebApplication.get().getSingletons().forEach(api -> requestInjection(api));

I found out that MyWebApplication is not yet loaded when the control reaches my Module class as a result I encounter Nullpointer.

Is there any way to wait till the rest resources are loaded to resteasy and then initiate the Guice Injection?

GedMarc commented 4 years ago

Hey @deepak229

My experience with resteasy on guice was less than desirable, i got it working but only after tons of hours, also only on resteasy 4, resteasy 3 was not usable at all. By the end of it all, ended up with https://issues.redhat.com/browse/RESTEASY-2110?_sscc=t , unfortunately i had to walk away from it entirely as the resolution was "we will not support java module system" - so i had to walk away.

What I did manage to do however, was get CXF running perfectly with very little effort, even getting JLink images out was a breeze, because of this i'm going to recommend that you rather step away from resteasy, it is designed for CDI and does not play nice with any other libraries.

You can find my implementation here for guice - a simple overload of the servlet and it goes like a boeing, not the 747max.

https://github.com/GedMarc/JWebMPDevKit/tree/master/GuicedEE/Services/commons/apache-cxf/src

You can also grab this library at https://mvnrepository.com/artifact/com.guicedee.services/org.apache.cxf

I hope you come right, it is possible, but is it worth the effort.

GedMarc commented 4 years ago

Woops - thats the jlink cxf

Guice CXF Impl here https://github.com/GedMarc/GuicedRestServices

Maven location here https://mvnrepository.com/artifact/com.guicedee.servlets/guiced-rest-services

Guide and stuffs here - www.guicedee.com

deepak229 commented 4 years ago

Thanks @GedMarc for the reply. Unfortunately, I cannot walkaway from resteasy :( I am doing a POC of migration of an existing web app thats in production to start using Guice. Resteasy is used heavily. So, moving away from resteasy is not an option for me.

I am one step away from getting it all working. The only problem I am seeing is that the Listener need to wait till the resteasy classes are loaded, or I need to createInjector again and bind the resteasy classes. it loads the rest classes probably twice. but does it matter? Probably not.

I really want to get a way where the GuiceResteasyBootstrapServletContextListener is aware of the resteasy deployment and kicks off only after resteasy is loaded.

GedMarc commented 4 years ago

Well.. RestEasy is just a JaxRS Implementation, not even the RI but a custom implementation of it. Switching across doesn't impact you at all.

You should really advise that they use a framework that is forward compatible providing the exact same functionality. Resteasy is not forwards compatible at all, and will not ever be. If you are moving an EE project across (which is definitely the correct move, EE is dead, picking it up from the garbage and renaming it isn't a solution. It was canned because current technology has superseded it) - you will need to take these things into consideration

Yes it is an ordering thing, I'll see if i can find my backup which I got working for you, but it definitely is the wrong approach to use it, and i don't believe you should continue down that path.

This is why we have specifications, and implementations. To swap out implementations when it no longer is relevant to your architecture.

Rather stay away from projects locked into JDK 8, and will forever be, and use the implementations that embrace JDK 9 and up

GedMarc commented 4 years ago

I really hope I do not get put onto your project - or get your architects on any of mine. ever

But here is the working commit for the servlet module rest easy - This is truly and deeply the wrong path you are taking, especially for starting a new project, and especially that it is a POC. I strongly advise you reconsider your position, and if need be speak to your powers that be and give them the biggest slap across their face that you can possibly manage, maybe use a cricket bat.

NB FOR EVERYONE ELSE!!! - THIS IS THE WRONG IMPLEMENTATION TO GO WITH, DO NOT DO THIS. YOU HAVE BEEN WARNED. YOU WILL NOT GET ANY PERFORMANCE OR ANY BENIFIT AT ALL. YOU WILL MAKE YOUR LIFE HELL IN THE NEAR FUTURE.

@Override
    public void onBind()
    {
        install(new JaxrsModule());
        bind(GuiceResteasyBootstrapServletContextListener.class).in(Singleton.class);
        bind(HttpServletDispatcher.class)
              .in(Singleton.class);

        if (path == null)
        {
            module.serve$("/*")
                  .with(HttpServletDispatcher.class);
        }
        else
        {
            final Map<String, String> initParams =
                    ImmutableMap.of("resteasy.servlet.mapping.prefix", path);
            module.serve$(path + "/*")
                  .with(HttpServletDispatcher.class, initParams);
        }
    }

Then you have to register the handler in your web container, i used undertow

public class RestEasyUndertowServletExtension
        implements ServletExtension
{
    @SuppressWarnings("unchecked")
    @Override
    public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext)
    {
        LogFactory.getLog("RestEasyUndertowRegistration")
                  .config("Registering Rest Easy Servlet Context Listener");
        InstanceFactory guiceInstanceFactory = new ImmediateInstanceFactory<>(GuiceContext.get(GuiceResteasyBootstrapServletContextListener.class));
        deploymentInfo.addListener(new ListenerInfo(GuiceResteasyBootstrapServletContextListener.class, guiceInstanceFactory));
    }
}

https://github.com/GedMarc/GuicedRestServices/commit/278127f1a3f4d8bf4a013ec1104b68ce245edf7b#diff-fcf278d175642d1cc5e1b9a77080bf58R31

I truly hope you fight back, and i will never work with your company, even by gunpoint.

GedMarc commented 4 years ago

close this issue, there is no issue. this is a user support request and should have been placed on gitter.

deepak229 commented 4 years ago

Closing this issue as per the above comment.