【问题标题】:Managed property inheritance托管属性继承
【发布时间】:2012-11-04 12:01:01
【问题描述】:

我的问题与issue 类似。我有一个 BaseBean,它目前只有一个属性,注释为 @ManagedProperty

但是,当我在命令按钮操作方法中访问此 inherited 托管属性的 getter 时,它返回 null。我调试并确认基础 bean 构造函数被调用了两次 - 一次是在页面加载时,然后是在单击按钮时,如上述链接中所述。

我按照文章选择的答案以及this帖子中提到的建议进行操作,但无济于事。

以下是我的代码:

public abstract class BaseBean
{
   @ManagedProperty(value = "#{serviceLocator}")
   private IServiceLocator serviceLocator;

   public IServiceLocator getServiceLocator() {
      return serviceLocator;
   }

   public void setServiceLocator(IServiceLocator serviceLocator) {
      this.serviceLocator = serviceLocator;
   }
}

@ManagedBean
@ViewScoped
public class RegistrationBean extends BaseBean implements Serializable
{
   private static final long serialVersionUID = -6449858513581500971L;

   private String userID;
   private String password;
   private String firstName;
   private String lastName;
   private String email;
   private String addressLine1;
   private String addressLine2;
   private String city;
   private String state;
   private String pincode;

   private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationBean.class);

   /* getter / setters */

   public String register() 
   {
      String nextPage = null;
      try {
         RegistrationDetails userDetails = ModelBuilder.populateRegistrationData(this);
         int registrationID = getServiceLocator().getUserService().registerUser(userDetails);
         LOGGER.info("Registered user successfully. Registration ID - {}", registrationID);
         nextPage = "success";
      }
      catch (RegistrationException e) {
         LOGGER.error(e.getMessage());
      }
      return nextPage;
   }

   public void checkUserExists() 
   {
      int regID = getServiceLocator().getUserService().findUser(getUserID());

      if(regID > 0) {
         FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "User already exists !!", null);
         FacesContext.getCurrentInstance().addMessage(null, message);
      }
   }
}

为什么要在表单提交时再次调用构造函数??? :/

即使在通过 ajax 对 userID 字段的 blur 事件调用的 checkUserExists() 方法中,getter 也会返回 null。

编辑:添加了 ServiceLocator 的代码..

@ManagedBean
@ApplicationScoped
public class ServiceLocator implements IServiceLocator
{
   private static final String USER_SERVICE = "userService";
   private static final String MOVIE_SERVICE = "movieService";

   @PostConstruct
   public void init() {
      final ServletContext sc = FacesUtils.getServletContext();
      this.webAppContext = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
      this.userService = (IUserService) webAppContext.getBean(USER_SERVICE);
      this.movieService = (IMovieService) webAppContext.getBean(MOVIE_SERVICE);
   }

   private ApplicationContext webAppContext;

   private IUserService userService;

   private IMovieService movieService;

   @Override
   public IUserService getUserService() {
      return userService;
   }

   @Override
   public IMovieService getMovieService() {
      return movieService;
   }
}

【问题讨论】:

  • register 的返回字符串怎么样,这会导致视图 bean 被重新创建...
  • @Daniel :NPE 在到达 return 语句之前发生。 getServiceLocator() 返回 null... :|
  • 在这里查看我的答案:stackoverflow.com/a/46792693/1599699

标签: jsf inheritance jsf-2


【解决方案1】:

AFAIK 你试图混合两个答案:一个是@RequestScoped mbeans,另一个是@ViewScoped mbeans。如果您看到您发布的第一个链接,BalusC 表示您不必在@ViewScoped mbeans 中包含@ManagedProperty,如ViewParam vs @ManagedProperty(value = “#{param.id})” 所示。

如果您无法通过视图参数传递serviceLocator,则必须找到另一种方法来获取该值(从会话中保存/检索它)。

另外,请查看 BalusC 的此信息,解释为什么可以在每个请求上重新创建 @ViewScoped mbean:

简而言之:当任何 UIComponent 使用绑定属性绑定到 bean 或在视图中使用 JSTL 或标记时,@ViewScoped 会中断。在这两种情况下,bean 的行为都类似于请求范围的。第一个在我看来是一个相当大的错误,第二个只是在 Facelets 中摆脱整个 JSTL 内容的额外借口。

这与 JSF 2.0 问题 1492 有关。以下是相关性摘录: 这是部分状态保存的先有鸡/先有蛋的问题。视图被执行以填充视图应用增量状态之前,因此我们看到了您所描述的行为。 在这一点上,我看不到解决此用例的明确方法。 如果必须使用视图范围的绑定,解决方法是将 javax.faces.PARTIAL_STATE_SAVING 设置为 false。

来自


根据您的评论和编辑,您可以使用此处提供的代码访问@ApplicationScoped mbean:

这将是一行:

FacesContext.getCurrentInstance().getExternalContext()
    .getApplicationMap().get("serviceLocator");

您必须使用该代码,因为显然@ViewScoped bean 不能接受@ManagedProperty 的注入。

【讨论】:

  • ServiceLocator 是一个应用程序范围的 bean,它只是委托对服务的调用。我在我的问题中发布了 ServiceLocator 代码。谢谢,指出我的困惑.. :)
  • 这似乎有效:D。我没有使用这种方法,因为我认为它可以通过注射获得。那么,这对 Viewscope 有什么影响吗???
  • @VrushankDesai 显然是的,除了使用 <f:viewparam> 之外,您似乎无法在 @ViewScoped 托管 bean 中注入 bean/值。这很奇怪(即使对我来说也是如此),但我们必须以 atm =\ 的方式使用该技术。至少,您设法解决了您的问题=)。不要忘记将此帖子标记为答案。
【解决方案2】:

ServiceLocator 的代码未显示,因此有许多未决问题可能有助于确定问题的答案。我会发表评论或提出问题,也许某些事情会触发“啊哈!”给你:

  • 验证 ServiceLocator 实际上是用 @ManagedBean 注释的。

  • 请记住,您不能注入比目标 bean 范围(生命周期)更短的 bean。在这种情况下,如果ServiceLocator@RequestScoped,那么它不能被注入到你的@ViewScoped bean 中。

  • 我们是否可以假定IServiceLocator 是由某个托管bean ServiceLocator 实现的接口?

  • ServiceLocator 闻起来像 EJB;如果是,请使用@EJB 注入 EJB。

【讨论】:

  • 是的,不是的,是的,不是的。用服务定位器类的代码更新了我的问题.. :)
猜你喜欢
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 2012-05-08
  • 2012-08-15
相关资源
最近更新 更多