Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency injection failling #1

Closed
erickgr2 opened this issue Jul 27, 2020 · 28 comments
Closed

Dependency injection failling #1

erickgr2 opened this issue Jul 27, 2020 · 28 comments

Comments

@erickgr2
Copy link

erickgr2 commented Jul 27, 2020

I have been using the this extension to publish a webeservice in my app, I can expose the endpoint and reach it properly, but internally there is a problem when the logic tries to make use of injected beans. The injection does not seem to work.

2020-07-27 16:51:15,374 INFO [org.apa.cxf.end.ServerImpl] (executor-thread-1) Setting the server's publish address to be /DispatchService.jws 2020-07-27 16:51:15,381 INFO [io.qua.cxf.CXFQuarkusServlet] (executor-thread-1) Web Service com.ahslink.controller.DispatchServiceImpl on /DispatchService.jws available. 2020-07-27 16:51:15,468 ERROR [com.ahs.con.DispatchServiceImpl] (executor-thread-1) ERROR:: java.lang.NullPointerException at com.ahslink.controller.DispatchServiceImpl.isValid(DispatchServiceImpl.java:55) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) at org.apache.cxf.jaxws.JAXWSMethodInvoker.performInvocation(JAXWSMethodInvoker.java:66) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(AbstractJAXWSMethodInvoker.java:232) at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:85) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:74) at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126) at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37) at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:296) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:215) at javax.servlet.http.HttpServlet.service(HttpServlet.java:523) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:271) at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63) at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67) at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133) at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65) at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247) at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:56) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108) at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$10$1.call(UndertowDeploymentRecorder.java:565) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152) at io.undertow.server.handlers.HttpContinueReadHandler.handleRequest(HttpContinueReadHandler.java:43) at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:113) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:290) at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18) at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$6$1.run(UndertowDeploymentRecorder.java:396) at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:231) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2046) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1578) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452) at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29) at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29) at java.lang.Thread.run(Thread.java:748) at org.jboss.threads.JBossThread.run(JBossThread.java:479)

Should I include some dependency extra in my project? or some extra configuration? Currently I have the following dependencies:

  • quarkus-arc
  • quarkus-junit5
  • quarkus-hibernate-orm
  • quarkus-hibernate-validator
  • quarkus-config-yaml
  • ojdbc
  • jakarta.ejb-api
  • quarkus-cxf
  • quarkus-resteasy

I make use of @Inject for my dependencies
@webservice(
serviceName = "DispatchService.jws",
portName = "DispatchServiceSoap",
name = "DispatchService",
endpointInterface = "com.ahslink.controller.DispatchService",
targetNamespace = "http://www.openuri.org/")
public class DispatchServiceImpl implements DispatchService{

@Inject
private Dispatch dispatchServiceManager;

@Override
public boolean isValid(long dispatchId)
{
    boolean dispatchIsValid = false;
    try {
        dispatchIsValid = dispatchServiceManager.isValid(dispatchId);
    }
    catch (EJBException exception) {
        LOGGER.error("EJBException ERROR:", exception);
    }
    catch (Exception exception) {
        LOGGER.error("Exception ERROR:", exception);
    }
    return dispatchIsValid;
}

}

@shumonsharif
Copy link
Owner

Hi @erickgr2 I am just getting back from PTO; sorry for the late response. I was just now able to recreate this issue. Will keep you posted as I investigate further. Thanks!

@shumonsharif
Copy link
Owner

Hi @erickgr2 I have not had much luck with this yet. The way the extension was developed, it seems it may involve a significant amount of work to get dependency injection to work within the web service implementation classes.

As a work around, are you able to programmatically inject the CDI managed bean? So something like:

private Dispatch dispatchServiceManager = CDI.current().select(Dispatch.class).get();

Kindly keep me posted if the above addresses your needs for now.

@querdenker2k
Copy link

Are you planning to implement CDI injection.

@shumonsharif
Copy link
Owner

Yes, I am. I have left this issue open and looking into it, but given the level of effort involved, it may be some time until this is implemented. Will keep you all posted.

@erickgr2
Copy link
Author

erickgr2 commented Aug 6, 2020

Hi @shumonsharif I have not had the chance to try the workaround suggested yet. I let you know it goes. Thank you!!

@suchwerk
Copy link

suchwerk commented Sep 1, 2020

Yes, I am. I have left this issue open and looking into it, but given the level of effort involved, it may be some time until this is implemented. Will keep you all posted.

Maybe this helps you: quarkusio/quarkus@1e26899

@shumonsharif
Copy link
Owner

Thanks @suchwerk . I don't believe the linked issue is related. In our case, the injected bean is available at runtime (the programmatic injection workaround I had suggested works fine).

I'm unfortunately still trying to wrap my head around why certain things were implemented as in the original code (such as the use of GeneratedBeanGizmoAdaptor to generate classes at runtime) -- and I believe that's where our issue may be. Will gladly accept a PR if any of you are able to make progress on this issue, as I haven't been able to.

@dufoli
Copy link
Collaborator

dufoli commented Oct 2, 2020

