这个 JSF 模式会破坏依赖注入吗?

发布于 2024-12-07 18:34:57 字数 790 浏览 0 评论 0原文

我有一个 JSF2 项目(GlassFish 3.1 上的 Mojarra)。

我有一个 ViewScoped bean,它通过实用程序类引用服务,如下所示:

@ManagedBean
@ApplicationScoped
public static class ServicesUtil {
  @EJB
  UserService userService;
  @EJB
  EmailService emailService;
  /** getters/setters **/
}

我的问题是

@ManagedBean
@ViewScoped
public class UserHandler {
  public String method() {
     ServicesUtil.getUserService().doUserStuff();
     return "newPage";
  }
}

,由于 ServicesUtil 是 ApplicationScoped,这是否意味着整个应用程序的每个服务只有一个实例?这是不好的做法吗?如果操作正确,GlassFish 中的 CDI 实际上会根据需要创建新实例吗?

同样,如果将服务注入到 UserHandler 中,应用程序是否会更具可扩展性?

我们添加 ServicesUtil 层的原因是我的一位同事说,当处理程序为 ViewScope 时,他偶尔会遇到注入无法正常工作的问题。在 ViewScoped bean 中使用 @EJB 是否会遇到困难?

非常感谢任何帮助!

I have a JSF2 project (Mojarra on GlassFish 3.1).

I have a ViewScoped bean that references services through a utility class like so:

@ManagedBean
@ApplicationScoped
public static class ServicesUtil {
  @EJB
  UserService userService;
  @EJB
  EmailService emailService;
  /** getters/setters **/
}

and

@ManagedBean
@ViewScoped
public class UserHandler {
  public String method() {
     ServicesUtil.getUserService().doUserStuff();
     return "newPage";
  }
}

My question is, since the ServicesUtil is ApplicationScoped, does that mean there is only one instance of each service for the entire application? And is this bad practice? If done correctly, would the CDI in GlassFish actually create new instances as they are needed?

Similarly, if the Services were injected into the UserHandler instead would the application be more scalable?

The reason we added the ServicesUtil layer is one of my coworkers said that he occasionally had problems getting the injection to work in the Handler when it is ViewScope. Should there be any difficulty using @EJB in a ViewScoped bean?

Any help is greatly appreciated!

Rob

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

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

发布评论

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

评论(1

并安 2024-12-14 18:34:57

您使用的模式似乎没有多大意义。将 EJB 注入视图作用域 bean 应该没有问题。

根据您使用的 EJB 类型(无状态、有状态或单例),情况有所不同。

如果 userService 和 emailService 是无状态的(它们很可能应该是无状态的),那么通过使用首先注入到应用程序范围的 bean 中的 bean,您将一无所获。也就是说,注入的不是 bean 本身,而是一个代理,并且每个对其的请求都会路由到不同的真实 bean 实例(请参阅 http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans)。

如果 userService 和 emailService 是有状态的,您确实会在这里获得一个实例,但我非常怀疑您是否需要在应用程序中的每个用户之间共享实际实例。但即使您希望这样做,一次也只有一个用户(线程)可以访问有状态 bean。

如果这些服务是单例的,您可以立即将它们注入视图作用域 bean 中。绝对没有理由通过应用程序范围的 bean。

此外,ServicesUtil.getUserService() 是一个静态方法,因此使用它来获取注入的服务很脆弱。如果您想使用它(您不应该,但假设)应该将 ServicesUtil 注入到 UserHandler 中。

然后,您似乎混淆了 CDI 和 JSF 托管 bean。我同意这很令人困惑,但目前就是这样。 @ViewScoped 不能与 CDI bean 组合使用。从您的代码中不清楚 @ManagedBean 是 JSF 变体还是 Java EE/CDI 变体。在本例中,如果您想使用视图范围,则应为 javax.faces.bean.ManagedBean。

The pattern you're using doesn't seem to make a lot of sense. There should be no problem with injecting EJBs into a view scoped bean.

Depending on the type of EJB you are using (stateless, stateful or singleton) different things hold.

If the userService and emailService are stateless (they most likely should be), you gain nothing by using a bean that's injected into an application scoped bean first. Namely, what's injected is not the bean itself but a proxy and every request to that is routed to a different real bean instance anyway (see http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans).

If the userService and emailService are stateful, you do get a single instance here, but I highly doubt you need to share actual between every user in your application. But even if you would want that, only a single user (thread) can access the stateful bean at a time.

If those services are singleton, you can just inject them right away into the view scoped bean. There is absolutely no reason to go via an application scoped bean.

Furthermore, ServicesUtil.getUserService() is a static method, so using this to get an injected service is brittle. If you want to use this (you shouldn't, but suppose) ServicesUtil should be injected into UserHandler.

Then, it seems you are confusing CDI and JSF managed beans. I agree this is confusing, but it's currently the way it is. @ViewScoped does not work in combination met CDI beans. From your code it's not clear if @ManagedBean is the JSF variant or the Java EE/CDI one. In this case it should be javax.faces.bean.ManagedBean if you want to use the view scope.

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