执行 Hibernate 拦截器时无法注入依赖项 - Wildfly/CDI
Cannot inject dependencies when executing Hibernate Interceptor - Wildfly/CDI
我正在从 Hibernate 中实现一个 EmptyInterceptor 来审核数据库更改。
问题是所有注入的依赖项 (@Inject) 都是 null,在拦截器内部和任何其他 class 中,当在拦截器执行中。
我看到另一个有同样问题的问题,但是使用 Spring 框架有一个解决方法,就是将拦截器变成一个 bean,然后 CDI 可以向它注入所有依赖项。
我想使用我的 DAO 和实体管理器来持久化这些新的审计实体,有没有办法让 WELD/CDI 将我的依赖项注入拦截器?
使用 Wildfly 17,CDI 2.0
HistoricoInterceptor
@Interceptor
@Historico
public class HistoricoInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 6271759158996755175L;
@Inject
@Any
private Instance<HistoricoInterceptadorI> historicoInterceptadorI;
@Inject
private RequestQueryParamExtractor requestQueryParamExtractor;
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[]
propertyNames,
Type[] types) {}
beans.xml
<?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_2_0.xsd"
version="2.0" bean-discovery-mode="all">
<interceptors <class>br.com.procempa.tesouro.pessoaapi.util.interceptor.HistoricoInterceptor</class>
</interceptors>
RequestQueryParamExtractor
@RequestScoped
public class RequestQueryParamExtractor {
private static final String LOTACAO_PARAM = "lotacaoId";
private static final String LOGIN_PARAM = "nomeLogin";
@Inject
private HttpServletRequest httpServletRequest;
public Optional<String> getLotacaoId() {
String lotacaoId = httpServletRequest.getParameter(LOTACAO_PARAM);
return Optional.ofNullable(lotacaoId);
}
public Optional<String> getNomeLogin() {
String nomeLogin = httpServletRequest.getParameter(LOGIN_PARAM);
return Optional.ofNullable(nomeLogin);
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/pessoaDSHom</jta-data-source>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.SQL" value="DEBUG"/>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.default_schema" value="poasiat" />
<property name="hibernate.jpa.compliance.global_id_generators"
value="false"/>
<property name="hibernate.session_factory.interceptor"
value="br.com.procempa.tesouro.pessoaapi.util.interceptor.HistoricoInterceptor"/>
</properties>
</persistence-unit>
</persistence>
拦截器是 Hibernate 拦截器,不是 CDI 拦截器。这并没有错,只是注意名称“拦截器”在此上下文中被重载了(CDI 也使用具有不同 FQCN 的拦截器)。
现在,从 CDI 的角度来看,Hibernate 拦截器是一个 non-contextual 对象,因此不会由 CDI 处理。这意味着,除其他外,没有注射。
您可以通过执行动态解析来获取您的 bean 来解决此问题:
// invoke this from within a method where you want to use that bean
Instance<Object> instance = CDI.current().getBeanManager().createInstance();
RequestQueryParamExtractor rqpe = instance.select(RequestQueryParamExtractor.class).get();
此 OFC 假定您正在解析的 class 是已知 bean。
最后但并非最不重要的一点是,如果您以这种方式解析任何 @Dependent
作用域 bean,您也应对它们的销毁负责。使用完它们后,您应该通过调用 Instance.destroy(beanInstance)
来处理它们。无需为 normal-scoped beans(例如您的代码显示的 RequestQueryParamExtractor
实例)执行此操作。
这是为了防止内存泄漏,因为您正在对生命周期不受 CDI 控制的 non-contextual 对象执行动态解析。因此,已解决的依赖实例可能会留在那里。
我正在从 Hibernate 中实现一个 EmptyInterceptor 来审核数据库更改。
问题是所有注入的依赖项 (@Inject) 都是 null,在拦截器内部和任何其他 class 中,当在拦截器执行中。
我看到另一个有同样问题的问题,但是使用 Spring 框架有一个解决方法,就是将拦截器变成一个 bean,然后 CDI 可以向它注入所有依赖项。
我想使用我的 DAO 和实体管理器来持久化这些新的审计实体,有没有办法让 WELD/CDI 将我的依赖项注入拦截器?
使用 Wildfly 17,CDI 2.0
HistoricoInterceptor
@Interceptor
@Historico
public class HistoricoInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 6271759158996755175L;
@Inject
@Any
private Instance<HistoricoInterceptadorI> historicoInterceptadorI;
@Inject
private RequestQueryParamExtractor requestQueryParamExtractor;
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[]
propertyNames,
Type[] types) {}
beans.xml
<?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_2_0.xsd"
version="2.0" bean-discovery-mode="all">
<interceptors <class>br.com.procempa.tesouro.pessoaapi.util.interceptor.HistoricoInterceptor</class>
</interceptors>
RequestQueryParamExtractor
@RequestScoped
public class RequestQueryParamExtractor {
private static final String LOTACAO_PARAM = "lotacaoId";
private static final String LOGIN_PARAM = "nomeLogin";
@Inject
private HttpServletRequest httpServletRequest;
public Optional<String> getLotacaoId() {
String lotacaoId = httpServletRequest.getParameter(LOTACAO_PARAM);
return Optional.ofNullable(lotacaoId);
}
public Optional<String> getNomeLogin() {
String nomeLogin = httpServletRequest.getParameter(LOGIN_PARAM);
return Optional.ofNullable(nomeLogin);
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/pessoaDSHom</jta-data-source>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.SQL" value="DEBUG"/>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.default_schema" value="poasiat" />
<property name="hibernate.jpa.compliance.global_id_generators"
value="false"/>
<property name="hibernate.session_factory.interceptor"
value="br.com.procempa.tesouro.pessoaapi.util.interceptor.HistoricoInterceptor"/>
</properties>
</persistence-unit>
</persistence>
拦截器是 Hibernate 拦截器,不是 CDI 拦截器。这并没有错,只是注意名称“拦截器”在此上下文中被重载了(CDI 也使用具有不同 FQCN 的拦截器)。
现在,从 CDI 的角度来看,Hibernate 拦截器是一个 non-contextual 对象,因此不会由 CDI 处理。这意味着,除其他外,没有注射。
您可以通过执行动态解析来获取您的 bean 来解决此问题:
// invoke this from within a method where you want to use that bean
Instance<Object> instance = CDI.current().getBeanManager().createInstance();
RequestQueryParamExtractor rqpe = instance.select(RequestQueryParamExtractor.class).get();
此 OFC 假定您正在解析的 class 是已知 bean。
最后但并非最不重要的一点是,如果您以这种方式解析任何 @Dependent
作用域 bean,您也应对它们的销毁负责。使用完它们后,您应该通过调用 Instance.destroy(beanInstance)
来处理它们。无需为 normal-scoped beans(例如您的代码显示的 RequestQueryParamExtractor
实例)执行此操作。
这是为了防止内存泄漏,因为您正在对生命周期不受 CDI 控制的 non-contextual 对象执行动态解析。因此,已解决的依赖实例可能会留在那里。