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

发布于 2024-10-21 22:21:36 字数 2963 浏览 4 评论 0原文

好的,这是我的会话 bean。我总是可以从任何 Servlet 或 Filter 中检索 currentUser。这不是问题,问题是 fileList 和 currentFile。我已经用简单的整数和字符串进行了测试,其效果相同。如果我从视图作用域 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!");
        }
    }

这是一个例子。

我的观点范围是bean。这是它的装饰方式。

 @ManagedBean
 @ViewScoped
 public class ViewLines implements Serializable {

    @Inject
    private UserSessionBean userSessionBean; 

现在是代码。

    userSessionBean.setCurrentFile(file);
    System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());

我可以完美地看到当前的文件名。这实际上是从 jsf 操作方法打印的。显然当前文件正在被设置。

现在如果我这样做。

@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() {
    }
}

currentUser 显示正常,但我看不到该文件。只是一片空白。字符串、整数等也会发生同样的情况。

感谢您对此提供的任何帮助。

信息:UserSessionBean:第3B行--8531268875812004316.csv(从视图范围bean打印的值)

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

**编辑**

这有效。

 FacesContext context = FacesContext.getCurrentInstance();
    userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);

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

注入是否只允许您访问 bean 而不能更改它们的属性?

Ok here is my session bean. I can always retrieve the currentUser from any Servlet or Filter. That's not the problem The problem is the fileList, and currentFile. I've tested with simple int's and Strings and its' the same effect. If I set a value from my view scoped bean I can get the data from another class.

@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!");
        }
    }

Here is an example.

My view scoped bean. This is how it is decorated.

 @ManagedBean
 @ViewScoped
 public class ViewLines implements Serializable {

    @Inject
    private UserSessionBean userSessionBean; 

Now the code.

    userSessionBean.setCurrentFile(file);
    System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());

I can see the current file name perfectly. This is actually being printed from a jsf action method. So obviously the currentFile is being set.

Now if I do this.

@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() {
    }
}

currentUser shows up fine but I can't see the file. It's just blank. The same thing happens with Strings, int's, etc.

Thanks for any help you can provide on this.

INFO: UserSessionBean : Line 3B--8531268875812004316.csv (value printed from view scoped bean)

INFO: File filter tester.csv (value printed when filter is ran.)

**EDIT**

This worked.

 FacesContext context = FacesContext.getCurrentInstance();
    userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);

I put this in the constructor of the ViewScoped and everything was fine. Now why isn't the inject doing what I thought? At first I thought maybe because I was using JSF managed beans instead of the new CDI beans. But I changed the beans to the new style(with named) and that was the same effect.

Does the inject only allow you to access the beans but not change their attributes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明明#如月 2024-10-28 22:21:36

您正在混合 JSF 和 CDI。您的 UserSessionBean 是一个 JSF @ManagedBean,但您正在使用 CDI @Inject 将其注入另一个 bean 中。 CDI 不会重用 JSF 托管的,而是创建一个全新的。使用其中之一,而不是同时使用两者。注入 JSF 托管 bean 的正确注释是 <代码>@ManagedProperty

替换

@Inject
private UserSessionBean userSessionBean; 

@ManagedProperty(value="#{userSessionBean}")
private UserSessionBean userSessionBean; 

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

或者,将所有 JSF bean 管理注释迁移到 CDI bean 管理注释。

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

@Named
@SessionScoped
public class UserSessionBean implements Serializable {}

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

@Named
@ViewScoped
public class ViewLines implements Serializable {}

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

此外,自 JSF 2.3 以来,JSF bean 管理注释已被弃用。另请参阅支持 Bean (@ManagedBean) 或 CDI Bean (@Named)?

You're mixing JSF and CDI. Your UserSessionBean is a JSF @ManagedBean, yet you're using CDI @Inject to inject it in another bean. CDI doesn't reuse the JSF managed one, it instead creates a brand new one. Use the one or the other, not both. The correct annotation to inject a JSF-managed bean is @ManagedProperty.

Replace

@Inject
private UserSessionBean userSessionBean; 

by

@ManagedProperty(value="#{userSessionBean}")
private UserSessionBean userSessionBean; 

and ensure that you don't have a import javax.enterprise.context anywhere in your code (which is the package of CDI annotations).

Alternatively, migrate all JSF bean management annotations to CDI bean management annotations.

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

@Named
@SessionScoped
public class UserSessionBean implements Serializable {}

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

@Named
@ViewScoped
public class ViewLines implements Serializable {}

Additional advantage is that you can just @Inject it inside a regular servlet or filter without the need to manually grab it as request/session/application attribute.

Moreover, JSF bean management annotations are deprecated since JSF 2.3. See also Backing beans (@ManagedBean) or CDI Beans (@Named)?

薔薇婲 2024-10-28 22:21:36

我对为什么会发生这种情况的最佳猜测是因为变量文件被设置在视图范围中,然后通过引用传递到会话范围 bean 中。也许发生这种情况是因为当视图范围 bean 被销毁时,它仍然具有对该变量的引用,但不会费心查看会话范围中是否有任何其他对它的引用,而会话范围应该保留它。因此,在这种情况下,当它被销毁时,它会从视图和会话范围中删除。

您可以尝试使用用“new”实例化的对象调用 setCurrentFile 吗?这可能会证明或反驳我的这个假设。

否则,我最好的建议是打开调试器,并准确查看 getCurrentFile 正在更改的位置。

My best GUESS as to why this is happening, is because the variable file, is being set in view scope, and then passed by reference into the session scoped bean. Maybe this is happening because when the view scope bean is destroyed, it still has a reference to that variable, but doesn't bother to see if there's any other references to it in session scope, where it should be preserved. Hence, when it's destroyed, it's removed from both view and session scope in this case.

Could you try calling setCurrentFile with an object instantiated with 'new'? That might prove or disprove this hypothesis of mine.

Otherwise, my best advice would be to crack open the debugger, and see exactly where getCurrentFile is being changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文