8

This is a Tridion 2009-SP1 Java environment with an Oracle Broker. Both the deployer and the website are running on the same server. We have the CD_2009.1.71453 roll up hotfix installed as well

We use some Keywords with metadata to store and retrieve information dynamically.

When we turn the CacheChannelService on with all the proper cacheBindings for the different dynamic content types it works for all but the Taxonomies.

What we can see happening is that when the cache is empty (after a restart or manual clearing) that the keywords are properly added to the cache after a publish of the containing category. However, when we update a keyword or add a new one and republish the category this does not get picked up in the website. It even causes an error when it can't find the new keyword in the cache.

It seems that somehow the mechanism where;

  1. It checks the cache
  2. Not in the cache (or updated version)
  3. Retrieve item from the Broker

Does not work properly.

Either we are missing something really obvious or it is a bug. I have looked through all the other posts about caching, but haven't found the solution yet. Tridion support has been contacted, but so far they haven't given the golden tip either.

Simple version of Broker conf.

cd_broker_conf (same on uploader and website):

<Bindings>
  <Binding Name="LinkInfo" Class="com.tridion.broker.linking.SQLLinkInfoHome" />
  <Binding Name="ComponentMeta" 
           Class="com.tridion.broker.components.meta.OracleComponentMetaHome" />
  <Binding Name="Taxonomy" Class="com.tridion.broker.taxonomies.SQLTaxonomyHome" />
</Bindings>
<ObjectCache Enabled="true">
  <Policy Type="LRU" Class="com.tridion.cache.LRUPolicy">
    <Param Name="MemSize" Value="128mb" />
   </Policy>
  <Features>
    <Feature Type="DependencyTracker" Class="com.tridion.cache.DependencyTracker" />
  </Features>
  <CacheBindings>
    <CacheBinding Name="LinkInfo" Class="com.tridion.broker.linking.CachedLinkInfoHome" />
    <CacheBinding Name="ComponentMeta"
                  Class="com.tridion.broker.components.meta.CachedComponentMetaHome" />
    <CacheBinding Name="Taxonomy" Class="com.tridion.broker.taxonomies.CachedTaxonomyHome" />
  </CacheBindings>
  <RemoteSynchronization Host="127.0.0.1" Port="1099" Queuesize="10000"
                         ServiceMonitorInterval="10000" />
</ObjectCache>

Added the part of the cd_broker.log where you can see it looking for a new keyword in the cache:

