简体   繁体   English

无法使用cdi注入bean:NullPointerException

[英]Unable to inject bean with cdi : NullPointerException

Ok so I am new to CDI and currently facing problem while injecting bean. 好的,所以我是CDI的新手,目前在注入bean时遇到问题。 Here are details of module: 以下是模块的详细信息:

ResourceController.java 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 MessagePrinter.java

//imports

public class MessagePrinter  {

    @Inject
    private InjectedBean bean;


    public void print(String message) {

        bean.print(message);    
    }

}    

InjectedBean.java InjectedBean.java

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

InjectedBeanImp.java 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. 这里的问题是,每当我访问资源ResourceController.java ,都会在MessagePrinter.java类中得到NullPointerException ,这意味着InjectedBean.java失败。

Here is stacktrace : 这是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 1)从Tomcat切换到Tomee,以排除服务器问题的可能性
2) I explicitly maintained the empty beans.xml in WEB-INF folder(which was unavailable by default) 2)我在WEB-INF文件夹中明确维护了空beans.xml (默认情况下不可用)

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 更新1

Here are contents of beans.xml 这是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 :) 正如可以看到的, bean-discovery-mode被“注释”了,因为在注释之一中正确提到了它:)

So I annotated required beans as below: 所以我注释了必需的bean,如下所示:

ResourceController.java 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 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 ie IMessagePrinter.java to ResourceController.java instead of creating instance But now I am getting below exception : 另外,我现在已经将MessagePrinter.java的接口(即IMessagePrinter.java注入到ResourceController.java而不是创建实例,但是现在我得到了以下异常:

    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. 注意:但是,如果我在没有beans.xml情况下遵循这种方法,则可以正常工作,但是我不想明确地实现实现和接口的绑定。

You should not create MessagePrinter bean = new MessagePrinter(); 您不应该创建MessagePrinter bean = new MessagePrinter(); but inject it @Inject private MessagePrinter bean; 但是将其注入@Inject private MessagePrinter bean;

In annotated mode you need to put a scope like @ApplicationScoped on the bean to be discovered. 在带注释的模式下,您需要在要发现的bean上放置一个像@ApplicationScoped这样的作用域。 Maybe use all discovery mode if you want any bean. 如果您需要任何bean,也许使用所有发现模式。

In beans.xml you can change beans.xml您可以更改

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. 正如talex所说,您不应使用new关键字来创建MessagePrinter,因为CDI容器正在控制MessagePrinter的生命周期,而使用new则破坏了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM