我正在开发一个Java EE应用程序,主要是带有JSF管理控制台的JAX-RS,它使用CDI/Weld来javax.enterprise.context.ApplicationScoped对象注入依赖项.除了一些小的调试问题,CDI已经为这个项目做了很好的工作.
现在我需要对CDI注入的对象生命周期进行一些非常粗粒度的控制.我需要能力:
@ScopeType并实现Context我可以提供执行上述两个任务之一的方法.我完全清楚,一般来说,如果不是反对的话,CDI和依赖注入都是如此.我只是想知道
我是Java EE 6和CDI的新手.我已经阅读了几个教程和焊接文档.然而,根据我的理解应该起作用的东西不是,所以我需要帮助.
我有以下情况.我使用随IDE提供的maven原型创建了一个带有NetBeans 7.0.1的Java EE 6应用程序,并部署到IDE提供的GlassFish 3.1.
beans.xml位于我的EJB jar的META-INF目录中.
我创建了一个类作为我的EJB工件(和EntityManager)的生产者类工作的类
@Stateless
public class EjbArtifactProducer {
@PersistenceContext(unitName = "trackProfiler-PU")
private EntityManager em;
@EJB
private UserFacadeLocal userFacade;
@EJB
private AuthServiceLocal authService;
@EJB
private NewsEntryFacadeLocal newsEntryFacade;
@EJB
private RoleFacadeLocal roleFacade;
@EJB
private TrackCommentFacade trackCommentFacade;
@EJB
private TrackFacade trackFacade;
@EJB
private TrackTypeFacade trackTypeFacade;
@EJB
private WaypointFacadeLocal waypointFacade;
@Produces
public AuthServiceLocal getAuthService() {
return authService;
}
@Produces
public EntityManager getEm() {
return em;
}
@Produces
public NewsEntryFacadeLocal getNewsEntryFacade() {
return newsEntryFacade;
}
@Produces
public …Run Code Online (Sandbox Code Playgroud) 我尝试用MVP范例构建一个Webapp.因为我希望API干净并使一切都易于测试,我尝试通过Contructor Injection注入所有可能的东西.现在我来到了一个可以看到多个Textfields的视图.当数据库中存在值时,这些文本字段会被演示者填充,因此我的演示者需要视图的引用,但是vie显然也需要引用者的引用.CDI告诉我将Presenter注入到视图中,否则由于循环依赖性而无法实现.是否可以通过setter方法避免在视图中设置演示者?代码看起来像这样:
视图:
public Class ViewImpl implements view {
private PresenterImpl presenter;
private User user;
@Inject
public ViewImpl(PresenterImpl presenter, User user) {
super();
this.presenter = presenter;
this.user = user;
}
public void attach() {
super.attach();
presenter.fetchNames();
showUser();
}
public void setUser(User user) {
this.user = user;
}
}
Run Code Online (Sandbox Code Playgroud)
主持人:
public Class PresenterImpl implements Presenter {
private ViewImpl view;
private User user;
@Inject
public PresenterImpl(ViewImpl view, User user) {
this.view = view;
this.user = user;
}
public void fetchNames() {
fetchFromDB(); …Run Code Online (Sandbox Code Playgroud) 我正在编写一个Java EE 6 Web应用程序,我注意到在使用注入对象与直接创建和使用对象时会对性能产生重大影响.每个方法调用的开销似乎是50-60ms.
例如,使用非注入150方法调用大约需要500毫秒,而使用注入对象150方法调用需要12,000 - 13,000毫秒.一个数量级的差异然后一些.
这通常吗?
我在JBoss AS 7.1.1 final上运行,它使用Weld来处理CDI.
注入的对象被定义为单例bean(通过javax.ejb.Singleton注释).这会导致部分问题吗?或者只是Weld代理导致减速?
我是Java EE/JSF的新手,现在阅读有关CDI限定符的内容 - 更改类实现的可能性.这很棒,但我有一个问题.据我所知,我可以使用限定符更改类实现,但我需要在使用此实现的任何地方更改它.在一个地方做这件事的最佳解决方案是什么?凭借我对Java EE的小知识,我发现了这一点.
让我们假设我们正在创建简单的Calculator应用程序.我们需要创建几个类:
Calculator (计算器的基本实现)ScientificCalculator (科学实施计算器)MiniCalculator (潜力最小)MockCalculator (用于单元测试)@Calculator(将指示计算器的实际实现;我应该为每个实现创建限定符吗?)这是个问题.我有四个计算器的实现,我想在少数地方使用其中一个,但只有一个在时间(在我将使用的初始项目阶段MiniCalculator,然后Calculator等等).如何在没有更改代码的情况下在注入对象的每个位置更改实现?我应该创建负责注射的工厂method injector吗?我的解决方案是正确有意义的吗
厂
@ApplicationScoped
public class CalculatorFctory implements Serializable {
private Calculator calc;
@Produces @Calculator Calculator getCalculator() {
return new Calculator();
}
}
Run Code Online (Sandbox Code Playgroud)
使用计算器的类
public class CalculateUserAge {
@Calculator
@Inject
private Calculator calc;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的解决方案吗?如果我错了或者有更好的解决方案,请纠正我.谢谢!.
我想用Java Swing编写一个简单的Java桌面应用程序.通常我使用Spring Framework来执行依赖注入并构建整个类结构.但是,我已经看到CDI越来越受欢迎,并想尝试一下.
我想使用CDI对我的项目进行依赖注入,但我不知道如果没有Servlet容器这是否可行(因为它使用的是Spring).每个教程似乎都与servlet容器或应用程序服务器有关.
我想使用CDI向JSF Web应用程序中的托管bean注入常量字符串消息,这里是生产者类:
@Named
@RequestScoped
public class StringProducer {
@Produces
@Named("message")
@RequestScoped
public String getMessage() {
return "Hello World";
}
}
Run Code Online (Sandbox Code Playgroud)
以下是它如何在另一个托管bean中注入:
@Inject Named("message") String message;
Run Code Online (Sandbox Code Playgroud)
但这总是导致异常:
org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435 Normal scoped bean int is not proxyable
Run Code Online (Sandbox Code Playgroud)
我试图在Instance中包装String类型,如下所示:
@Inject Named("message") Instance<String> message;
Run Code Online (Sandbox Code Playgroud)
但没有改变.
拥有以下相当简单的代码和正确配置的基于JTA的持久化上下文:
abstract class AbstractRepository<E> {
@PersistenceContext
protected EntityManager em;
@Transactional
public synchronized void persist(E entity) {
em.persist(entity);
em.flush();
}
}
@ApplicationScoped
class MyEntityRepository extends AbstractRepository<MyEntity> {
}
Run Code Online (Sandbox Code Playgroud)
我在调用时遇到以下异常MyEntityRepository.persist():
2015-06-23T12:34:55.233+0200|Severe: javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:161)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:151)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:281)
at my.project.AbstractRepository.persist(AbstractRepository.java:28)
at my.project.QuestionnaireRepository.persist(QuestionnaireRepository.java:1)
at my.project.QuestionnaireRepository$Proxy$_$$_WeldClientProxy.persist(Unknown Source)
at my.project.QuestionnaireForm.save(QuestionnaireForm.java:29)
at my.project.QuestionnaireForm.lambda$0(QuestionnaireForm.java:1)
at my.project.QuestionnaireForm$$Lambda$56/1079229220.buttonClick(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:977)
at com.vaadin.ui.Button.fireClick(Button.java:393)
at com.vaadin.ui.Button$1.click(Button.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) …Run Code Online (Sandbox Code Playgroud) 当试图部署耳朵时,我们得到了臭名昭着的WELD-001408(见下面的stacktrace).
问题:似乎WELD无法通过@Inject将EJB注入到lib/shared.jar中的CDI托管bean(!= @ManagedBean)中. 为什么是这样?有没有一个标准说这不应该工作?
更新 我在相关位置也有一个ejb-jar.xml ...
UPDATE2: 我在github上创建了一个最小的versin
首先是设置 - 我的研究/调查结果以及最后的更详细的问题:
我们目前正在使用Glassfish 4.1 => Weld 2.2.2.Final,但错误是相同的,使用Payara 4.1.1.154 => Weld 2.2.16.Final,也是Java EE 7
耳朵的布局
sample.ear
??? a-ejb.jar (contains AEjb.java + beans.xml + ejb-jar.xml)
??? b-ejb.jar (contains AnotherCdiIManagedBeanPojo.java + DummyEjb.java + beans.xml)
??? lib
| ??? shared.jar (contains ACdiManagedBeanPojo.java, AnotherCdiDependency.java + beans.xml)
??? META-INF
??? application.xml (...)
Run Code Online (Sandbox Code Playgroud)
在shared.jar中有
public class ACdiManagedBeanPojo {
@Inject
private AEjb aEjb;
@Inject
private AnotherCdiDependency anotherCdiDependency;
}
Run Code Online (Sandbox Code Playgroud)
AEjb是驻留在a-ejb.jar中的EJB
@javax.ejb.Singleton
@javax.ejb.LocalBean
@javax.enterprise.context.ApplicationScoped
public class AEjb …Run Code Online (Sandbox Code Playgroud) 我打算将Web应用程序从使用JSF托管bean转换为使用CDI托管bean.我知道我需要在下面做:
是这一切都需要做吗?我需要注意哪些问题?
cdi ×10
java ×6
java-ee ×4
java-ee-6 ×2
jboss-weld ×2
jsf-2 ×2
weld ×2
ejb ×1
ejb-3.1 ×1
glassfish-3 ×1
glassfish-4 ×1
java-7 ×1
jboss7.x ×1
jsf ×1
managed-bean ×1
migration ×1
omnifaces ×1
transactions ×1