Class CachingOfBizPropertySet

java.lang.Object
com.opensymphony.module.propertyset.AbstractPropertySet
com.atlassian.jira.propertyset.CachingOfBizPropertySet
All Implemented Interfaces:
com.opensymphony.module.propertyset.PropertySet, Serializable

public class CachingOfBizPropertySet extends com.opensymphony.module.propertyset.AbstractPropertySet implements Serializable
Reimplementation of OFBizPropertySet that caches property entries and values to provide more efficient access.

Note that JiraCachingPropertySet is just a decorator around an arbitrary supplied property set and thus has uncertain behaviour both in a clustered environment and when there are multiple instances of the caching property set, as the individual caches have no way to share state.

CachingOfBizPropertySet is different. It is a flyweight around the OfBizPropertyEntryStore, which caches the operations that it can (such as the existence, type, and value of an entry) and delegates those it can't cache to the database directly. The implementation deviates from that of OFBizPropertySet only in ways that make it more fault-tolerant, such as by not throwing an exception when removing a nonexistent property and not throwing an exception when setting a property to a new type without removing it first.

The only known disadvantage to using this class is that it will eagerly load the value on a cache miss. This seems to be an acceptable loss, because the main reasons why code would bother to call exists(String) or getType(String) seem to be

  1. To know whether or not the property exists and/or the appropriate getter type to use, both of which suggest that the value will eventually be retrieved anyway and that loading it eagerly is not wasteful.
  2. To guard against the exception that OFBizPropertySet throws if you attempt to remove a property that does not exist of change the type of an existing property. This implementation silently ignores a spurious remove and gracefully updates the type if it is changed, so these guards are not necessary.
  3. To use the existence or absence of the key as a boolean value, where the actual stored value is a meaningless sentinel. This is a strange thing to do, and it makes more sense to store an actual boolean value for the property, instead.

This class is thread-safe, in spite of the difficulties that the PropertySet contract imposes upon it. Its only mutable state is the entity definition provided through PropertySet.init(Map, Map). This is stored in an immutable holder class whose reference is marked as volatile to ensure safe publishing.

Although OFBizPropertySet itself allows for multiple generic delegators to be used, this implementation ignores this setting. JIRA always uses the "default" delegator.

Since:
v6.2
See Also:
  • Constructor Details

    • CachingOfBizPropertySet

      public CachingOfBizPropertySet()
    • CachingOfBizPropertySet

      public CachingOfBizPropertySet(String entityName, Long entityId)
    • CachingOfBizPropertySet

      public CachingOfBizPropertySet(OfBizPropertyEntryStore entryStore, String entityName, Long entityId)
  • Method Details

    • getKeys

      public List<String> getKeys()
      Specified by:
      getKeys in interface com.opensymphony.module.propertyset.PropertySet
      Overrides:
      getKeys in class com.opensymphony.module.propertyset.AbstractPropertySet
    • getKeys

      public List<String> getKeys(String prefix)
      Specified by:
      getKeys in interface com.opensymphony.module.propertyset.PropertySet
      Overrides:
      getKeys in class com.opensymphony.module.propertyset.AbstractPropertySet
    • getKeys

      public List<String> getKeys(int type)
      Specified by:
      getKeys in interface com.opensymphony.module.propertyset.PropertySet
      Overrides:
      getKeys in class com.opensymphony.module.propertyset.AbstractPropertySet
    • getKeys

      public List<String> getKeys(String prefix, int type)
      Specified by:
      getKeys in interface com.opensymphony.module.propertyset.PropertySet
    • getType

      public int getType(String key) throws com.opensymphony.module.propertyset.PropertyException
      Specified by:
      getType in interface com.opensymphony.module.propertyset.PropertySet
      Throws:
      com.opensymphony.module.propertyset.PropertyException
    • exists

      public boolean exists(String key) throws com.opensymphony.module.propertyset.PropertyException
      Specified by:
      exists in interface com.opensymphony.module.propertyset.PropertySet
      Throws:
      com.opensymphony.module.propertyset.PropertyException
    • init

      public void init(Map config, Map args)
      Specified by:
      init in interface com.opensymphony.module.propertyset.PropertySet
      Overrides:
      init in class com.opensymphony.module.propertyset.AbstractPropertySet
    • remove

      public void remove() throws com.opensymphony.module.propertyset.PropertyException
      Specified by:
      remove in interface com.opensymphony.module.propertyset.PropertySet
      Throws:
      com.opensymphony.module.propertyset.PropertyException
    • remove

      public void remove(String key)
      Implementation note: Unlike OFBizPropertySet, this implementation will not throw an exception if the property does not exist.
      Specified by:
      remove in interface com.opensymphony.module.propertyset.PropertySet
      Parameters:
      key - the key of the property to be removed
      Throws:
      com.opensymphony.module.propertyset.PropertyException - if the attempt to remove an existing property fails at the persistence layer
    • supportsType

      public boolean supportsType(int type)
      Specified by:
      supportsType in interface com.opensymphony.module.propertyset.PropertySet
      Overrides:
      supportsType in class com.opensymphony.module.propertyset.AbstractPropertySet
    • setImpl

      protected void setImpl(int type, String key, Object obj)
      Specified by:
      setImpl in class com.opensymphony.module.propertyset.AbstractPropertySet
    • get

      @Nullable protected Object get(int type, String key)
      Specified by:
      get in class com.opensymphony.module.propertyset.AbstractPropertySet
    • equals

      public boolean equals(Object o)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object