Re: getThreadObjectContext with domain parameter - code -

From: Arnaud Garcia (arnau..magemed-87.com)
Date: Mon Sep 14 2009 - 11:34:34 EDT

  • Next message: Borut Bolčina: "Re: Using Cayenne Servlet Filter can bring the web application down"

    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 <razumovsky.andre..mail.com>:
    > 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:35:54 EDT