;-) many thanks it works well now. Arnaud
2009/9/14 Andrey Razumovsky <[email protected]>: > Now you're creating new HashMap every request, and, as in your first > example, old bindings get erased. Bind method should be rewritten as > > public static void bindThreadObjectContext(ObjectContext context, > String domain) { > Map<String, ObjectContext> objectContextMap = > threadObjectContext.get(); > if (objectContextMap == null) { > objectContextMap = Collections.synchronizedMap(new > HashMap<String, ObjectContext>()); > threadObjectContext.set( objectContextMap); > > } > objectContextMap.put(domain, context); > > Or maybe there is something I don't understand :) > > 2009/9/14 Arnaud Garcia <[email protected]> > >> Well, I think there is something I don't understand, I change again >> and, no change.. >> now I build a new hash, that I put on the ThreadLocal >> >> I am sorry but I don't understand why... >> Arnaud >> >> code below >> >> >> public class ImagemedBaseContext { >> >> protected static final ThreadLocal<Map<String, ObjectContext>> >> threadObjectContext = new ThreadLocal<Map<String, ObjectContext>>(); >> >> public static ObjectContext getThreadObjectContext(String domain) >> throws IllegalStateException { >> ....... >> public static void bindThreadObjectContext(ObjectContext context, >> String domain) { >> Map<String, ObjectContext> objectContextMap = >> Collections.synchronizedMap(new HashMap<String, ObjectContext>()); >> objectContextMap.put(domain, context); >> threadObjectContext.set(objectContextMap); >> >> >> -------------------------------------------------------------------------------------- >> 2009/9/14 Andrey Razumovsky <[email protected]>: >> > Now objectContextMap is static, so only one context is allowed per domain >> > name (for entire app). Map should be created on the fly if needed, in >> bind() >> > >> > 2009/9/14 Arnaud Garcia <[email protected]> >> > >> >> OK, so I just change by adding new ObjectContext to a Map and set/get >> >> this Map from the ThreadLocal which is only as the map created one >> >> time... >> >> But, I still have the same error sometimes.... >> >> >> >> below the new code if you can have a quick look... >> >> >> >> many thanks, for help ! >> >> >> >> arnaud >> >> >> >> >> --------------------------------------------------------------------------------------- >> >> public class ImagemedBaseContext { >> >> >> >> private static Map<String, ObjectContext> objectContextMap = >> >> Collections.synchronizedMap(new HashMap<String, ObjectContext>()); >> >> private static final Logger log = >> >> Logger.getLogger(ImagemedBaseContext.class.getName()); >> >> protected static final ThreadLocal<Map<String, ObjectContext>> >> >> threadObjectContext = new ThreadLocal<Map<String, ObjectContext>>(); >> >> >> >> public static ObjectContext getThreadObjectContext(String domain) >> >> throws IllegalStateException { >> >> ObjectContext context = threadObjectContext.get().get(domain); >> >> if (context == null) { >> >> throw new IllegalStateException("Current thread has no >> >> bound ObjectContext."); >> >> } else { >> >> log.fine("[GET OBJECT CONTEXT] ObjectContext (" + >> >> context.hashCode() + ") for domain=" + domain + " to ThreadLocal (" + >> >> threadObjectContext.hashCode() + ")"); >> >> } >> >> return context; >> >> >> >> } >> >> >> >> public static void bindThreadObjectContext(ObjectContext context, >> >> String domain) { >> >> objectContextMap.put(domain, context); >> >> threadObjectContext.set(objectContextMap); >> >> if (context == null) { >> >> log.fine("[UNBIND OBJECT CONTEXT]"); >> >> } else { >> >> log.fine("[BIND OBJECT CONTEXT] ObjectContext (" + >> >> context.hashCode() + ") for domain=" + domain + " to ThreadLocal (" + >> >> threadObjectContext.hashCode() + ")"); >> >> } >> >> } >> >> } >> >> >> >> >> --------------------------------------------------------------------------------------- >> >> >> >> >> --------------------------------------------------------------------------------------- >> >> >> >> 2009/9/11 Andrey Razumovsky <[email protected]>: >> >> > Well, looking at your code, I think you should not create new >> ThreadLocal >> >> > each time request is received (in bindThreadObjectContext). You old >> >> bindings >> >> > just get erased >> >> > >> >> > 2009/9/11 Arnaud Garcia <[email protected]> >> >> > >> >> >> Hello, >> >> >> >> >> >> I created a filter to use multi domains in a webapp, but I still have >> >> >> a problem...., I don't find the bug... if someone can help me to fix >> >> >> it ! >> >> >> (I think that some people will also need this kind of filter, so this >> >> >> is why I post the complete code) >> >> >> >> >> >> So, the last bug is that sometimes the ObjectContext cannot be >> >> >> retrieved..... >> >> >> java.lang.IllegalStateException: Current thread has no bound >> >> ObjectContext. >> >> >> at >> >> >> >> >> >> com.imagemed.cayenne.ImagemedBaseContext.getThreadObjectContext(ImagemedBaseContext.java:39) >> >> >> >> >> >> thanks >> >> >> >> >> >> Arnaud >> >> >> >> >> >> >> >> >> To use the filter: >> >> >> ---------------------- >> >> >> >> >> >> =>Declare the filter in web.xml as usual : >> >> >> >> >> >> <filter> >> >> >> <filter-name>Imagemed.Cayenne</filter-name> >> >> >> >> >> >> >> >> >> <filter-class>com.imagemed.cayenne.WebApplicationMultiDomainsContextFilter</filter-class> >> >> >> </filter> >> >> >> >> >> >> <filter-mapping> >> >> >> <filter-name>Imagemed.Cayenne</filter-name> >> >> >> <url-pattern>/*</url-pattern> >> >> >> </filter-mapping> >> >> >> >> >> >> Then in your DAO you retrieve your contexts from your session like >> this: >> >> >> >> >> >> ctxtForDomain1 = (DataContext) >> >> >> ImagemedBaseContext.getThreadObjectContext("DOMAIN1"); >> >> >> ctxtForDomain2 = (DataContext) >> >> >> ImagemedBaseContext.getThreadObjectContext("DOMAIN2"); >> >> >> .... >> >> >> >> >> >> Below you will find the complete code..... >> >> >> >> >> >> >> >> >> ------------------------------ THE FILTER ------------------------- >> >> >> package com.imagemed.cayenne; >> >> >> >> >> >> import java.io.IOException; >> >> >> import java.util.ArrayList; >> >> >> import java.util.Collection; >> >> >> import java.util.logging.Logger; >> >> >> import javax.servlet.Filter; >> >> >> import javax.servlet.FilterChain; >> >> >> import javax.servlet.FilterConfig; >> >> >> import javax.servlet.ServletException; >> >> >> import javax.servlet.ServletRequest; >> >> >> import javax.servlet.ServletResponse; >> >> >> import javax.servlet.http.HttpServletRequest; >> >> >> import javax.servlet.http.HttpSession; >> >> >> import org.apache.cayenne.access.DataContext; >> >> >> import org.apache.cayenne.access.DataDomain; >> >> >> import org.apache.cayenne.conf.Configuration; >> >> >> import org.apache.cayenne.conf.ServletUtil; >> >> >> >> >> >> >> >> >> public class WebApplicationMultiDomainsContextFilter implements >> Filter { >> >> >> >> >> >> public static final String DATA_CONTEXT_KEY = >> "cayenne.datacontext"; >> >> >> private ArrayList<String> domains = new ArrayList<String>(); >> >> >> private static final Logger log = >> >> >> >> >> >> Logger.getLogger(WebApplicationMultiDomainsContextFilter.class.getName()); >> >> >> >> >> >> public static DataContext getSessionContext(HttpSession session, >> >> >> String domain) { >> >> >> synchronized (session) { >> >> >> String dataCtxKey = DATA_CONTEXT_KEY + "." + domain; >> >> >> DataContext ctxt = (DataContext) >> >> >> session.getAttribute(dataCtxKey); >> >> >> >> >> >> if (ctxt == null) { >> >> >> ctxt = DataContext.createDataContext(domain); >> >> >> session.setAttribute(dataCtxKey, ctxt); >> >> >> } else { >> >> >> log.fine("[RETRIEVE] DataContext (" + ctxt.hashCode() >> >> >> + ") retrieved from session key=" + dataCtxKey); >> >> >> } >> >> >> >> >> >> return ctxt; >> >> >> } >> >> >> } >> >> >> >> >> >> public void destroy() { >> >> >> } >> >> >> >> >> >> public void doFilter(ServletRequest request, ServletResponse >> >> >> response, FilterChain chain) throws IOException, ServletException { >> >> >> boolean reset = false; >> >> >> >> >> >> if (request instanceof HttpServletRequest) { >> >> >> reset = true; >> >> >> >> >> >> HttpSession session = ((HttpServletRequest) >> >> >> request).getSession(true); >> >> >> for (String domain : domains) { >> >> >> DataContext context = getSessionContext(session, >> domain); >> >> >> ImagemedBaseContext.bindThreadObjectContext(context, >> >> >> domain); >> >> >> } >> >> >> } >> >> >> >> >> >> try { >> >> >> chain.doFilter(request, response); >> >> >> } finally { >> >> >> if (reset) { >> >> >> for (String domain : domains) { >> >> >> ImagemedBaseContext.bindThreadObjectContext(null, >> >> >> domain); >> >> >> } >> >> >> } >> >> >> } >> >> >> } >> >> >> >> >> >> public void init(FilterConfig filterConfig) throws >> ServletException { >> >> >> >> >> >> >> >> >> ServletUtil.initializeSharedConfiguration(filterConfig.getServletContext()); >> >> >> Collection<DataDomain> collDomains = >> >> >> Configuration.getSharedConfiguration().getDomains(); >> >> >> for (DataDomain dataDomain : collDomains) { >> >> >> domains.add(dataDomain.getName()); >> >> >> log.info("[FOUND DOMAIN] name=" + dataDomain.getName()); >> >> >> } >> >> >> } >> >> >> } >> >> >> >> >> >> ------------------------------ ImagemedBaseContext >> >> ------------------------ >> >> >> package com.imagemed.cayenne; >> >> >> >> >> >> import java.util.Collections; >> >> >> import java.util.HashMap; >> >> >> import java.util.Map; >> >> >> import java.util.logging.Logger; >> >> >> import org.apache.cayenne.ObjectContext; >> >> >> >> >> >> public class ImagemedBaseContext { >> >> >> >> >> >> private static Map<String, ThreadLocal> threadLocalMap = >> >> >> Collections.synchronizedMap(new HashMap<String, ThreadLocal>()); >> >> >> private static final Logger log = >> >> >> Logger.getLogger(ImagemedBaseContext.class.getName()); >> >> >> >> >> >> public static ObjectContext getThreadObjectContext(String domain) >> >> >> throws IllegalStateException { >> >> >> ThreadLocal<ObjectContext> threadObjectContext = >> >> >> threadLocalMap.get(domain); >> >> >> ObjectContext context = threadObjectContext.get(); >> >> >> >> >> >> if (context == null) { >> >> >> throw new IllegalStateException("Current thread has no >> >> >> bound ObjectContext."); <============================ ligne 39 >> >> >> } else { >> >> >> log.fine("[GET OBJECT CONTEXT] ObjectContext (" + >> >> >> context.hashCode() + ") for domain=" + domain + " to ThreadLocal (" + >> >> >> threadObjectContext.hashCode() + ")"); >> >> >> } >> >> >> return context; >> >> >> >> >> >> } >> >> >> >> >> >> public static void bindThreadObjectContext(ObjectContext context, >> >> >> String domain) { >> >> >> ThreadLocal<ObjectContext> threadObjectContext = new >> >> >> ThreadLocal<ObjectContext>(); >> >> >> threadObjectContext.set(context); >> >> >> threadLocalMap.put(domain, threadObjectContext); >> >> >> if (context == null) { >> >> >> log.fine("[UNBIND OBJECT CONTEXT]"); >> >> >> } else { >> >> >> log.fine("[BIND OBJECT CONTEXT] ObjectContext (" + >> >> >> context.hashCode() + ") for domain=" + domain + " to ThreadLocal (" + >> >> >> threadObjectContext.hashCode() + ")"); >> >> >> } >> >> >> } >> >> >> } >> >> >> >> >> > >> >> > >> >> > >> >> > -- >> >> > Andrey >> >> > >> >> >> > >> > >> > >> > -- >> > Andrey >> > >> > > > > -- > Andrey >
