注入一个EJB到JAX-RS(RESTful服务)注入一个EJB到JAX-RS(RESTful服务)

2019-05-10 12:00发布

我试图注入一个无状态EJB进入我的JAX-RS通过注释Web服务。 不幸的是,EJB就是null ,我得到一个NullPointerException ,当我尝试使用它。

@Path("book")
public class BookResource {

    @EJB
    private BookEJB bookEJB;

    public BookResource() {
    }

    @GET
    @Produces("application/xml")
    @Path("/{bookId}")
    public Book getBookById(@PathParam("bookId") Integer id)
    {
        return bookEJB.findById(id);
    }
}

我究竟做错了什么?

以下是有关我的机器的一些信息:

  • Glassfish的3.1
  • Netbeans的6.9 RC 2
  • Java EE 6的

你们可以显示一些工作的例子吗?

Answer 1:

我不知道这应该工作。 因此,要么:

方法1:使用注射提供商SPI

实现供应商,将做查找并注入EJB。 看到:

  • @EJB注入 。

举例com.sun.jersey:球衣服务器:1.17:

import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;

import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.ws.rs.ext.Provider;
import java.lang.reflect.Type;

/**
 * JAX-RS EJB Injection provider.
 */
@Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {

    public ComponentScope getScope() {
        return ComponentScope.Singleton;
    }

    public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
        if (!(t instanceof Class)) return null;

        try {
            Class c = (Class)t;
            Context ic = new InitialContext();

            final Object o = ic.lookup(c.getName());

            return new Injectable<Object>() {
                public Object getValue() {
                    return o;
                }
            };
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

选项2:使BookResource的EJB

@Stateless
@Path("book")
public class BookResource {

    @EJB
    private BookEJB bookEJB;

    //...
}

看到:

  • 如何合并REST服务与EJB 3.1
  • EJB 3.1和休息-该轻型混合动力

方案3:使用CDI

@Path("book")
@RequestScoped
public class BookResource {

    @Inject
    private BookEJB bookEJB;

    //...
}

看到:

  • 从注入一罐的EJB到JAX-RS类战争


Answer 2:

这个线程比较旧,不过我昨天刚打了同样的问题。 这里是我的解决方案:

只是使BookResource通过托管bean @ javax.annotation.ManagedBean的一流水平。

对于这个工作,你需要用的beans.xml使CDI:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

这个文件需要在WEB-INF如果BookResource是一个战争文件的一部分。 如果BookResource是打包的EJB放入META-INF。

如果你想使用@EJB大功告成。 如果你想通过@Inject注入EJB比的beans.xml必须付诸EJB的jar文件到META-INF为好。

你在做什么:你只是告诉该资源应容器管理的容器。 为此,它支持注入以及生命周期事件。 所以,你有你的商业门面,没有它推广到EJB。

你并不需要延长javax.ws.rs.core.Application这个工作。 BookResource是作为根资源自动请求范围。

测试了Glassfish的3.1.2和Maven项目。

编码愉快。



Answer 3:

您应该能够做到注射JAX-RS资源没有使它EJB或CDI组件。 但是你要记住,你的JAX-RS资源绝不能单。

所以,你的设置与此代码应用程序。 这使得BookResource每个请求的 JAX-RS资源。

@javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
  private Set<Object> singletons = new HashSet<Object>();
  private Set<Class<?>> classes = new HashSet<Class<?>>();

  public InjectionApplication() {
    // no instance is created, just class is listed
    classes.add(BookResource.class);
  }

  @Override
  public Set<Class<?>> getClasses() {
    return classes;
  }

  @Override
  public Set<Object> getSingletons() {
    return singletons;
  }
}

有了这个设置,你让JAX-RS实例BookResource你在每个请求的基础,并注入所有需要的依赖。 如果您BookResource JAX-RS资源,这是,你把getSingletons

public Set<Object> getSingletons() {
  singletons.add(new BookResource());
  return singletons;
}

然后,您创建实例,它不是由JAX-RS运行时,没有人在容器关心设法注入什么。



Answer 4:

不幸的是,我的回答是注释太长,所以这里去。 :)

泽克,我希望你知道究竟你是通过促进你的bean到EJB,由Pascal的建议做。 不幸的是,容易,因为它是时下使用Java EE为“使一个类的EJB”,你应该知道这样做的意义的。 每个EJB与它提供的附加功能以及创建开销:他们是事务感知,有自己的环境中,他们参加全EJB的生命周期等。

我认为你应该做一个干净的和可重复使用的方法是这样的:提取访问您的服务器上的服务(其希望是通过访问SessionFacade :)成BusinessDelegate 。 这代表应该是使用某种JNDI查找(可能是一个服务定位 -是的,他们仍然是有效的在Java EE中)来访问你的后端。

好吧,关闭记录:如果你真的,真的, 真的需要注射,因为你不想手动编写JNDI访问,你仍然可以使你的委托一个EJB,尽管它......嗯,它只是感觉不对。 :)这样,至少它会很容易有别的东西以后替换它,如果你决定切换到一个JNDI查找方法...



Answer 5:

我试图做同样的事情。 我使用EJB 3.1,并已部署我的应用程序与独立的EJB项目的EAR。 作为Jav_Rock指出,我使用上下文查找。

@Path("book")
public class BookResource {

  @EJB
  BookEJB bookEJB;

  public BookResource() {
    try {
        String lookupName = "java:global/my_app/my_ejb_module/BookEJB";
        bookEJB = (BookEJB) InitialContext.doLookup(lookupName);
    } catch (NamingException e) {
        e.printStackTrace();
    }
  }

  @GET
  @Produces("application/xml")
  @Path("/{bookId}")
  public Book getBookById(@PathParam("bookId") Integer id) {
    return bookEJB.findById(id);
  }
}

请参阅下面的链接,非常有用的JNDI查找提示

JNDI查找提示



Answer 6:

阿尔扬是正确的。 我创建了另一个类初始化EJB,而不是创建一个RS豆

@Singleton
@LocalBean
public class Mediator {
    @EJB
    DatabaseInterface databaseFacade;

为了避免空指针:

@Path("stock")
public class StockResource {
    @EJB
    DatabaseInterface databaseFacade;
...

它的实际工作对GF



Answer 7:

我有同样的问题,我解决它通过上下文查找调用EJB TE(注射是不可能的,我有同样的错误NullPointerException异常)。



文章来源: Inject an EJB into JAX-RS (RESTful service)