Details
-
Bug
-
Resolution: Unresolved
-
Low
-
None
-
6.4.3, 6.4.11
-
6.04
-
1
-
Severity 3 - Minor
-
0
-
Description
The CacheLoader interface that can be implemented by add-ons is defined such that the loader() function returns non-null.
If a client of the API violates the contract and returns a null value, recent versions of LoadingCache (at least atlassian-cache 2.5.8+) enforce this constraint and throw a CacheException. However, DelegatingCache hides the source of the exception and the corresponding error message, leaving only the following generic stack trace in the code, with no immediate clue as to the source:
com.atlassian.cache.CacheException at com.atlassian.cache.ehcache.DelegatingCache.get(DelegatingCache.java:99)
The issue is the first catch() in DelegatingCache, where the ehcache.CacheException is re-thrown as an Atlassian CacheException, but using "e.getCause()" rather than just "e".
@SuppressWarnings("unchecked") @Nullable @Override public V get(@Nonnull final K key) { try { Element element = delegate.get(key); return element == null ? null : (V) element.getObjectValue(); } catch (net.sf.ehcache.CacheException e) { throw new CacheException(e.getCause()); } catch (Exception e) { throw new CacheException(e); } }
When faced with a bare exception that has no cause, such as that thrown by LoadingCache#getFromLoader:
if (value == null) { throw new CacheException("CacheLoader returned null for key " + key); }
...it results in DelegatingCache performing a "throw new CacheException(null)" and no data being provided to the client. LoadingCache throws various other exceptions too, but they are all hidden from the logs.
(Perhaps LoadingCache needs to be throwing an Atlassian CacheException rather than an ehcache CacheException, or maybe DelegatingCache needs to be adjusted?)