to have client generated, you need if i remember well in config something like:
quarkus.cxf.serviceInterface= "yournamespace.Dispatch"
Can you post your config file ?

@dufoli
Copy link
Collaborator

dufoli commented Oct 3, 2020

I have added a test in my merge request.
To summarize, I generated class for web service with use AbstractCxfClientProducer.loadCxfClient but it seems not used or even worst sei is not found... I do not know why. Anyway, I was expected that injection of client was working but obvisouly not.

@shumonsharif
Copy link
Owner

@dufoli Thanks for looking into this. You are absolutely right, I think the issue is related to multiple web service implementations, I'm going to open a separate ticket to track it. For now, I fixed your unit test, to focus on the CDI / dependency injection issue.

@dufoli
Copy link
Collaborator

dufoli commented Oct 5, 2020

@shumonsharif thanks to rename class. You forget to rename in config file.
Hmm the Foowebseevice is loaded from producer. If you dump generated class with an option on mvn you will see that a producer of sei is built. That's why cdi found it. But I think that cxf client factory generate some code for implementors.

@dufoli
Copy link
Collaborator

dufoli commented Oct 10, 2020

maybe I have to use in AbstractCxfClientProducer:
Thread.currentThread().getContextClassLoader();
seiClass = classLoader.loadClass(sei);
instead of
seiClass = Class.forName(sei);

or maybe sei must be marked as unremovable.

@dufoli
Copy link
Collaborator

dufoli commented Oct 10, 2020

or maybe just have to register AdditionalBeanBuildItem. To be honest I am a bit lost with CDI stuff.

@dufoli
Copy link
Collaborator

dufoli commented Oct 10, 2020

or simple : just register Webservice annotation as Path do it for jax rs.

@buildstep
BeanDefiningAnnotationBuildItem additionalBeanDefiningAnnotation() {
return new BeanDefiningAnnotationBuildItem(DotName.createSimple("javax.jws.WebService")));
}

@LorenzoBono
Copy link

so i have to adapt "io.quarkus.cxf.deployment.QuarkusCxfProcessor" with this here ?

@buildstep BeanDefiningAnnotationBuildItem additionalBeanDefiningAnnotation() { return new BeanDefiningAnnotationBuildItem(DotName.createSimple("javax.jws.WebService"))); }

@akrtkv
Copy link

akrtkv commented Oct 13, 2020

Same issue. Any news here?

@dufoli
Copy link
Collaborator

dufoli commented Oct 13, 2020

I have tried many things without success. I ask for help on zulip.

@JakobDeHertogh
Copy link

Same issue, and for me @shumonsharif 's workaround gives me "java.lang.IllegalStateException: Unable to locate CDIProvider" errors. Any experience with this?

@dufoli
Copy link
Collaborator

dufoli commented Oct 13, 2020

OK it is fixed. Indeed phylosophy of container mean that you can not instanciate injected client but you can used it through rest and it work perfectly ! I have implement direct test and test through REST API. Anyway, cxf client is loaded by container when needed.

@akrtkv
Copy link

akrtkv commented Oct 13, 2020

OK it is fixed. Indeed phylosophy of container mean that you can not instanciate injected client but you can used it through rest and it work perfectly ! I have implement direct test and test through REST API. Anyway, cxf client is loaded by container when needed.

What’s that mean? Can u provide example, please?

@dufoli
Copy link
Collaborator

dufoli commented Oct 14, 2020

You have an example in integration test check rest api and inject

@akrtkv
Copy link

akrtkv commented Oct 14, 2020

If i understood correctly, it's not clean solution with using rest over soap.

@jgrabowski
Copy link

I've had the same problem with injecting EntityManager into my service implementation bean. Any chance to fix it soon?

@shumonsharif
Copy link
Owner

@JakobDeHertogh @jgrabowski Would you both kindly point us to sample projects demonstrating the issues you are seeing?

@jgrabowski
Copy link

Hi,
Please find attached demo project. I've modified your Fruit service to use Hibernate/H2mem as a storage.
FruitWebServiceImpl - is an implementation following your pattern (quarkus-cxf style). It has configuration in application.properties. It doesn't inject EntityManager.
FruitWebServiceImpl2 - uses startup event to register endpoint (it's "pure cxf" style). It properly injects EntityManager.

Hope it helps.

Jakub.
injection-bug.zip

@dufoli
Copy link
Collaborator

dufoli commented Oct 18, 2020

@jgrabowski thanks for the example projet, we will have to investiguate. currently I am on native...Any help is welcome.

@shumonsharif
Copy link
Owner

@jgrabowski Would you kindly add a unit test to your project that demonstrates the issue you are seeing? I don't see any issues when I use the suggested approach for injecting EntityManager, kindly try with the changes below.

import javax.enterprise.inject.spi.CDI;
...
    //@Inject
    EntityManager em = CDI.current().select(EntityManager.class).get();

@dufoli
Copy link
Collaborator

dufoli commented Nov 3, 2020

I close the ticket because answer has been provided and new repo is quarkiverse-cxf now

@dufoli dufoli closed this as completed Nov 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants