Domanda

Sto cercando di iniettare un bean definito in un contesto primavera in una CDI componente gestito ma non sono riuscito. Il bean non viene iniettato, anziché una nuova istanza viene creata ogni volta l'iniezione deve essere eseguita. Il mio ambiente è Tomcat 7 con JBoss Weld.

La primavera è ApplicationContext straighforward:

<beans>
  ...
  <bean id="testFromSpring" class="test.Test" />
  ...
</bean>

Le CDI gestito aspetto di fagioli come questo:

@javax.inject.Named("testA")
public class TestA {

  @javax.inject.Inject
  private Test myTest = null;

  ...

  public Test getTest() {
    return this.myTest;
  }

}

Questa è la mia faces-config.xml

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0">
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
  </application>
</faces-config>

Tuttavia, quando ho accedere alla proprietà test dall'interno di una pagina JSF, una nuova istanza Test viene creato ogni volta che si verifica l'accesso. Questo è un semplice esempio:

<html>
  ...
  <p>1: <h:outputText value="#{testFromSpring}" /></p>
  <p>2: <h:outputText value="#{testA.test}" /></p>
  ...

ottengo il seguente output:

1: test.Test@44d79c75
2: test.Test@53f336eb

Dopo un aggiornamento:

1: test.Test@44d79c75
2: test.Test@89f2ac63

I può vedere che la prima uscita è corretta. Non importa quante volte ho aggiornare la pagina, il testFromSpring restituisce il valore dal fagiolo definito nel contesto primavera. Tuttavia la seconda uscita chiaramente mostra che ogni volta che il metodo getTest sui componenti test viene invocato, una nuova istanza Test viene creata e iniettato invece di utilizzare l'istanza dal contesto Spring come ci si aspetterebbe.

Quindi, qual è il motivo di questo comportamento?

Come posso Iniettare il fagiolo dal contesto molla nel bean gestito CDI?

Ho anche provato ad utilizzare un qualificatore utilizzando il nome definito nel contesto primavera, ma ora viene generata un'eccezione che indica, che il fagiolo non può essere trovato:

org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies.  Injection point:  field test.TestA.myTest;  Qualifiers:  [@javax.inject.Named(value=testFromSpring)]

per il codice

@javax.inject.Named("testA")
public class TestA {

  @javax.inject.Inject
  @javax.inject.Named("testFromSpring")
  private Test myTest = null;
È stato utile?

Soluzione

Pascal è giusto che non si può iniettare qualcosa gestito da primavera in un chicco di saldatura (o viceversa).

Ma è possibile definire un produttore che ottiene i fagioli di primavera e dà loro da saldare. Questo suona come un estremo hack, btw, e non credo che si suppone di utilizzare entrambi i quadri in un unico progetto. Scegli uno e rimuovere l'altro. In caso contrario, si otterrà in più problemi.

Ecco come sarà simile.

@Qualifier
@Retention(Runtime)
public @interface SpringBean {
     @NonBinding String name();
}


public class SpringBeanProducer {

    @Produces @SpringBean
    public Object create(InjectionPoint ip) {
         // get the name() from the annotation on the injection point
         String springBeanName = ip.getAnnotations()....

         //get the ServletContext from the FacesContext
         ServletContext ctx = FacesContext.getCurrentInstance()... 

         return WebApplicationContextUtils
              .getRequiredWebApplication(ctx).getBean(springBeanName);
    }
}

Quindi è possibile avere:

@Inject @SpringBean("fooBean")
private Foo yourObject;

P.S. È possibile effettuare la sopra più type-safe. Invece di ottenere il fagiolo per nome, è possibile ottenere, attraverso la riflessione, il tipo generico del punto di iniezione, e cercarlo nel contesto primavera.

Altri suggerimenti

Non credo Weld può iniettare qualcosa che non è riuscito (un'istanza) di saldatura (un chicco di primavera nel tuo caso).

C'è anche il progetto JBoss Bucaneve. Non so se funzionerà con JBoss saldare Tomcat, la documentazione viene descritta su JBoss 5, 6 e 7. Secondo http://docs.jboss.org/snowdrop/2.0.0.Final/html/ch03.html#d0e618 si inietta fagioli dichiarato in JBoss-spring.xml in posizioni contrassegnate con @Spring invece di @Inject. Non me l'esperienza, però, YMMV.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top