2012-01-23 2 views
1

우리는 JBoss 7.1, MySQL/PostgreSQL DB, JSF 2.0과 CDI 빈을 사용하고 있습니다.PhaseListener에서 @Named 빈에 액세스하는 방법은 무엇입니까?

로그인 및 비밀번호로 DB를 기반으로 인증을 구현해야합니다. 우리에게는 관리 (관리) 포털이 있습니다. 클라이언트가 로그인하지 않고 제한된 페이지를 열면 클라이언트가 로그인하지 않은 경우 해당 페이지를 login.* 페이지로 리디렉션해야합니다. PhaseListener을 사용하여이 작업을 시도했습니다. 로그인하고 로그 아웃 할 수 있지만 다른 페이지를 열려고하면 문제가 발생했습니다 : PhaseListener 클래스 안에 @Named("user") public class UserManager 콩을 가져올 수 없습니다. 나는 FacesContext, & EL ...을 사용하여 그것을 얻으려고 노력했다, 그 모두는 나를 도와주지 않았다.

UserManager은 로그인의 유효성을 검사하고 로그인 한 사용자를 current 속성으로 저장합니다. 모든 요청에 ​​대해 에 #{user.current}이 아닌 경우 null이 아닌지 확인하고 싶습니다. 하지만 PhaseListener#{user} 콩을 가져올 수 없습니다.

@Named 콩을 beforePhase() 또는 afterPhase()에 어떻게 얻을 수 있습니까?


업데이트는 :

private boolean loggedIn(FacesContext context) throws IOException, ServletException 
{ 
    LOGSTORE.debug("loggedIn().2 "); 

    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); 
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); 

// ELContext elContext = FacesContext.getCurrentInstance().getELContext(); 
// UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication() 
//  .getELResolver().getValue(elContext, null, "user"); 

    HttpSession session = (HttpSession) context.getExternalContext().getSession(true); 
    UserManager userManager = (UserManager) session.getAttribute("user"); 

// UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"); 

    if (!StringUtils.contains(((HttpServletRequest) context.getExternalContext().getRequest()) 
     .getRequestURL().toString(), URL_SESSION_EXPIRED)) 
    { 

     if (userManager == null || !userManager.isLoggedIn()) 
     { 
      LOGSTORE.debug(" userManager is " + (userManager == null ? "" : "not ") + " null"); 
      if (userManager != null) 
      { 
       LOGSTORE.debug(" userManager.isLoggedIn() is " 
        + (userManager.isLoggedIn() ? "TRUE" : "FALSE")); 
      } 
      LOGSTORE.debug(" doPhaseFilter() - START REDIRECT "); 
      response.sendRedirect(request.getContextPath() + "/" + homepage + "?auth-failed"); 
     } 
     return false; 

    } else 
    { 
     LOGSTORE.debug("loggedIn().3 it is " + homepage); 
     return true; 
    } 
} 
+0

* "FacesContext, EL ...을 사용하여 얻으려고했는데 모두 도움이되지 못했습니다"* – BalusC

+0

위의 스 니펫을 추가했습니다. SessionPhaseListener에서 빈을 얻으십시오 – AnNik

답변

7

세션은 CDI는 빈이 JSF는 빈을 관리 범위 일반 세션으로 HTTP 세션에서 동일한 방식으로 저장되지 않은 관리 범위 : 여기에 지금까지 내 시도이다. 세션 범위가 지정된 JSF 관리는 사실 세션의 빈 이름을 키로 저장합니다. 세션 스코프 된 CDI 관리 빈은 세션 범위에서 다른 맵을 통해 더 멀리 추상화됩니다.

EL을 세션 맵에서 가져 오는 대신 프로그래밍 방식으로 평가해야합니다. EL 해결 프로그램 시도가 실수 한 번 있습니다. 값에 #{} 표현이 없습니다. 이에 따라

ELContext elContext = FacesContext.getCurrentInstance().getELContext(); 
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication() 
    .getELResolver().getValue(elContext, null, "user"); 

수정을 : 당신이 방법으로 이미도 FacesContext context을했다고

UserManager userManager = context.getApplication() 
    .evaluateExpressionGet(context, "#{user}", UserManager.class); 

참고 : 그런데

ELContext elContext = FacesContext.getCurrentInstance().getELContext(); 
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication() 
    .getELResolver().getValue(elContext, null, "#{user}"); 

은, 위의 속기는 Application#evaluateExpressionGet()입니다 논의.

+0

Wonderful! 나는이 예제만으로 모든 종류의 물건을 헛되이 시도하고 있었다. [http://anonsvn.icesoft.org/repo/icefaces/trunk/icefaces/samples/address-demo/src/com/icesoft/applications/faces /address/PhaseSync.java). 이제 나는 자러 갈 수있어! BalusC에게 다시 한 번 감사드립니다. – Ravi

0

JSF의 다음 버전에서이 문제가 실제로 해결 될 수 있기를 바랍니다. 해야 할 일 (그리고 이식성 유지)은 JNDI를 통해 BeanManager를 검색 한 다음, BeanManager에서 명명 된 Bean을 가져 오는 것입니다.

0

또 다른 가능성은 Seam Faces입니다. 휴대용 CDI 확장이며 faces events을 관찰 할 수 있습니다.

2

다음 코드를 사용하여 PhaseListener 내부에서 CDI beans에 대한 참조를 얻습니다.

public BeanManager getBeanManager() { 
    BeanManager beanManager = null; 
    try { 
     InitialContext initialContext = new InitialContext(); 
     beanManager = (BeanManager) initialContext.lookup("java:comp/BeanManager"); 
    } catch (NamingException e) { 
     logger.log(Level.SEVERE, "Couldn't get BeanManager through JNDI", e); 
    } 
    return beanManager; 
} 

public <T> T getBean(final Class<T> clazz) { 
    BeanManager bm = getBeanManager(); 
    Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next(); 
    CreationalContext<T> ctx = bm.createCreationalContext(bean); 
    return (T) bm.getReference(bean, clazz, ctx); 
} 

그래서 콩을 얻으려면 다음과 같이 호출하면됩니다.

DataManager dataManager = getBean(DataManager.class); 

이 경우의 빈은 PhaseListener에서 사용되고있는 빈 @Dependent이다.