Concurrency issues using SEAM-Wicket for facebook app
mole Jul 29, 2009 1:43 PMWe 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?