标签: cdi

为什么最终类不能用 CDI 代理?

CDI 规范的第 5.4.1 节指出,如果声明了 ,否则有效的 bean 是不可代理的(因此无法注入)final。规范没有给出任何理由,我想不出这个决定的理由。

我试图坚持设计规则,说没有明确设计用于继承的类应该禁止它。因此,CDI 规范似乎强制执行了糟糕的设计(并使 CheckStyle 哭泣)。

为什么会这样,我们可以做些什么?

谢谢你。

java dependency-injection cdi jboss-weld

2
推荐指数
1
解决办法
1101
查看次数

CDI 事务管理:@Transactional 如何工作?

在会话范围内有一个简单的 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 …

ejb jpa transactions cdi jakarta-ee

2
推荐指数
1
解决办法
7677
查看次数

当对CDI中的事件使用自定义注释时,不允许对此位置使用注释"@Added"

在@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)

java events cdi

2
推荐指数
1
解决办法
1万
查看次数

JSF Controller忽略@RolesAllowed批注

我有一个这样命名和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

jsf java-ee cdi jsf-2

2
推荐指数
1
解决办法
1021
查看次数

CDI 不适用于隐式 @Dependent 作用域,不满意注入点编译时错误

容器是 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

2
推荐指数
1
解决办法
1316
查看次数

CDI bean 的 Servlet 和作用域

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)

java servlets dependency-injection cdi

2
推荐指数
1
解决办法
1975
查看次数

CDI Beans 和 Hibernate Envers

我开始使用 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)

cdi hibernate-envers

2
推荐指数
1
解决办法
730
查看次数

将无状态会话 bean 注入自定义 JsonDeserializer 失败

我正在构建一个使用 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)

java json jackson cdi

2
推荐指数
1
解决办法
607
查看次数

CDI 中@Transactional 的限制是什么?

我试图@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。我是不是弄错了?或者我只是缺少一些额外的配置?

ejb jpa cdi jakarta-ee

2
推荐指数
1
解决办法
915
查看次数

从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解决方案?如果我需要回到学校或者我理解我在写什么,那就不行了.感谢您花时间帮忙!

java cdi jboss-weld

2
推荐指数
1
解决办法
1024
查看次数