简体   繁体   中英

CDI Producer causes stackoverflow

I want to create a producer to choose an implementation of my Interface Hello dynamically.

public interface Hello extends Serializable{

     public String sayHello();
}

Hello Impls:

public class HelloBanned implements Hello{

    @Override
    public String sayHello() {
        return "Get out!!!";
    }  
}

public class HelloCoolGuy implements Hello{

   @Override
   public String sayHello() {
       return "Welcome";
   }   
}

My sessionBean, where I want the producer method:

public class UsuarioHandler implements Serializable{

    @Inject
    private Usuario usuario;
    @Inject
    @Preferred
    Hello hello;
    @EJB
    UsuarioBeanLocal userEJB;

    public String login(){
        usuario.setId(2L);
        return userEJB.efetuarLogin(usuario);
    }
    @Produces
    @Preferred
    public Hello getHello(@New HelloBanned ban,
                      @New HelloCoolGuy cool){
        if (usuario.isBannedFlag()){
            return ban;
        }
        return cool;
    }
}

This code result on StackOverFlow. I can't find what can be causing it.

In CDI producers support injection. Since, your class UsuarioHandler is both the producer and the injection target a stack overflow is the expected result. Think about it:

  1. After UsuarioHandler is instantiated as a managed bean, @Preferred Hello hello needs to be injected.
  2. Then the producer for @Preferred Hello hello needs instantiated, also your UsuarioHandler .
  3. But the producer itself needs an instance of @Preferred Hello hello injected as well.
  4. So another producer is instantiated, and so on.

Since the cope for your UsuarioHandler is @Default , the container doesn't proxy it, therefore creating a new instance each time one is needed, as producer or as a managed bean.

Make your Producer Method "getHello" static (can even be private) and pass the Usuario as a parameter.

@Produces
@Preferred
private static  Hello getHello(@New HelloBanned ban,
                      @New HelloCoolGuy cool, Usuario usuario){
    if (usuario.isBannedFlag()){
       return ban;
    }
    return cool;
}

I find the most common issue with CDI not working in a project is the fact that the XML bean descriptor for CDI is missing. Add the beans.xml into your META-INF/beans.xml or WEB-INF/beans.xml

The descriptor can be empty like so:

    <?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_0.xsd">
</beans>

To find out more about the beans.xml file please refer to this link: http://www.seamframework.org/Documentation/WhatIsBeansxmlAndWhyDoINeedIt

If this is not the issue then please paste in your stacktrace so we can see what the error you're getting is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM