【问题标题】:Stateful EJB does not keep property value有状态 EJB 不保留属性值
【发布时间】:2012-12-28 05:07:24
【问题描述】:

我正在使用有状态 EJB 来保存我的登录信息:

@Stateful
public class SecurityService {

    private static final Logger log4jLogger = Logger.getLogger(SecurityService.class);

    @Inject UtenteDao utenteDao;
    @Inject AutorizzazioneDao autorizzazioneDao;

    private Utente utenteCorrente;

    private Negozio negozioCorrente;

    public SecurityService() {

    }

    public boolean authenticate() {

        boolean result = false;

        Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
        if (principal!=null) {
            utenteCorrente = utenteDao.findByUsername(principal.getName());
        }

        if (negozioCorrente!=null && utenteCorrente!=null) {
            Autorizzazione a = autorizzazioneDao.cercaPerNegozioAndUtente(negozioCorrente, utenteCorrente);
            result = a!=null;
        }

        return result;
    }

// ... }

我的 JSF 登录页面由以下人员控制:

@Named
@RequestScoped
public class LoginController {

@Inject private SecurityService securityService;

private String username;    
private String password;

private Negozio negozio;

public void login() throws IOException {

    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext externalContext = context.getExternalContext();
    HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();

    try {

        if (request.getUserPrincipal() != null) {
            request.logout();
        }
        request.login(username, password);

        securityService.setNegozioCorrente(negozio);
        if (!securityService.authenticate()) {
            throw new ServletException("Utente non abilitato.");
        }

        externalContext.redirect("/pippo/");

    } catch (ServletException e) {
        e.printStackTrace();
        context.addMessage(null, new FacesMessage("Accesso Negato"));        
    }
}

public void logout() throws IOException {
//...

}

public String getLoggedUsername() {
    Utente utenteCorrente = securityService.getUtenteCorrente();
    String fullName = "";
    if (utenteCorrente!=null) {
        fullName = utenteCorrente.getNomeCompleto();
    } else {
        System.out.println("Utente NULLO");
    }
    return fullName;
}
//... 

}

我的用户实际上可以按照我想要的方式登录(通过我的域添加一些程序的安全性)。

我遇到的问题是在下一页,当您已经登录时。我想在所有页面中显示标题“欢迎!您以#{loginController.loggedUsername} 登录。

我不断收到 null securityService.getUtenteCorrente()

SecurityService EJB 的行为类似于无状态会话 bean!我想知道我是否误解了关于有状态 EJB 的某些内容,或者我只是省略了一些内容以使其按预期工作。

我的目标只是拥有一个“会话范围”的 bean 来保持用户状态。是否需要 EJB 或者我可以只使用 SessionScoped JSF ManagedBean?

【问题讨论】:

标签: jsf session jakarta-ee ejb stateful


【解决方案1】:

LoginController 是请求范围的,而您的 SecurityService 是依赖范围的(出于所有目的,它不是会话范围的,除非您这样指定)。因此,当第二个 JSF 页面在 EL 表达式中引用 LoginController 时,将创建一个新的 LoginController 实例,该实例将引用 SecurityService SFSB 的不同实例。

如果您需要访问原始的SecurityService 实例,您应该将其标记为@SessionScoped,以便像LoginController 这样的客户端可以跨请求访问它们。但是,您可能还想首先考虑为什么需要 @Stateful 注释,因为此任务可以由 @SessionScoped 托管 bean 完成。您实际上并不需要 SFSB 来存储对您的 User/Principal 对象的引用。

【讨论】:

  • 好的,谢谢。它现在有效,但你让我思考。我阅读了一些有关有状态和无状态的内容,但仍然无法在简单的 Web 应用程序中找到有状态的有效用例。也许你可以给我推荐一个?我已经使用 Stateless 来拥有 EJB(以及事务方法)。
  • @FabioB.:SFSB 通常用于 CDI 对话,因为只有 SFSB 可以引用扩展的持久性上下文。在 Web 应用程序中,这通常是您使用 SFSB 以事务方式跨多个 HTTP 请求管理持久性上下文的地方。一个典型的用例是一个 JSF 组件(如向导),它引用一个 SFSB 来管理向导的状态,由数据库支持。
  • 这是一个非常有用的 S.O.用户! :)
【解决方案2】:

为了被管理会话 bean 必须使用 @EJB 注释声明或使用 JNDI 查找,你注入它的方式只是给你一个不受应用服务器管理的普通对象,实际上你创建一个新的对象随时使用。

【讨论】:

  • 你说得对,我误解了@EJB end @Inject 之间的区别。感谢@Vineet 的详尽解释。
猜你喜欢
  • 1970-01-01
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多