2012-08-14 16 views
9

Intento crear una aplicación web con el paradigma MVP. Como quiero que la API esté limpia y que todo sea fácil de probar, intento inyectar todo lo posible a través de Contructor Injection. Ahora llegué a un punto en el que tengo una vista con múltiples campos de texto. Estos campos de texto se llenan por el presentador cuando hay valores para él en el DB, por lo que mi presentador necesita una referencia de la vista, pero obviamente, el público también necesita una referencia del presentador. CDI me dice que la inyección de Presenter en la vista y de lo contrario no es posible debido a las dependencias circulares. ¿Es posible evitar configurar el presentador en la vista a través de un método setter? El código es como la siguiente:MVP con CDI; evitando la dependencia circular

Vista:

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

Presentador:

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

Aquí tengo la dependencia cíclica. Para evitar que he tratado de utilizar la interfaz de Instancia y cambió el presentador a esto:

Presentador:

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

Pero cuando lo hago me sale un java.lang.NoClassDefFoundError: org/jboss/soldadura/inyección/Excepciones

actualización: Aquí es el seguimiento de la pila

[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

Añadir 'org.jboss.weld.injection.Exceptions' a la ruta de clases, al menos, para que pueda ver lo que la excepción es – artbristol

Respuesta

5

Lo tengo para trabajar ahora. La sugerencia de Nikita Beloglazov ayudó mucho porque, según tengo entendido, el problema es realmente el momento en que se realiza la instanciación. Como me quiero quedar con la inyección de constructor Elegí el segundo enfoque:

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

Para conseguir que esto funcione tengo que inyectar solamente un objeto proxy en el momento de la inyección de constructor y obtener la instancia real en el momento en que la primera acción en el objeto se realiza. Este es el comportamiento normal de los frijoles de ámbito normal. Así que hice el presentador y la vista @SessionScoped y extendí las interfaces desde Serializable. Ahora la inyección de Constructor funciona y ViewImpl es "inyección lenta".

+0

Este enfoque realmente soluciona la dependencia circular, pero tenga en cuenta que esta excepción le muestra que hay algo mal con su arquitectura. Ver [esta respuesta] (http://stackoverflow.com/a/15301179/1113510) de @nick – Moesio

5

Intenta mover puntos de inyección desde el constructor a las propiedades. Así que anota las propiedades con @Injection, no constructor. Creo que de esta manera Weld primero crea instancias de clases y solo luego inyecta dependencias. Y reemplace su constructor por defecto.
Si anota la soldadura del constructor necesita tener una instancia de Vista al crear Presenter, pero para crear la vista necesita el presentador. Con el constructor predeterminado y las propiedades anotadas, puede crear Vista y Presentador y solo luego inyectárselas entre sí.

0

Me parece que Vaadin no tiene nada que ver con el problema.

Puede haber (probablemente) un problema de inyección de dependencia circular, pero el problema está en el ClassNotFoundException. ¿En qué servidor de aplicaciones está implementando? ¿Es un Java EE 6 AS de pleno derecho? De lo contrario, tal vez le falten algunas bibliotecas en su implementación.

+0

estoy usando JBoss 7.1. Ese no debería ser el problema. –

0

Hay algunos enfoques para resolver la dependencia circular, pero cuando se lanza este tipo de excepción, tenga en cuenta que podría haber algún problema con su arquitectura.

pero considere ver this answer