Zec*_*eck 70 java rest ejb jax-rs java-ee
我正在尝试通过注释将无状态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);
}
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
以下是有关我的机器的一些信息:
你们能展示一些有用的例子吗?
Pas*_*ent 112
我不确定这应该有效.所以要么:
选项1:使用注射提供者SPI
实现将执行查找并注入EJB的提供程序.看到:
com.sun.jersey的示例:jersey-server: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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
选项2:使BookResource成为EJB
@Stateless
@Path("book")
public class BookResource {
@EJB
private BookEJB bookEJB;
//...
}
Run Code Online (Sandbox Code Playgroud)
看到:
选项3:使用CDI
@Path("book")
@RequestScoped
public class BookResource {
@Inject
private BookEJB bookEJB;
//...
}
Run Code Online (Sandbox Code Playgroud)
看到:
Mic*_*ons 14
这个线程相当陈旧,不过我昨天也遇到了同样的问题.这是我的解决方案:
只需通过类级别的@ javax.annotation.ManagedBean将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>
Run Code Online (Sandbox Code Playgroud)
如果BookResource是war文件的一部分,则此文件需要在WEB-INF中.如果BookResource与ejbs一起打包,则将其放入META-INF.
如果你想使用@EJB,你就完成了.如果要通过@Inject注入EJB,则必须将beans.xml放入ejbs jar文件中,并将其放入META-INF中.
你在做什么:你只是告诉容器资源应该是容器管理的.因此,它支持注入和生命周期事件.因此,您拥有业务外观,而无需将其提升为EJB.
您无需为此扩展javax.ws.rs.core.Application.BookResource作为根资源自动请求作用域.
使用Glassfish 3.1.2和maven项目进行测试.
快乐的编码.
Mar*_*tin 10
您应该能够在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;
}
}
Run Code Online (Sandbox Code Playgroud)
通过此设置,您可以让JAX-RS根据请求为您实例化BookResource,并注入所有必需的依赖项.如果您将BookResource类设置为单例 JAX-RS资源,那么您可以将其放入getSingletons
public Set<Object> getSingletons() {
singletons.add(new BookResource());
return singletons;
}
Run Code Online (Sandbox Code Playgroud)
然后,您创建了一个不受JAX-RS运行时管理的实例,并且容器中没有人关心注入任何内容.
不幸的是,我的回答太长,无法发表评论,所以这里就是这样.:)
Zeck,我希望你通过将你的bean推广到EJB来了解你正在做什么,正如Pascal所建议的那样.不幸的是,就像现在使用Java EE"将类创建为EJB"一样简单,您应该意识到这样做的含义.每个EJB都会产生开销以及它提供的附加功能:它们具有事务感知能力,具有自己的上下文,它们参与完整的EJB生命周期等.
我认为你应该采用干净和可重用的方法做到这一点:将对服务器服务(希望通过SessionFacade访问)的访问权限提取到BusinessDelegate中.这个委托应该使用某种JNDI查找(可能是ServiceLocator - 是的,它们在Java EE中仍然有效!)来访问你的后端.
好的,关闭记录:如果你真的,真的,真的需要注入,因为你不想手动编写JNDI访问,你仍然可以让你的委托成为EJB,虽然它......好吧,它只是感觉不对.:)至少如果您决定切换到JNDI查找方法,至少可以很容易地用其他东西替换它...
归档时间: |
|
查看次数: |
76408 次 |
最近记录: |