我尝试使用MVP范例构建Web应用程序。因为我希望API干净并使一切都易于测试,我尝试通过Contructor Injection注入所有可能的东西。现在我来到了一个可以看到多个Textfields的视图。当数据库中有值时,这些文本字段会被演示者填充,因此我的演示者需要视图的引用,但是显然也需要引用者的引用。 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;
}
}
主讲人:
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();
view.setUser(user);
}
}
这里我得到循环依赖。为了避免这种情况,我尝试使用Instance Interface并将演示者更改为:
主讲人:
public Class PresenterImpl implements Presenter {
private ViewImpl view;
private Instance<ViewImpl> instanceView;
private User user;
@Inject
public PresenterImpl(Instance<ViewImpl> instanceView, User user) {
this.instanceView = instanceView;
this.user = user;
bind();
}
public void bind() {
this.view = instanceView.get();
}
public void fetchNames() {
fetchFromDB();
view.setUser(user);
}
}
但是当我这样做时,我得到一个java.lang.NoClassDefFoundError:org / jboss / weld / injection / Exceptions
更新:这是堆栈跟踪
[com.vaadin.Application] (http-localhost-127.0.0.1-8080-2) Terminal error:: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_05]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_05]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_05]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_05]
at com.vaadin.terminal.gwt.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:141) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:89) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleBurst(AbstractCommunicationManager.java:1660) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1543) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleUidlRequest(AbstractCommunicationManager.java:577) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:461) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:350) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at de.me.main.web.MEAppServlet.service(MEAppServlet.java:60) [classes:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_05]
Caused by: com.vaadin.event.ListenerMethod$MethodException: Invocation of method click in de.me.login.view.LoginViewImpl$1 failed.
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:530) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1035) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
at com.vaadin.ui.Embedded$1.click(Embedded.java:97) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
... 30 more
Caused by: java.lang.NoClassDefFoundError: org/jboss/weld/injection/Exceptions
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:125) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:120) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.getParameterValues(ConstructorInjectionPoint.java:170) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:120) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.getParameterValues(ConstructorInjectionPoint.java:170) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:120) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.getParameterValues(ConstructorInjectionPoint.java:170) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:120) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.getParameterValues(ConstructorInjectionPoint.java:170) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:120) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.getParameterValues(ConstructorInjectionPoint.java:170) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:333) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:289) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:107) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:90) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at de.me.main.layout.MainLayouter$Proxy$_$$_WeldClientProxy.go(MainLayouter$Proxy$_$$_WeldClientProxy.java) [MainService-0.0.5-SNAPSHOT.jar:]
at de.me.controller.MainController.showMainView(MainController.java:81) [MainService-0.0.5-SNAPSHOT.jar:]
at de.me.controller.MainController.access$0(MainController.java:80) [MainService-0.0.5-SNAPSHOT.jar:]
at de.me.controller.MainController$1.onLogin(MainController.java:48) [MainService-0.0.5-SNAPSHOT.jar:]
at de.me.presenter.LoginPresenterImpl.doLogin(LoginPresenterImpl.java:69) [UserManagement-0.0.5-SNAPSHOT.jar:]
at de.me.view.LoginViewImpl$1.click(LoginViewImpl.java:60) [UserManagement-0.0.5-SNAPSHOT.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_05]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_05]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_05]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_05]
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510) [vaadin-7.0.0.alpha3.jar:7.0.0.alpha3]
... 33 more
答案 0 :(得分:5)
尝试将注入点从构造函数移动到属性。因此使用@Injection注释属性,而不是构造函数。我认为这种方式焊接首先创建类的实例,然后才注入依赖项。并使用默认值替换您的构造函数 如果在创建Presenter时注释构造函数焊接需要具有View实例,但要创建View,则需要Presenter。使用默认构造函数和带注释的属性,它可以创建View和Presenter,然后只将它们相互注入。
答案 1 :(得分:5)
我现在就开始工作了。 Nikita Beloglazov的暗示帮助很大,因为据我所知,问题实际上是实例化的时刻。由于我想继续使用构造函数注入,我选择了第二种方法:
public Class PresenterImpl implements Presenter {
private ViewImpl view;
private Instance<ViewImpl> instanceView;
private User user;
@Inject
public PresenterImpl(Instance<ViewImpl> instanceView, User user) {
this.instanceView = instanceView;
this.user = user;
bind();
}
public void bind() {
this.view = instanceView.get();
}
public void fetchNames() {
fetchFromDB();
view.setUser(user);
}
}
为了使其工作,我必须在构造函数注入时仅注入代理对象,并在执行对象的第一个操作时获取实际实例。这是普通范围bean的正常行为。所以我制作了演示者和视图@SessionScoped并从Serializable扩展了接口。现在构造函数注入工作,ViewImpl是“懒惰注入”。
答案 2 :(得分:0)
在我看来,Vaadin与这个问题毫无关系。
可能存在(可能)循环依赖注入问题但问题出在ClassNotFoundException
。您部署到哪个应用程序服务器?它是一个完整的Java EE 6 AS吗?如果没有,也许你在部署中遗漏了一些库。
答案 3 :(得分:0)
有一些解决循环依赖的方法,但是当抛出这种异常时,注意你的架构可能有问题。
但请考虑点击this answer