2012-08-14 11 views
9

Próbuję zbudować Webapp z paradygmatem MVP. Ponieważ chcę, aby interfejs API był czysty i aby wszystko było łatwe do sprawdzenia, staram się wstrzykiwać wszystko, co jest możliwe za pomocą narzędzia Contructor Injection. Teraz doszedłem do punktu, w którym mam widok z wieloma Textfieldami. Te pola tekstowe są wypełniane przez prezentera, gdy są w nim wartości, więc mój prezenter potrzebuje odniesienia do widoku, ale oczywiście również potrzebuje odniesienia do prezentera. CDI mówi mi, że wstrzyknięcie prezentera do widoku i w inny sposób nie jest możliwe z powodu zależności kołowych. Czy możliwe jest uniknięcie ustawiania prezentera w widoku za pomocą metody ustawiającej? Kod wygląda mniej więcej tak:MVP z CDI; unikanie zależności cyklicznej

Widok:

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

Presenter:

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

Tu uzyskać zależność cykliczną. Aby uniknąć sytuacji, starałem się używać interfejsu instancji i zmienił prezentera do tego:

Presenter:

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

Ale kiedy to zrobić otrzymuję java.lang.NoClassDefFoundError: org/JBoss/spoiny/wtrysk/wyjątki

Aktualizacja: Oto ślad stosu

[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

Dodaj 'org.jboss.weld.injection.Exceptions' do ścieżki klasy co najmniej, dzięki czemu można zobaczyć, co Wyjątkiem jest – artbristol

Odpowiedz

5

Mam to teraz działa. Podpowiedź od Nikity Beloglazova bardzo pomogła, ponieważ jak rozumiem, problemem jest właśnie moment, w którym instancja jest wykonywana. Jak chcę pozostać z wtryskiem konstruktora Wybrałem drugie podejście:

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

Aby uzyskać to do pracy muszę wstrzykiwać tylko obiekt proxy w momencie iniekcji konstruktora i uzyskać prawdziwe wystąpienie w chwili, gdy wykonuje się pierwszą akcję na obiekcie. Jest to normalne zachowanie normalnej scoped beans. Zrobiłem więc prezentację i widok @SessionScoped i rozszerzyłem interfejsy z Serializable. Teraz wtrysk Constructor działa, a ViewImpl jest "leniwie wstrzykiwany".

+0

To podejście naprawdę rozwiązuje zależność cykliczną, ale zauważ, że ten wyjątek pokazuje, że coś jest nie tak z architekturą. Zobacz [tę odpowiedź] (http://stackoverflow.com/a/15301179/1113510) z @nick – Moesio

5

Spróbuj przenieść punkty wtrysku z konstruktora do właściwości. A więc adnotuj właściwości za pomocą @Injection, a nie konstruktora. Myślę, że w ten sposób spawanie najpierw tworzy wystąpienia klas, a dopiero potem wstrzykuje zależności. Zamień swój konstruktor na domyślny.
Jeśli adnotacja spoiny konstruktora musi mieć instancję widoku podczas tworzenia prezentacji, ale aby utworzyć widok, potrzebuje on prezentera. Przy domyślnym konstruktorze i właściwościach z adnotacjami może on tworzyć widok i prezenter, a następnie wstrzykiwać je sobie nawzajem.

0

Wydaje mi się, że Vaadin nie ma nic wspólnego z problemem.

Prawdopodobnie istnieje (prawdopodobnie) okrągły problem z zależnością, ale problem leży w ClassNotFoundException. Do jakiego serwera aplikacji jesteś wdrażany? Czy jest to pełnoprawna Java EE 6 AS? Jeśli nie, być może brakuje niektórych bibliotek w swoim wdrożeniu.

+0

Używam JBoss 7.1. To nie powinno być problemem. –

0

Istnieje kilka podejść do rozwiązania zależności cyklicznej, ale kiedy ten wyjątek zostanie zgłoszony, może to być coś nie tak z architekturą.

Ale rozważyć zobaczyć this answer