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.

      public class FacebookRequestContextManager {
              /** this member holds the facebook session id for this request */
              private FacebookRequestContext facebookRequestContext;
              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);
                      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?