无法在另一个@ManagedBean中@Inject一个@ManagedBean

Dre*_*w H 2 jsf inject cdi managed-bean

好的,这是我的会话bean.我总是可以从任何Servlet或Filter中检索currentUser.这不是问题问题是fileList和currentFile.我用简单的int和Strings进行了测试,并且它的效果相同.如果我从视图范围bean中设置一个值,我可以从另一个类中获取数据.

@ManagedBean(name = "userSessionBean")
@SessionScoped
public class UserSessionBean implements Serializable, HttpSessionBindingListener {

    final Logger logger = LoggerFactory.getLogger(UserSessionBean.class);

    @Inject
    private User currentUser;

    @EJB
    UserService userService;

    private List<File> fileList;   

    private File currentFile;

    public UserSessionBean() {

        fileList = new ArrayList<File>();
        currentFile = new File("");
    }

    @PostConstruct
    public void onLoad() {

        Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
        String email = principal.getName();

        if (email != null) {
            currentUser = userService.findUserbyEmail(email);
        } else {

            logger.error("Couldn't find user information from login!");
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是一个例子.

我的观点是scoped bean.这就是它的装饰方式.

 @ManagedBean
 @ViewScoped
 public class ViewLines implements Serializable {

    @Inject
    private UserSessionBean userSessionBean; 
Run Code Online (Sandbox Code Playgroud)

现在的代码.

    userSessionBean.setCurrentFile(file);
    System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());
Run Code Online (Sandbox Code Playgroud)

我可以完美地看到当前的文件名.这实际上是从jsf动作方法打印的.很明显,currentFile正在设置中.

现在,如果我这样做.

@WebFilter(value = "/Download")
public class FileFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {        
        HttpSession session = ((HttpServletRequest) request).getSession(false);
        UserSessionBean userSessionBean = (UserSessionBean) session.getAttribute("userSessionBean");       

        System.out.println(userSessionBean.getCurrentUser().getUserId()); //works

        System.out.println("File filter" + userSessionBean.getCurrentFile().getName()); //doesn't work


        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}
Run Code Online (Sandbox Code Playgroud)

currentUser显示正常,但我看不到该文件.它只是空白.Strings,int等也会发生同样的事情.

感谢您提供的任何帮助.

INFO:UserSessionBean:第3B行 - 8531268875812004316.csv(从视图作用域打印的值)

信息:文件过滤器tester.csv(运行过滤器时打印的值.)

**编辑**

这很有效.

 FacesContext context = FacesContext.getCurrentInstance();
    userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);
Run Code Online (Sandbox Code Playgroud)

我把它放在ViewScoped的构造函数中,一切都很好.现在为什么不按照我的想法进行注射?起初我想也许是因为我使用的是JSF托管bean而不是新的CDI bean.但是我将bean更改为新样式(带有命名),这也是同样的效果.

注入只允许您访问bean但不更改其属性吗?

Bal*_*usC 5

你正在混合JSF和CDI.你UserSessionBean是一个JSF @ManagedBean,但你正在使用CDI @Inject将它注入另一个bean.CDI不重用JSF托管的,而是创建一个全新的.使用其中一个,而不是两个.注入JSF管理的bean的正确注释是@ManagedProperty.

更换

@Inject
private UserSessionBean userSessionBean; 
Run Code Online (Sandbox Code Playgroud)

通过

@ManagedProperty(value="#{userSessionBean}")
private UserSessionBean userSessionBean; 
Run Code Online (Sandbox Code Playgroud)

并确保import javax.enterprise.context您的代码中没有任何地方(这是CDI注释的包).

或者,将所有JSF bean管理批注迁移到CDI bean管理批注.

import javax.inject.Named;
import javax.enterprise.context.SessionScoped;

@Named
@SessionScoped
public class UserSessionBean implements Serializable {}
Run Code Online (Sandbox Code Playgroud)

import javax.inject.Named;
import javax.faces.view.ViewScoped;

@Named
@ViewScoped
public class ViewLines implements Serializable {}
Run Code Online (Sandbox Code Playgroud)

另外一个优点是,您可以@Inject在常规servlet或过滤器中使用它,而无需手动将其作为请求/会话/应用程序属性获取.

此外,自JSF 2.3以来,不推荐使用JSF bean管理注释.另请参阅Backing beans(@ManagedBean)或CDI Beans(@Named)?