0

Ok so I am new to CDI and currently facing problem while injecting bean. Here are details of module:

ResourceController.java

//imports

@Path("/resource")
public class ResourceController {

    @GET
    @Path("/print/{message}")
    public void printMessage(@PathParam("message") String message){
        MessagePrinter bean = new MessagePrinter();
        bean.print(message);
    }
}    

MessagePrinter.java

//imports

public class MessagePrinter  {

    @Inject
    private InjectedBean bean;


    public void print(String message) {

        bean.print(message);    
    }

}    

InjectedBean.java

public interface InjectedBean {
    public void print(String message);
}    

InjectedBeanImp.java

public class InjectedBeanImp implements InjectedBean {

    public InjectedBeanImp() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public void print(String message) {

        System.out.println(message);
    }

}    

here the problem is that whenever I hit the resource ResourceController.java , I get NullPointerException in MessagePrinter.java class meaning injection of InjectedBean.java is failed.

Here is stacktrace :

java.lang.NullPointerException
    at com.bean.MessagePrinter.print(MessagePrinter.java:14)
    at com.resource.ResourceController.printMessage(ResourceController.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:143)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:83)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskTh 

Before anyone of you mark this as duplicate question ,I did lot of research on many threads for solution and eliminated some probable errors as :

1) switched from Tomcat to Tomee to rule out the possibility of server issue
2) I explicitly maintained the empty beans.xml in WEB-INF folder(which was unavailable by default)

but still I am stuck with the same problem and could not find any other solution. What is it that I am doing wrong?

Update-1

Here are contents of beans.xml

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.2" bean-discovery-mode="annotated">

    <!-- some content -->
</beans>

as can be seen bean-discovery-mode is "annotated" as it was correctly mentioned in one of the comments :)

So I annotated required beans as below:

ResourceController.java

//imports

@Path("/resource")
@ApplicationScoped
public class ResourceController {

    @Inject
    private IMessagePrinter bean;

    @GET
    @Path("/print/{message}")
    public void printMessage(@PathParam("message") String message){

        bean.print(message);
    }
}   

MessagePrinter.java

//imports

@ApplicationScoped
public class MessagePrinter implements IMessagePrinter {

    @Inject
    private InjectedBean bean;


    public void print(String message) {

        bean.print(message);    
    }

}     

Also I have now injected the interface for MessagePrinter.java i.e IMessagePrinter.java to ResourceController.java instead of creating instance But now I am getting below exception :

    SEVERE: Servlet.service() for servlet [Jersey RESTful Application] in context with path [/TestEJB] threw exception [A MultiException has 3 exceptions.  They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IMessagePrinter,parent=ResourceController,qualifiers={},position=-1,optional=false,self=false,unqualified=null,29372562)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.resource.ResourceController errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.resource.ResourceController
] with root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IMessagePrinter,parent=ResourceController,qualifiers={},position=-1,optional=false,self=false,unqualified=null,29372562)

Again I am stuck. Thanks in advance for your patience :)

Note: However if I follow this approach without beans.xml it works fine but I don't want to do binding of implementations and interfaces explicitly.

jCoder
  • 41
  • 2
  • 8
  • What container are you deploying to? I see tomee and jersey in the stack. TomEE ships with CXF. Ideally you shouldn't ship your own JAX-RS implementation. – John Ament Jul 26 '17 at 20:09
  • 1
    `MessagePrinter bean = new MessagePrinter();` is definitely nonsense - you want to inject it instead. Apart from that, do you have `beans.xml` with discovery set to `all`? If not, you beans won't be picked up as you do not use bean defining annotations. – Siliarus Jul 27 '17 at 06:24
  • @John Ament :sorry but didn't really get your comment _TomEE ships with CXF. Ideally you shouldn't ship your own JAX-RS implementation_ – jCoder Jul 29 '17 at 08:11
  • @jCoder its really hard to clarify if you don't answer the questions being presented. Based on your stacktrace, it looks like you're deploying to tomee but shipping the jersey JAX-RS library with it. Is that in fact what you are doing? – John Ament Jul 30 '17 at 20:22
  • @John Ament: Sorry for late response. Yes I am using TomEE and jersey. – jCoder Jul 31 '17 at 17:41
  • Looks a bit like https://stackoverflow.com/questions/15453350/unable-to-inject-applicationscoped-bean-in-jax-rs-service. Do you need ResourceController to be ApplicationScoped? – aschoerk Jul 31 '17 at 21:52
  • @ aschoerk tried with '@RequestScoped' and '@ManagedBean' as well but doesn't seem to make any difference , I get same error , also tried with discovery-mode=all but no luck with that either :( – jCoder Aug 02 '17 at 16:23

3 Answers3

2

You should not create MessagePrinter bean = new MessagePrinter(); but inject it @Inject private MessagePrinter bean;

talex
  • 17,973
  • 3
  • 29
  • 66
0

In annotated mode you need to put a scope like @ApplicationScoped on the bean to be discovered. Maybe use all discovery mode if you want any bean.

Romain Manni-Bucau
  • 3,354
  • 1
  • 16
  • 13
  • As you can notice in update above, I have already annotated beans 'ResourceController.java' and 'MessagePrinter.java' with @ApplicationScoped. Still I am getting 'UnsatisfiedDependencyException' – jCoder Jul 31 '17 at 17:36
  • Are you sure jersey uses cdi? Looks like it falls back on hk2 which doesnt know beans if you dont have the cdi extension – Romain Manni-Bucau Aug 09 '17 at 06:29
0

In beans.xml you can change

bean-discovery-mode="annotated"

to

bean-discovery-mode="all"

As talex said, you should not use new keyword to create MessagePrinter because the CDI container is controlling the life cycle of MessagePrinter and by using new you are breaking it.

mburesh
  • 1,012
  • 5
  • 15
  • 22
Hossein
  • 35
  • 10