4

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

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

我遵循了文章选择的答案以及这篇文章中提到的建议但无济于事。

以下是我的代码:

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);
      }
   }
}

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

checkUserExists()即使在通过 ajax 对 userID 字段的 blur 事件调用的方法中,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;
   }
}
4

2 回答 2

1

AFAIK 您试图混合两个答案:一个用于@RequestScopedmbeans,另一个用于@ViewScopedmbeans。如果您看到您发布的第一个链接,BalusC 表示您不必@ManagedProperty@ViewScopedmbeans 中拥有,如ViewParam 与 @ManagedProperty(value = “#{param.id})”</a> 所示。

如果您无法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");

您必须使用该代码,因为显然@ViewScopedbean 不能接受@ManagedProperty.

于 2012-11-04T17:27:58.767 回答
0

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

  • 验证它ServiceLocator实际上是用@ManagedBean.

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

  • 我们是否假设这IServiceLocator是某个托管 bean 实现的接口ServiceLocator

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

于 2012-11-04T17:21:15.410 回答