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 <arnau..magemed-87.com>
> 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 <razumovsky.andre..mail.com>:
> > 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 <arnau..magemed-87.com>
> >
> >> 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
This archive was generated by hypermail 2.0.0 : Mon Sep 14 2009 - 11:15:31 EDT