@AfterReturning(pointcut = "updateSingles()", returning = "retVal") public Object cacheUpdateSingles(final JoinPoint jp, final Object retVal) throws Throwable { try { doUpdate(jp, retVal); } catch (Throwable ex) { if (LOG.isDebugEnabled()) { LOG.warn("Caching on " + jp.toShortString() + " aborted due to an error.", ex); } else { LOG.warn( "Caching on " + jp.toShortString() + " aborted due to an error: " + ex.getMessage()); } } return retVal; }
private void doUpdate(final JoinPoint jp, final Object retVal) throws Throwable { if (isCacheDisabled()) { LOG.debug("Caching is disabled."); return; } final MemcachedClientIF cache = getMemcachedClient(); final Method methodToCache = getMethodToCache(jp); List<UpdateSingleCache> lAnnotations; if (methodToCache.getAnnotation(UpdateSingleCache.class) != null) { lAnnotations = Arrays.asList(methodToCache.getAnnotation(UpdateSingleCache.class)); } else { lAnnotations = Arrays.asList(methodToCache.getAnnotation(UpdateSingleCaches.class).value()); } for (int i = 0; i < lAnnotations.size(); i++) { // This is injected caching. If anything goes wrong in the caching, LOG the crap outta it, // but do not let it surface up past the AOP injection itself. try { final AnnotationInfo info = getAnnotationInfo(lAnnotations.get(i), methodToCache.getName(), getJitterDefault()); final String baseKey = CacheBase.getBaseKey( info.getAsString(AType.KEY_TEMPLATE), info.getAsInteger(AType.KEY_INDEX, null), retVal, jp.getArgs(), methodToCache.toString(), factory, methodStore); final String cacheKey = buildCacheKey( baseKey, info.getAsString(AType.NAMESPACE), info.getAsString(AType.KEY_PREFIX)); Object dataObject = getIndexObject( info.getAsInteger(AType.DATA_INDEX, null), retVal, jp.getArgs(), methodToCache.toString()); dataObject = UpdateSingleCacheAdvice.getMergedData( dataObject, info.getAsString(AType.DATA_TEMPLATE, null), retVal, jp.getArgs(), factory); final Class dataTemplateType = (Class) info.getAsType(AType.DATA_TEMPLATE_TYPE, String.class); final Object submission = (dataObject == null) ? new PertinentNegativeNull() : applyDataTemplateType(dataObject, dataTemplateType); boolean cacheable = true; if (submission instanceof CacheConditionally) { cacheable = ((CacheConditionally) submission).isCacheable(); } if (cacheable) { cache.set( cacheKey, calculateJitteredExpiration( info.getAsInteger(AType.EXPIRATION), info.getAsInteger(AType.JITTER)), submission); } // Notify the observers that a cache interaction happened. final List<UpdateSingleCacheListener> listeners = getPertinentListeners( UpdateSingleCacheListener.class, info.getAsString(AType.NAMESPACE)); if (listeners != null && !listeners.isEmpty()) { for (final UpdateSingleCacheListener listener : listeners) { try { listener.triggeredUpdateSingleCache( info.getAsString(AType.NAMESPACE), info.getAsString(AType.KEY_PREFIX, null), baseKey, dataObject, retVal, jp.getArgs()); } catch (Exception ex) { LOG.warn("Problem when triggering a listener.", ex); } } } } catch (Exception ex) { if (LOG.isDebugEnabled()) { LOG.warn("Caching on " + jp.toShortString() + " aborted due to an error.", ex); } else { LOG.warn( "Caching on " + jp.toShortString() + " aborted due to an error: " + ex.getMessage()); } } } }