[Debug 27-03-2013 09:35:41] Retrieving Keyword with KeywordURI: tcm:11-12436-1024
[Debug 27-03-2013 09:35:41] Retrieving Keyword List from cache
[Debug 27-03-2013 09:35:41] Retrieving Keyword with KeywordURI: tcm:11-12436-1024
[Debug 27-03-2013 09:35:41] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12799-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12801-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12801-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12800-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12444-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Retrieving Keyword with KeywordURI: tcm:11-12451-1024
[Debug 27-03-2013 09:36:50] Retrieving Keyword List from cache
[Debug 27-03-2013 09:36:50] Cache miss, Keyword list not in cache, retrieving and storing in cache
[Debug 27-03-2013 09:36:50] Retrieving a keyword: SELECT TF.FACET_ID, TF.PUBLICATION_ID, TF.TAXONOMY_ID, TF.FACET_NAME, TF.FACET_PARENT, TF.FACET_ISABSTRACT, TF.FACET_ISNAVIGABLE, TF.FACET_HASCHILDREN,  TF.FACET_KEY, TF.FACET_LEFT, TF.FACET_RIGHT, TF.FACET_DEPTH, TF.FACET_DESCRIPTION, TF.FACET_ITEMTYPE,(  SELECT COUNT(DISTINCT ITC.ITEM_REFERENCE_ID) AS CNT FROM ITEM_CATEGORIES_AND_KEYWORDS ITC WHERE ITC.KEYWORD_ID=TF.FACET_ID ) AS RELATED_ITEMS  FROM TAXFACETS TF LEFT JOIN ITEM_CATEGORIES_AND_KEYWORDS ITC ON ITC.KEYWORD_ID=TF.FACET_ID WHERE TF.PUBLICATION_ID = ? AND TF.FACET_ID = ? AND TF.FACET_ITEMTYPE = ? GROUP BY TF.FACET_ID, TF.PUBLICATION_ID, TF.TAXONOMY_ID, TF.FACET_NAME, TF.FACET_PARENT, TF.FACET_ISABSTRACT, TF.FACET_ISNAVIGABLE, TF.FACET_HASCHILDREN, TF.FACET_KEY, TF.FACET_LEFT, TF.FACET_RIGHT, TF.FACET_DEPTH, TF.FACET_DESCRIPTION, TF.FACET_ITEMTYPE
[Debug 27-03-2013 09:36:50] No keywords found for the given Keyword URI: tcm:11-12451-1024
  • Do you have some debug logging to see what happens when an item is invalidated and when a page tries to get that item from cache? I've done some pretty heavy websites with Taxonomy caching turned on. Additionally, what is the hotfix level of your environment? I remember that I needed a couple. – Raimond Mar 26 '13 at 16:20
  • Hi there. Can you check if you have CD_2009.1.71453 on your system? Seems there were some improvements done to taxonomies in 69135 and this hotfix includes that one. Besides that, can you check exactly what API are you using for retrieving Taxonomies? You should know that not all methods go through cache. – Daniel Neagu Mar 27 '13 at 8:48
  • I updated the question, but we do have the CD_2009.1.71453 hotfix installed. We use the com.tridion.taxonomies.Keyword API. And for instance use: TaxonomyFactory.getTaxonomyKeyword(tcm:11-12451-1024) to get a specific keyword to display it's contents. – Hendrik Beenker Mar 27 '13 at 9:00
  • We discovered that the problem only occurs when specifically asking directly for a keyword (-1024) with getTaxonomyKeyword, when we ask for the whole category (-512) it does work properly. – Hendrik Beenker Mar 27 '13 at 9:53
10

Looking closely at your problem, it seems that the findTaxonomyKeyword method from the CachedTaxonomyHome class caches your result but when the whole taxonomy is reDeployed, the cache invalidation does not happen. To fix this you have two options:

  1. You contact Tridion Customer Support, explain the problem, explain why this would be a ShowStopper for your project and they might consult with R&D to see if a hotfix would be required;

  2. You implement/configure your own version of CachedTaxonomyHome in which you add a dependency to make sure the cache is invalidated when needed. Below you will find an implementation example for this:

public class FlushingCachedTaxonomyHome extends CachedTaxonomyHome {
    private Logger log = Broker.getInstance().getLogger();
    private TaxonomyHome taxonomyHome;
    private Cache taxonomyCache = CacheFactory.getInstance().getCache(DistributorCacheConstants.REGION_TAXONOMY);

    public FlushingCachedTaxonomyHome(Object brokerHome) {
        super(brokerHome);
        this.taxonomyHome = (TaxonomyHome) brokerHome;
    }

    public List findTaxonomyKeyword(int publicationId, int keywordId, int keywordItemType) throws StorageException {
        log.debug("Retrieving Keyword List from cache");
        Serializable key = KeyGenerator.createKey(publicationId, keywordId, keywordItemType);
        List foundKeywords = (List) this.taxonomyCache.get(key);
        if (foundKeywords == null) {
            log.debug("Cache miss, Keyword list not in cache, retrieving and storing in cache");
            foundKeywords = this.taxonomyHome.findTaxonomyKeyword(publicationId, keywordId, keywordItemType);
            this.taxonomyCache.put(key, foundKeywords);
            if (foundKeywords != null && !foundKeywords.isEmpty()) {
                final String taxonomyURI = ((Keyword) foundKeywords.get(0)).getTaxonomyURI();
                try {
                    final TCMURI taxonomy =  new TCMURI(taxonomyURI);
                    final int taxonomyId = taxonomy.getItemId();
                    // add a dependency for our added taxonomy keywords to the actual taxonomy to which they belong
                    this.taxonomyCache.addDependency(key,
                              DistributorCacheConstants.REGION_TAXONOMY, KeyGenerator.createKey(publicationId, taxonomyId));
                } catch (ParseException pe) {
                    //TODO: handle this
                }
            }
        }
        return foundKeywords;
    }
}

Keep in mind that this is only an example but it should get the job done. Also, do not forget to add it to the CacheBinding.

  • Thanks Daniel for thinking with us. This solution could be helpful when a keyword is not in the cache, but it still doesn't solve the issue that when a keyword is updated en republished that it should be removed from the cache. This is how it works for other dynamic content items. I think we are going to need a hotfix. The only other option would be turn of the caching for taxonomy entirely, but I am not sure the system administrators like that option. – Hendrik Beenker Mar 28 '13 at 10:42
  • 1
    Hi @Hendrik: this WILL help and solve your problem. The trick is this: if you look closely, we add the object to the cache and we also add a dependency to another object. The dependency is to the Category object. Conclusion: whenever the Category object is changed in any way, the result will be evicted from cache. This will work for you for sure. – Daniel Neagu Mar 28 '13 at 13:20
  • Hi @DanielNeagu, thank you for the answer. This did indeed solve our issue. We had some configuration issue with a missing/incorrect remotesynchronization setting. But, creating a custom CachedTaxonomyHome with this code made it work. We implemented it for both the Deployer as well as the Website, just to be sure, but I think we only need it for the website, right? – Hendrik Beenker Apr 24 '13 at 8:16
  • 1
    Nope...you need it for both but mainly for the deployer. Why the deployer? Because the one that is actually sending the invalidation messages is the Deployer? Why also the website? Just as a precaution, a best practice (keep them both in sync) and because you never know what goes behind the scenes in case of Caching messages. – Daniel Neagu Apr 24 '13 at 8:25
  • 1
    This code is part of Tridion 2011. There will be no need for building something special for Taxonomies in anything post Tridion 2011. – Daniel Neagu Apr 24 '13 at 10:02
3

I'd like to comment a statement in the thread of the answer above:

"... but mainly for the deployer. Why the deployer? Because the one that is actually sending the invalidation messages is the Deployer? "

Looking in the log files this statement does not seem to be true... It must be implemented in the web app. But better, as suggested in both: uploader/web app.

And one more suggestion/question: Shouldn't:

this.taxonomyCache.put(key, foundKeywords);
//be after the check for null:
if (foundKeywords != null && !foundKeywords.isEmpty()) {
?

It could become a showstopper if you publish (and visit) an item that reads a Keyword that's not published yet...

  • +1 for the putting the use of foundKeywords after the null check. As for what the log files are telling us... how can we be sure both web app and deployer don't share a broker conf, so they are logging to the same file? – Dominic Cronin Jun 14 '13 at 19:25
  • Only the deployer can notify webapps of updates, so if you had to choose one, choose the deployer – Nuno Linhares Jun 16 '13 at 20:29
  • The code establishes relationship between Kwds & Cats/Taxnms: this.taxonomyCache.addDependency(key, DistributorCacheConstants.REGION_TAXONOMY, KeyGenerator.createKey(publicationId, taxonomyId)); After publishing a Cat with Kwds I get (in CCS log): [Debug ...] Received a broadcast event [CacheEvent eventType=Invalidate regionPath=/com.tridion.broker.Taxonomies.Taxonomy key=46:39978] from listener xxx:-yyy ... So the uploader/CCS has no idea about the individual Keywords and without relationship on the App side no Kwds would be invalidated. – Venko Ivanov Jun 17 '13 at 8:30
  • The implementation in Tridion 2011SP1/2013 regarding the check: (foundKeywords != null && !foundKeywords.isEmpty()) before adding foundKeywords to cache seems to be correct. – Venko Ivanov Jul 16 '13 at 10:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.