This discussion is archived
3 Replies Latest reply: Feb 3, 2012 10:52 AM by Brian Oliver RSS

Bug with class-scheme and cache-ref macro

Jonathan.Knight Expert
Currently Being Moderated
I was trying to build and run our project using Coherence 3.7.1.0 and 2.1.1 of Incubator Commons.

In our project we have a cache mapping and class scheme that allow us to create a CQC and use it just like a normal cache, i.e. we can call Cachefactory.getCache(“ReplicatedRefSourceBook”) and we get back a CQC wrapping a cache called LatestRefSourceBook. It works like this

Cache config file:
<?xml version="1.0"?>
<cache-config xmlns:element="class://com.oracle.coherence.environment.extensible.namespaces.XmlElementProcessingNamespaceContentHandler"
    element:introduce-cache-config="config/cluster.xml">

    <caching-scheme-mapping>

        <!-- Replicated Caches for Reference data -->
        <cache-mapping>
            <cache-name>ReplicatedRef*</cache-name>
            <scheme-name>odc-replicated-dimension</scheme-name>
            <init-params>
               <init-param>
                   <param-name>underlying-cache</param-name>
                   <param-value>LatestRef*</param-value>
               </init-param>
            </init-params>
        </cache-mapping>

    </caching-scheme-mapping>

    <caching-schemes>
        <class-scheme>
            <scheme-name>odc-replicated-dimension</scheme-name>
            <class-name>com.xxx.xxx.core.cache.ConnectedCache</class-name>
            <init-params>
                <init-param>
                    <param-name>cacheName</param-name>
                    <param-type>java.lang.String</param-type>
                    <param-value>{cache-name}</param-value>
                </init-param>
                <init-param>
                    <param-name>underlyingCache</param-name>
                    <param-type>{cache-ref}</param-type>
                    <param-value>{underlying-cache}</param-value>
                </init-param>
            </init-params>
        </class-scheme>
    </caching-schemes>

</cache-config>
Our ConnectedCache class extends WrapperNamedCache and has a constructor that takes a String and a NamedCache. The NamedCache is supplied by the {cache-ref} macro as Coherence strips the ReplicatedRef part and replaces it with LatestRef so if I ask for ReplicatedRefSourceBook the underlying-cache is LatestRefSourceBook.

The problem is that in INC-10 2.1.1 this breaks (although it might be broken in other versions after 1.7.3) as the Incubator takes over creating class-scheme and messes up the underlying-cache parameter. The problem seems to be in the ExtensibleEnvironment.instantiateAny method. The parameters I want are inside the info (CacheInfo) parameter but these do not get added to the parameterProvider. If I change the method so it looks like the one below then it appears to work. Basically it requires parameters from the CacheInfo parameter to be copied into the parameterProvider. (My change is between the two /* Fix added by JK */ comments).
public Object instantiateAny(CacheInfo info,
                             XmlElement xmlClass,
                             BackingMapManagerContext context,
                             ClassLoader loader)
{
    //use a registered Scheme to produce the instance (if required)
    if (xmlClass.getName().equals("class-scheme") && xmlClass.getAttributeMap().containsKey("use-scheme"))
    {
        //determine the schemeId for the Scheme to use
        String schemeId = xmlClass.getAttribute("use-scheme").getString();
        try
        {
            //locate the builder
            ParameterizedBuilder<?> builder = (ParameterizedBuilder<?>) getResource(BuilderRegistry.class)
                .getBuilder(schemeId);

            //locate the cache mapping
            CacheMapping cacheMapping = getResource(CacheMappingRegistry.class).findCacheMapping(
                info.getCacheName());

            //determine the parameter provider for the cache mapping
            MutableParameterProvider parameterProvider = new ScopedParameterProvider(cacheMapping == null
                    ? SystemPropertyParameterProvider.INSTANCE : cacheMapping.getParameterProvider());

            /* ---------- Fix added by JK ----------------------------------- */
            // Copy any attributes from the CacheInfo into the parameterProvider
            for(Map.Entry attributeEntry : (Set<Map.Entry>)info.getAttributes().entrySet()) {
                parameterProvider.addParameter(new Parameter(attributeEntry.getKey().toString(), attributeEntry.getValue()));
            }
            /* ---------- Fix added by JK ----------------------------------- */

            //add the standard coherence parameters to the parameter provider
            parameterProvider.addParameter(new Parameter("cache-name", info.getCacheName()));
            parameterProvider.addParameter(new Parameter("class-loader", loader));
            parameterProvider.addParameter(new Parameter("manager-context", context));

            //set the class loader if we have one
            if (builder instanceof ClassLoaderAware)
            {
                ((ClassLoaderAware) builder).setContextClassLoader(loader);
            }

            return builder.realize(parameterProvider);
        }
        catch (ClassCastException classCastException)
        {
            throw new RuntimeException(String.format(
                "Cound not instantiate %s as the namespace did not return a ClassScheme.", xmlClass),
                classCastException);
        }
    }
    else
    {
        return super.instantiateAny(info, xmlClass, context, loader);
    }
}
Cheers,
JK

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points