我试图注入一个无状态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。 看到:
举例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;
//...
}
看到:
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)