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