我刚刚来自我的小型JavaSE/Guice世界,目前正在发现"由容器携带"-EE6的路径.在使用Glassfish3.1遇到麻烦之后,我刚刚切换到JBoss,现在面临的问题不应该是一个问题.
作为基础结构辅助类,我试图为任何类型的实体创建通用存储库/ DAO.以一种非常简单的方式,这可能看起来像这样.
public class Repository<E, K extends Serializable & Comparable<K>> {
private final Instance<EntityManager> entityManagerInstance;
protected final Class<E> getDomainObjectClass() {
return domainObjectClass;
}
private final Class<E> domainObjectClass;
protected final EntityManager getEntityManager() {
return entityManagerInstance.get();
}
@Inject
public Repository(Instance<EntityManager> entityManageryProvider, Provider<E> domainObjectProvider) {
//This is a dirty hack, sadly :(
domainObjectClass = (Class<E>)domainObjectProvider.get().getClass();
this.entityManagerInstance = entityManageryProvider;
}
public final void persist(E domainObject) {
final EntityManager em = getEntityManager();
em.persist(domainObject);
}
public final Collection<E> getAllEntities() {
final EntityManager em = getEntityManager(); …Run Code Online (Sandbox Code Playgroud) 我有@Statelessbean实现两个接口(远程和本地).我还添加@LocalBean了用于通过无接口视图访问bean的anotation.
@Stateless
@LocalBean
public class WeatherDataBean implements WeatherDataBeanRemote, WeatherDataBeanLocal {
@Inject
private EntityManager entityManager;
public WeatherDataBean () {
}
// ....attributes, getter & setter methods ....
}
Run Code Online (Sandbox Code Playgroud)
我使用@Inject这个原因取自JBoss AS7快速启动的这个例子:
我们使用来自CDI的"资源生成器"模式,将实体管理器的旧式@PersistenceContext注入"别名"为CDI样式注入.这允许我们在整个应用程序中使用一致的注入样式(@Inject).
以前我用过:
@PersistenceContext(unitName="WeatherStationJPA")
private EntityManager entityManager;
Run Code Online (Sandbox Code Playgroud)
在EJB中,它没有任何问题.但是使用@Inject注释我得到这个错误:
WELD-001408在注入点[[field] @Inject private ejb.WeatherDataBean.entityManager]中带有限定符[@Default]的[EntityManager]类型的不满意依赖项
这是我如何定义类资源:
public class Resources {
@SuppressWarnings("unused")
@PersistenceContext(unitName="WeatherStationJPA")
@Produces
private EntityManager entityManager;
@Produces
FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试注入实体管理器,为什么会出现此错误?
编辑: 根据@LightGuard的请求,我正在添加我用来引用注释的包:
WeatherDataBean有:
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject; …Run Code Online (Sandbox Code Playgroud)dependency-injection stateless-session-bean entitymanager cdi java-ee-6
我正在努力将我认为是一项简单的任务放在一起.我有一个无状态单例Bean,我将用作我的应用程序的"加载器".bean包含在Jar(loader.jar)文件中,并驻留在我的EAR的lib文件夹中.
在EAR的根目录中有另一个jar,它包含我的应用程序将使用的无状态会话Bean的实现.
然后我创建了一个小的logger类,它实际上包含了log4j:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Named;
import org.apache.log4j.Logger;
public class LoggerFactory {
private Logger logger;
public LoggerFactory(){
logger = Logger.getLogger(this.getClass().getName());
}
@Produces Logger getLogger(InjectionPoint caller){
return Logger.getLogger(caller.getMember().getDeclaringClass().getName());
}
}
Run Code Online (Sandbox Code Playgroud)
然后我把它放在一个罐子里,我把它命名为utils.jar.在这个jar中,按照CDI规范,我在META-INF文件夹中创建了一个空的beans.xml文件.utils.jar驻留在我的EAR的lib文件夹中.
现在,我之前提到的无状态Singleton Bean(加载器)
我写的就是这个
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import org.apache.log4j.Logger;
@Startup
@Singleton
public class Core {
@Inject
private Logger logger;
@PostConstruct
void init(){
logger.info("Core started");
}
}
Run Code Online (Sandbox Code Playgroud)
当我在glassfish 3.1.2上部署我的应用程序时,我在我的Loader bean中第一次调用logger时获得了一个简单的NPE.这让我觉得CDI调用根本没有发生,但我真诚地了解我做错了什么.
到目前为止,我的EAR结构如下:
EAR
|
+---lib
| +--loader.jar
| +--utils.jar …Run Code Online (Sandbox Code Playgroud) 使用CDI和JSF2时如何将HTTP请求参数注入bean中?
我有一个包含多个后端模块(EJB)的企业应用程序归档(EAR)以及一些Web模块(WAR).
事件在其中一个后端模块中被触发:
@Inject private Event<MyEvent> myEvent;
...
public void fireEvent() {
myEvent.fire(new MyEvent());
}
...
Run Code Online (Sandbox Code Playgroud)
可以在任何其他后端模块中观察到这样的代码:
public void listener(@Observes MyEvent myEvent) {
..
}
Run Code Online (Sandbox Code Playgroud)
但是我无法在WAR中检索事件.这是因为类加载器可见性(来自WAR的类对EJB不可见)还是CDI应该处理这个问题?
如果CDI不能用于应用程序范围的事件,有哪些替代方案?
有什么与CDI有效吗?也许某些CDI扩展将事件连接到WAR?
-----------编辑:
如果它在同一个WAR中被触发,我能够观察到该事件.此外,我尝试使用@Stateless bean作为事件侦听器,但没有成功.
包装是这样的:
这是在WAS8.0上运行的JSF 2应用程序.这是一个页面的"支持"bean的代码.
@Named("mySessionBean")
@SessionScoped
@Stateful
@LocalBean
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 10)
public class MySessionBean implements Serializable {
@PostConstruct
public void init()
{
System.out.println("start MySessionBean: " + this.hashCode());
}
@PreDestroy
public void cleanup()
{
System.out.println("destroy MySessionBean: " + this.hashCode());
}
....
}
Run Code Online (Sandbox Code Playgroud)
web.xml中设置的会话超时值小于bean的超时.当我运行应用程序时,我看到来自@PostConstruct的打印输出,但从未看到来自@PreDestroy的打印输出.我尝试了以下两种方案:1.logout - invalidateSession; 2.只需等到会话到期.
我不是应用程序的设计者.设计者坚持将所有支持bean作为有状态会话bean.我认为更主流的方法就是让它们成为CDI bean.但无论如何,当我确实将注释更改为CDI时,我也开始从@PreDestroy获取打印输出
@Named("mySessionBean")
@SessionScoped
public class MySessionBean implements Serializable {
.....
Run Code Online (Sandbox Code Playgroud)
我的问题是,在第一种情况下我没有得到@PreDestroy方法调用的原因是什么?如果我不能看到@PreDestroy被调用,在那里我可以跟踪"后盾" bean的生命周期(在这种情况下,有状态会话Bean)的任何其他方式.谢谢!
我正在测试/切换到Java EE7(Glassfish 4),我遇到的一个问题是拦截器,每当我尝试运行项目时,我都会收到以下错误.
严重:加载应用程序时出现异常:CDI部署失败:WELD-001417文件中启用拦截器类com.xxxxxx.security.SecuredInterceptor:/home/xxxxxx/xxxxxx/target/xxxxxx/WEB-INF/beans.xml@7既不是注释@Interceptor也没有通过便携式扩展注册
我正在看CDI 1.1规范的1.3.6节,它看起来没什么变化,所以我做错了什么?
这是我正在使用的代码;
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Secured {}
Run Code Online (Sandbox Code Playgroud)
@Secured
@Interceptor
public class SecuredInterceptor implements Serializable
{
@AroundInvoke
public Object interceptSecured(InvocationContext ic) throws Exception
{
// Do Stuff
}
}
Run Code Online (Sandbox Code Playgroud)
<?xml version="1.0" encoding="UTF-8"?>
<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"
bean-discovery-mode="annotated">
<interceptors>
<class>com.xxxxxx.security.SecuredInterceptor</class>
</interceptors>
</beans>
Run Code Online (Sandbox Code Playgroud) 我在JBoss EAP 6上使用Java EE 6,我的JSF bean注释如下:(
@ManagedBean @ViewScoped两者都来自javax.faces.bean包)
然而,他们也CDI豆(默认构造函数,使用@Inject,@PreDestroy等等).我一直在阅读你不能混合这些注释(JSF和CDI),但它显然工作正常:注入正在工作,preDestroy在视图更改时被调用等).
我错过了什么吗?问题是什么?为什么不用?
我想用mockito测试一些服务.这些服务基于CDI,不幸的是,使用现场注入,我无法改变.
public class Service {
@Inject Logger logger;
public void method() {
logger.info("some log text");
}
}
Run Code Online (Sandbox Code Playgroud)
现在使用mockito的@InjectMocks注释创建可测试的实例非常容易.它将注入嘲笑和间谍.
@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
@Spy Logger logger = LoggerFactory.getLogger(Service.class);
@InjectMocks Service service;
@Test public void test() {
// Given
// When
service.method();
// Then
}
Run Code Online (Sandbox Code Playgroud)
我需要将一些工作记录器注入我正在测试的服务类中.记录器框架是slf4j,首选记录器是logback.但不幸的Logger是,logback的实现是最终的,所以我不能窥探它,它会导致运行时异常.
我想到的解决方法:
但对于那些(那些)问题,是否有一个干净或至少更好的解决方案?
使用Wildfly 8.1我有几个bean,我尝试将几个EJB互相注入.可以说我有3个豆子:
@Stateless
public class A{
@Inject
private B b;
}
@Stateless
public class B{
@Inject
private C c;
}
@Stateless
public class C{
@Inject
private A a;
}
Run Code Online (Sandbox Code Playgroud)
显然,我有循环依赖.根据规格:
容器需要支持bean依赖关系图中的循环,其中参与每个循环依赖关系的至少一个bean具有正常范围
在容器中的代码上运行会导致表单错误:
org.jboss.weld.exceptions.DeploymentException:WELD-001443:伪范围bean具有循环依赖关系.依赖路径:
-Session bean [带有限定符的A类[@Default @Any]; 本地接口是[A] BackedAnnotatedField] @Inject private B,
[..]
我的问题是:@Stateless bean的范围是什么?它默认是@Dependent吗?最重要的是我如何在无状态会话bean之间启用循环依赖?
对不起,如果这个问题太琐碎了.我将非常感谢任何可以解释所呈现行为的进一步阅读资源.提前致谢.
更新 好了.我找到了解决方法.我使用@EJB注释而不是@Inject,但这并没有解释@Inject的奇怪行为.这个问题仍未解决,但正如Mika所说,CDI规范和Weld RI都可能是未解决的问题.
cdi ×10
java-ee ×3
java-ee-6 ×3
ejb ×2
java ×2
jsf-2 ×2
ear ×1
ejb-3.0 ×1
genericdao ×1
glassfish ×1
interceptor ×1
java-ee-7 ×1
jboss-weld ×1
jsf ×1
logback ×1
mockito ×1
view-scope ×1
war ×1
websphere-8 ×1
wildfly ×1