6 Replies Latest reply on Aug 5, 2009 11:51 AM by Michael Thumes

    Concurrency issues using SEAM-Wicket for facebook app

    Michael Thumes Newbie

      We build a quite successfull facebook prototype based on the example
      from the wicket wiki (http://cwiki.apache.org/WICKET/facebook-integration.html)
      and factored out the fetching of facebook session parameters to a separate
      SEAM component witch uses a SEAM @Observer(org.jboss.seam.wicket.beforeRequest).


      Essentially, we just grab the Facebook Credentials (session key and/or authtoken)
      and store it in EVENT Scope inside a custom FacebookRequestContext Bean (a POJO, not a SEAM Bean) which we use to instantiate a com.google.code.facebookapi.IFacebookRestClient later on.



      @Name("facebookRequestContextManager")
      @Scope(ScopeType.EVENT)
      @AutoCreate
      public class FacebookRequestContextManager {
              
              /** this member holds the facebook session id for this request */
              @Out(scope=ScopeType.EVENT)
              private FacebookRequestContext facebookRequestContext;
              
              @Observer("org.jboss.seam.wicket.beforeRequest")
              public void onBeforeWebRequest(){
      
                      // did facebook send us the sessionId?
                      String fbSessionParamName = FacebookParam.SESSION_KEY.toString();
                      String fbAuthTokenParamName = "auth_token";
                      
                      HttpServletRequest wicketHttpServletRequest = ((ServletWebRequest)WebRequestCycle.get().getRequest()).getHttpServletRequest();
      
                      String fbAuthToken = wicketHttpServletRequest.getParameter(fbAuthTokenParamName);
                      String fbSessionId = wicketHttpServletRequest.getParameter(fbSessionParamName);
                      
                      Session.get().setLocale(Locale.US);
                              
                      if( StringUtils.isEmpty(fbSessionId) ){
                              // we have no facebook session, so we need one!
                              if( !StringUtils.isEmpty(fbAuthToken)){
                                      // let the facebook service convert this authtoken into a valid session id:
                                      FacebookFacade facebookFacade = (FacebookFacade) Component.getInstance("FacebookFacade");
                                      try {
                                              fbSessionId = facebookFacade.authenticateSession( fbAuthToken );
                                      } catch (RuntimeException _e) {
                                              //ignore this: we'll throw the exception down there.... 
                                      }
                              }
                      }
                      if( fbSessionId==null ){
                              // send user to facebook login to initiate a new fb session
                              throw new FacebookAuthenticationException("auth failed");
                      }
                      facebookRequestContext = new FacebookRequestContext( fbSessionId );
              }
              
      }



      Things worked fine until we started serving several thousand customers
      per day. Under pressure, unfriendly things started to happen: Instead
      of giving each request Scope a separate FacebookRequestContext object, all our users
      got the same single instance (holding the very same session key) assigned. A rather
      puzzling customer experience ...


      Assuming a concurrency issue: Any clues what might be not thread safe with this construct?