cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrey Razumovsky <razumovsky.and...@gmail.com>
Subject Re: getThreadObjectContext with domain parameter - code -
Date Fri, 11 Sep 2009 15:13:45 GMT
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 <arnaud@imagemed-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

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message