托管属性继承

时间:2012-11-04 12:01:01

标签: jsf inheritance jsf-2

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

但是,当我在action方法a commandbutton中访问此继承的托管属性的getter时,它返回null。我调试并确认基本bean constructr被调用了两次 - 一次在页面加载时,然后单击按钮,如上面提到的链接中所述。

我按照文章所选答案以及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;
   }
}

2 个答案:

答案 0 :(得分:1)

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

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

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

  

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

     

这与JSF 2.0问题1492有关。以下是相关性摘录:   这是鸡/蛋问题,部分省钱。执行视图以在应用 delta状态之前填充视图,因此我们会看到您描述的行为。   此时,我没有看到解决此用例的明确方法。   解决方法是,如果必须使用视图范围的绑定,则将javax.faces.PARTIAL_STATE_SAVING设置为false。


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

这就是这一行:

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

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

答案 1 :(得分:0)

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

  • 确认ServiceLocator实际上已使用@ManagedBean进行了注释。

  • 请记住,您不能注入比目标bean更短的范围(生命周期)的bean。在这种情况下,如果ServiceLocator@RequestScoped,则无法将其注入@ViewScoped bean。

  • 我们假设IServiceLocator是由某个托管bean ServiceLocator实现的接口吗?

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