getThreadObjectContext with domain parameter - code -

From: Arnaud Garcia (arnau..magemed-87.com)
Date: Fri Sep 11 2009 - 07:19:27 EDT

  • Next message: Michael Gentry: "Re: Using Join Table"

    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() + ")");
            }
        }
    }



    This archive was generated by hypermail 2.0.0 : Fri Sep 11 2009 - 07:20:09 EDT