Java 将EJB注入JAX-RS(RESTful服务)
我正试图通过注释将无状态EJB注入我的JAX-RS Web服务。不幸的是,EJB只是Java 将EJB注入JAX-RS(RESTful服务),java,rest,jakarta-ee,ejb,jax-rs,Java,Rest,Jakarta Ee,Ejb,Jax Rs,我正试图通过注释将无状态EJB注入我的JAX-RS Web服务。不幸的是,EJB只是null,当我尝试使用它时,我得到了NullPointerException @Path("book") public class BookResource { @EJB private BookEJB bookEJB; public BookResource() { } @GET @Produces("application/xml") @Path(
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);
}
}
我做错了什么
以下是有关我的机器的一些信息:
- 玻璃鱼3.1
- Netbeans 6.9 RC 2
- Java EE 6
你们能给我举个例子吗 我不确定这是否有效。因此,要么: 选项1:使用注入提供者SPI
@Path("book")
@RequestScoped
public class BookResource {
@Inject
private BookEJB bookEJB;
//...
}
实现一个执行查找和注入EJB的提供程序。见:
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;
}
}
}
见:
@Path("book")
@RequestScoped
public class BookResource {
@Inject
private BookEJB bookEJB;
//...
}
见:
这样,如果您决定切换到JNDI查找方法,那么以后至少可以很容易地用其他方法替换它。您应该能够在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;
}
}
@javax.ws.rs.ApplicationPath(“应用程序”)
公共类注入应用程序扩展了javax.ws.rs.core.Application{
private Set singleton=new HashSet();
私有集>();
公共注入应用程序(){
//没有创建实例,只列出了类
添加(booksource.class);
}
@凌驾
public Set我也有同样的问题,我通过上下文查找调用te EJB解决了它(注入是不可能的,我有相同的错误NullPointerException)。这个线程很旧,但我昨天刚刚解决了同样的问题。以下是我的解决方案:
只需在类级别将BookResource设置为托管bean即可
为此,您需要使用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>
如果BookResource是war文件的一部分,则此文件需要在WEB-INF中。如果BookResource与EJB打包,则将其放入META-INF中
如果您想使用@EJB,那么就完成了。如果您想通过@inject注入EJB,那么必须将beans.xml也放入ejbs jar文件的META-INF中
你在做什么:你只是告诉容器,资源应该由容器管理。因此,它支持注入和生命周期事件。因此,你有了你的业务外观,而没有将它升级到EJB
您无需扩展javax.ws.rs.core.Application即可实现此功能。BookResource作为根资源自动确定请求范围
使用Glassfish 3.1.2和maven项目进行测试
愉快的编码。我也在尝试做同样的事情。我正在使用EJB3.1,并将我的应用程序作为EAR部署到单独的EJB项目中。正如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查找提示,请参见下面的链接
Arjan是对的。我创建了另一个类来初始化EJB,而不是为RS创建bean
@Singleton
@LocalBean
public class Mediator {
@EJB
DatabaseInterface databaseFacade;
要避免使用空指针,请执行以下操作:
@Path("stock")
public class StockResource {
@EJB
DatabaseInterface databaseFacade;
...
它实际上在GFErrr上起作用,这是当你没有完全阅读问题时得到的结果。在你的RESTful服务的情况下,可以说,服务本身就是你的BusinessDelegate。所以你有了它:我陈述的第一部分和最后一部分仍然完全有效,而我可能不会为业务创建BusinessDelegatessDelegate…:)我也不喜欢让我的api端点成为EJB,但你可以只使用@ManagedBean。如果你喜欢,请看我的答案,你提供的JNDI是在选项1:使用注入提供程序SPI
示例中开发的。人们经常谈论EJB“开销”似乎它们是重量级的,这是一个公认的事实,但大多数开发人员从未费心去衡量它。Adam Bien表明,2008年EJB和POJO之间的性能差异很小(<10%),此后性能才有所提高。简言之,如果您试图通过比较POJO和EJB来优化应用程序的性能,那么您找错了地方。我认为您误解了10%的数字,LeChe。这不是“我的应用程序现在慢了10%”,这是应用程序中速度慢10%的一种特定类型的操作。使用EJB而不是POJO不会使网络、数据库、文件IO和渲染多花费10%的时间,而且这些操作占了许多系统的大部分。在实际应用程序中使用EJB与POJO相比,对整体性能的影响可能可以忽略不计。至于latte在您的评论中,我同意有很好的理由不让所有东西都成为EJB:幸运的是,Pascal建议了两种选择。亲爱的@Pascal Thivent,让JAX资源成为@无状态的
是唯一的出路吗?@Pascal选项3也可以像这样
@Path("stock")
public class StockResource {
@EJB
DatabaseInterface databaseFacade;
...