cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Arnaud Garcia <arn...@imagemed-87.com>
Subject Re: getThreadObjectContext with domain parameter - code -
Date Mon, 14 Sep 2009 15:03:32 GMT
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.andrey@gmail.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 <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
View raw message