Question

I'm trying to implement login mechanizm using CDI @javax.enterprise.context.SessionScoped

Code:

@Named
@SessionScoped
public class Auth implements Serializable {

  private User user;

  @Inject
  private UserStore userStore;

  @Produces @CurrentUser
  public User getUser() {
    if (user == null) {
        Principal principal= FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();

            if (principal != null) {

                Map parameters = new HashMap();
                parameters.put("email", principal.getName());

                user = (User) userStore.findWithNamedQuery(User.GET_BY_EMAIL, parameters).get(0);
            }
        }

        return user;
    }

    public void logout() throws IOException {
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ec.invalidateSession();
        ec.redirect(ec.getRequestContextPath() + "/");
    }
}

The class that always receives the same User instance:

@Stateful
public class NewsService implements Serializable {

    @Inject @CurrentUser
    private User currentUser;

    @Inject
    private NewsStore newsStore;

    public List<News> getNewsForLoggedUser(Integer start, Integer limit) {
        Map<String, Object> params = new HashMap<>();
        params.put("user", currentUser);

        return (List<News>) newsStore.findWithNamedQuery(News.getAllForUser, params, start, limit);
    }
}

There problem is with getUser() method. Even though the session was invalidated it still returns value from the first login. How can I destroy CDI bean or change it so it outputs always actual value? I tried annotation logout() method with @PreDestroy, but it produces such error:

13:20:50,329 ERROR [org.jboss.weld.Bean] (default task-22) WELD-000019 Error destroying an instance Managed Bean [class com.intenso.presentation.Auth] with qualifiers [@Default @Any @Named] of com.intenso.presentation.Auth@59821e

I'm running on WildFly 8.0.0.Alpha4

Was it helpful?

Solution

The problem probably comes from the fact that your producer doesn't have an explicit scope, so it has the @Dependentpseudo-scope. That means the producer code is called once at your EJB build-time and that the Injected value stays the same for all your EJB life.

You didn't mention how your @Stateful EJB is used, but I assume that it's injected in another piece of code so your code keep it longer than a request.

To correct your bug your should give a normal scope to your producer (@RequestScopedseems the best choice). So your producer code will become

@Produces @CurrentUser @RequestScoped
public User getUser() { ... }

Remember a producers doesn't inherit the scope from the bean that contains it. With this normal scope, the user bean won't be directly injected, but CDI will inject a proxy of it. Thus the currentUser will stay the same only during the life of the current request.

Don't hesitate to read the dependent scope chapter of the CDI 1.1 spec, it's quite helpful

OTHER TIPS

i have had similar issues before, i feel ur session pages are cached and you to clear them by doing this

HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");          // HTTP 1.1
httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0
httpResponse.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(request, response);

in your FilterServlet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top