CDI 规范的第 5.4.1 节指出,如果声明了 ,否则有效的 bean 是不可代理的(因此无法注入)final。规范没有给出任何理由,我想不出这个决定的理由。
我试图坚持设计规则,说没有明确设计用于继承的类应该禁止它。因此,CDI 规范似乎强制执行了糟糕的设计(并使 CheckStyle 哭泣)。
为什么会这样,我们可以做些什么?
谢谢你。
在会话范围内有一个简单的 CDI bean,注入了一个实体管理器:
@Named("myBean")
@SessionScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
EntityManager em;
...
@Transactional
private void testInsert() {
long t = System.currentTimeMillis();
for (int i=1; i<50000; i++) {
create(i);
}
System.out.println("Time: " + Long.toString(System.currentTimeMillis()-t));
}
private void create(int i) {
Project p = new Project("Project " + i);
em.persist(p);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当通过 EL #{myBean.testInsert} 调用函数时,有两件事似乎很奇怪:
1)将@Transactional-annotation 移动到方法 create(int) 我得到:
javax.persistence.TransactionRequiredException:JBAS011469:需要事务来执行此操作(使用事务或扩展持久性上下文)
2)改用@Transactional 装饰 testInsert(),该函数立即返回,但 JPA 仍在后台线程中更新数据库。该过程需要 2 分钟才能完成仅 50000 条记录的 INSERT。在进程中关闭 Java …
在@Observes限定符附近使用自定义限定符来捕获事件时,我有这个编译错误.
所有类都在同一个包中,因此问题不在于import语句.我已经检查过了.
@Inject
private Logger logger;
List<Book> inventory = new ArrayList<>();
public void addBook(@Observes @Added Book book) {
logger.warning("adding book" + book.getTitle());
inventory.add(book);
}
public void removeBook(@Observes @Removed Book book) {
logger.warning("remove book");
}
Run Code Online (Sandbox Code Playgroud)
所以,这一行:public void addBook(@Observes @Added Book book){
这就像:public void removeBook(@Observes @Removed Book book){
标记有以下错误:此位置不允许使用注释@Added(@Removed).
这里是定义addBook和removeBook方法的代码.这里没有问题.
@Inject
@Added
private Event<Book> bookAddedEvent;
@Inject
@Removed
private Event<Book> bookRemovedEvent;
public Book createBook(String title, float price, String description) {
Book book = new Book(title, price, description);
book.setNumber(numberGenerator.generateNumber());
bookAddedEvent.fire(book);
return book;
}
public …Run Code Online (Sandbox Code Playgroud) 我有一个这样命名和SessionScoped的JSF控制器
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
@Named
@SessionScoped
public class SomeController {
...
Run Code Online (Sandbox Code Playgroud)
将@RolesAllowed或@DenyAll添加到控制器无效。当此控制器调用具有@RolesAllowed批注的EJB时,它将在那些bean调用上正常工作。
我正在使用jsf 2.2并将我的应用程序部署到Wildfy 8.1
容器是 Glassfish 4.1
我现在对 CDI 有一个非常奇怪的问题。如果我不注释我的NumberGenerator服务@Dependent,那么当我运行应用程序时,我会不断收到不满意的注入点错误。但是如果我明确地注释我的NumberGenerator实现,那么一切都会起作用。一句话,如果我想使用@Dependent默认作用域进行依赖注入,我必须明确指定它。
public interface NumberGenerator {
String generateNumber();
}
Run Code Online (Sandbox Code Playgroud)
第一次实施 NumberGenerator
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
@ThirteenDigits
@Dependent
public class IsbnGenerator implements NumberGenerator {
@Inject
private Logger logger;
@Override
public String generateNumber() {
String isbn = "13-84356-" + Math.abs(new Random().nextInt());
logger.log(Level.INFO, "Generated ISBN : {0}", isbn);
return isbn;
}
}
Run Code Online (Sandbox Code Playgroud)
第二次实施 NumberGenerator
import java.util.Random;
import java.util.logging.Logger;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
@EightDigits
@Dependent
public …Run Code Online (Sandbox Code Playgroud) dependency-injection glassfish cdi managed-bean glassfish-4.1
tl;dr 注入到 servlet 的 CDI bean 怎么可能也在适当的范围内?
在 oracle 官方教程和一些书籍中,我们可以看到一些简单的例子,展示了如何将 CDI bean 注入 servlet。这非常简单,因为我们只需要使用@Inject注释并在 beans.xml 中启用 bean 发现。我不明白的是,注入到 servlet的@RequestScoped 或 @SessionScoped bean怎么可能具有正确的范围。servlet 对象仅由容器创建一次,因此据我所知,注入也应该只发生一次,或者应该发生一些意外行为。但是当我们使用 ie. @RequestScoped 在 bean 类上,注入发生在对这个 servlet 的每个请求之后(很棒)。问题是它是如何深入工作的?
简单的例子
public interface BeanInterface {
public void beanInfo();
}
Run Code Online (Sandbox Code Playgroud)
——
@RequestScoped
public class BeanImpl implements BeanInterface {
@Override
public void beanInfo() {
System.out.println(this);
}
}
Run Code Online (Sandbox Code Playgroud)
——
@WebServlet("/bean")
public class BeanServlet extends HttpServlet {
//how is it injected with every GET/POST/... request
@Inject
private BeanInterface bean;
protected void …Run Code Online (Sandbox Code Playgroud) 我开始使用 Hibernate Envers。我已经能够使用 @Audited 正确注释类并创建修订版,但我无法用我的修订版记录已记录的用户数据。
我的 JSF 2.0 测试应用程序在 jbossEAP6/wildfly 服务器中的 CDI、JPA/Hibernate 上运行。我既不使用 Spring 也不使用 Seam。
这是一些代码:
修订实体.java
@Entity
@RevisionEntity(AuditListener.class)
public class RevisionEntity {
@Id
@GeneratedValue
@RevisionNumber
private int id;
@RevisionTimestamp
private long timestamp;
private String username;
Run Code Online (Sandbox Code Playgroud)
登录Bean.java
@Named
@Stateful
@SessionScoped
public class LoginBean implements Serializable{
private String username;
...
Run Code Online (Sandbox Code Playgroud)
审计监听器
import javax.ejb.Stateful;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.hibernate.envers.RevisionListener;
import br.test.login.filterlogin.beans.LoginBean;
@Named
@Stateful
@SessionScoped
public class AuditListener implements RevisionListener {
@Inject
private LoginBean loginBean;
public void newRevision(Object revisionEntity) …Run Code Online (Sandbox Code Playgroud) 我正在构建一个使用 JPA (EclipseLink) 提供 JAX-RS REST 服务的应用程序。当通过 JSON 公开用户实体时,我@XmlTransient在某些字段(例如密码字段)上使用注释来将它们从 JSON 表示中隐藏起来。发送创建或更新 (POST/PUT) 操作时,我想再次填充缺失的字段,以便 JPA 正确执行操作。
我目前的方法是我有一个自定义JsonDeserializer,用于反序列化用户并添加缺少的字段。为此,我想注入(使用@Inject)一个UserFacadeREST处理 JPA 内容的bean。但是,此注入失败并且 bean 实例为null(这当然会导致NullPointerException)。
我的UserFacadeRESTbean注释如下:
@Stateless
@LocalBean
@Path(UserFacadeREST.PATH)
public class UserFacadeREST extends AbstractFacade<User> {
//...
}
Run Code Online (Sandbox Code Playgroud)
我的UserDeserilizer(自定义JsonDeserializer):
public class UserDeserializer extends JsonDeserializer<User> {
@Inject
private UserFacadeREST userFacade;
@Override
public User deserialize(JsonParser parser, DeserializationContext context) throws IOException,
JsonProcessingException {
JsonNode node = parser.getCodec().readTree(parser);
int userId = (Integer) …Run Code Online (Sandbox Code Playgroud) 我试图@Transactional在 CDI 类中使用一种方法,而不是 EJB:
@javax.inject.Named
// fails @javax.enterprise.context.ApplicationScoped
// fails @javax.enterprise.context.SessionScoped
// works @javax.ejb.Singleton
// works @javax.ejb.Stateless
public class SomeClass {
@javax.persistence.PersistenceContext
private EntityManager em;
@javax.annotation.PostConstruct
@javax.transaction.Transactional
public void someMethod() {
em.persist(someEntity);
}
}
Run Code Online (Sandbox Code Playgroud)
当我SomeClass用@Singletonor注释时@Stateless,一切正常。
当我SomeClass用@ApplicationScoped或注释时@SessionScoped,WildFly 13 显示以下错误消息:
执行此操作需要事务(使用事务或扩展持久性上下文)
我的印象是@Transactional从 Java EE 7 开始就可以使用 CDI。我是不是弄错了?或者我只是缺少一些额外的配置?
我寻找一个干净的CDI解决方案,而不是WELD依赖的解决方案,但到目前为止没有...
我需要测试,如果我用@Inject @Any MyInterface的豆获得对象的列表中的每个元素是一个代理,而当真正的我需要得到真正的对象做反省和获取对象的所有属性.
我的WELD实施:
MyInterface interf = obj;
if (isProxy(interf )) {
interf = (Config) ((TargetInstanceProxy)interf ).getTargetInstance();
}
Run Code Online (Sandbox Code Playgroud)
其中isProxy是如此定义的(CDI解决方案?):
public boolean isProxy(Object obj) {
try{
return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
} catch (Exception e) {
LOGGER.error("Unable to check if object is proxy", e);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
任何建议/指示.在官方文档中我没有提到内省(这里)
然后我想得到bean的所有属性,如下所示:
Arrays.stream(interf.getClass().getDeclaredFields()).forEach(
field -> extractStuff(...)
);
Run Code Online (Sandbox Code Playgroud)
我们使用Wildfly和WELD,但不想将我们绑定到CDI的实现.提前致谢!
编辑: 问题是,更确切地说:您是否知道WELD 已经使用TargetInstanceProxy实施的干净CDI解决方案?如果我需要回到学校或者我理解我在写什么,那就不行了.感谢您花时间帮忙!
cdi ×10
java ×5
ejb ×2
jakarta-ee ×2
jboss-weld ×2
jpa ×2
events ×1
glassfish ×1
jackson ×1
java-ee ×1
jsf ×1
jsf-2 ×1
json ×1
managed-bean ×1
servlets ×1
transactions ×1