2012-08-14 96 views
9

我嘗試用MVP範例構建Web應用程序。因爲我想讓API變得乾淨並且讓所有事情都變得簡單可測試,我嘗試通過構造器注入來注入所有可能的東西。現在我來到了一個有多個文本框的視圖。當數據庫中存在值時,這些文本字段會被演示者填充,因此演示者需要參考視圖,但顯然還需要參考演示者。 CDI告訴我Presenter注入到視圖中,否則由於循環依賴關係是不可能的。是否有可能通過setter方法避免在視圖中設置演示者?該代碼看起來是這樣的:帶CDI的MVP;避免循環依賴

查看:

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); 
} 
} 

在這裏,我得到了循環依賴。爲了避免我試圖用實例接口,改變了主持人這個:

主持人:

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:組織/ JBoss的/焊接/注射/異常

更新:這裏是堆棧跟蹤

[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

添加'org.jboss.weld.injection.Exceptions'到classpath至少,所以你可以看到異常是什麼 – artbristol 2012-08-14 15:52:59

回答

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是「懶惰注入」。

+0

這種方法確實可以解決循環依賴問題,但請注意,此異常顯示您的體系結構存在問題。看@nick的[這個答案](http://stackoverflow.com/a/15301179/1113510) – Moesio 2013-04-12 14:45:46

5

嘗試將注入點從構造函數移動到屬性。所以使用@Injection註釋屬性,而不是構造函數。我認爲這種方式焊接首先創建類的實例,然後才注入依賴關係。並用默認值替換你的構造函數。
如果您在創建Presenter時註釋構造函數,焊接需要具有View實例,但要創建View,則需要Presenter。使用默認構造函數和註釋屬性,它可以創建View和Presenter,然後只將它們注入彼此。

0

在我看來,Vaadin與這個問題無關。

可能存在(可能)循環依賴注入問題,但問題在於ClassNotFoundException。您要部署哪個應用程序服務器?它是一個完整的Java EE 6 AS嗎?如果沒有,也許你缺少部署中的一些庫。

+0

我使用JBoss 7.1。 這應該不是問題。 – 2012-08-15 13:33:46

0

有一些解決循環依賴的方法,但是當拋出這種異常時,注意可能是你的架構有問題。

但考慮看看this answer