From f5fd91780dc18f431bea11ee2a488ea6210adc7f Mon Sep 17 00:00:00 2001 From: jensp Date: Sat, 18 Feb 2017 13:48:46 +0000 Subject: [PATCH] CCM NG/ccm-core: Improved performance for the configuration (reduced number DB-Queries for loading a configuration). git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4583 8810af33-2d31-482b-a856-94f89814c4df --- .../configuration/AbstractSetting.java | 43 +++++++------ .../configuration/ConfigurationManager.java | 61 ++++++++++++++++--- .../configuration/SettingManager.java | 15 ++++- 3 files changed, 91 insertions(+), 28 deletions(-) diff --git a/ccm-core/src/main/java/org/libreccm/configuration/AbstractSetting.java b/ccm-core/src/main/java/org/libreccm/configuration/AbstractSetting.java index 6e1be26ac..02930a6e3 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/AbstractSetting.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/AbstractSetting.java @@ -51,10 +51,15 @@ import static org.libreccm.core.CoreConstants.*; @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @NamedQueries({ @NamedQuery( - name = "AbstractSetting.findByClassAndName", - query = "SELECT s FROM AbstractSetting s " - + "WHERE configurationClass = :class " - + "AND name = :name") + name = "AbstractSetting.findAllForClass", + query = "SELECT s FROM AbstractSetting s " + + "WHERE s.configurationClass = :class") + , + @NamedQuery( + name = "AbstractSetting.findByClassAndName", + query = "SELECT s FROM AbstractSetting s " + + "WHERE s.configurationClass = :class " + + "AND s.name = :name") }) public abstract class AbstractSetting implements Serializable { @@ -95,11 +100,11 @@ public abstract class AbstractSetting implements Serializable { public String getConfigurationClass() { return configurationClass; } - + public void setConfigurationClass(final String configurationClass) { this.configurationClass = configurationClass; } - + public String getName() { return name; } @@ -151,10 +156,10 @@ public abstract class AbstractSetting implements Serializable { return false; } - if (!Objects.equals(configurationClass, other.configurationClass)) { + if (!Objects.equals(configurationClass, other.getConfigurationClass())) { return false; } - return Objects.equals(name, other.name); + return Objects.equals(name, other.getName()); } public boolean canEqual(final Object obj) { @@ -168,17 +173,17 @@ public abstract class AbstractSetting implements Serializable { public String toString(final String data) { return String.format( - "%s{ " - + "settingId = %d, " - + "configurationClass = \"%s\" " - + "name = \"%s\" " - + "%s" - + " }", - super.toString(), - settingId, - configurationClass, - name, - data); + "%s{ " + + "settingId = %d, " + + "configurationClass = \"%s\" " + + "name = \"%s\" " + + "%s" + + " }", + super.toString(), + settingId, + configurationClass, + name, + data); } } diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java index 6ccd312ac..4c4a33787 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java @@ -34,7 +34,9 @@ import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.RequiresPrivilege; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.ServiceLoader; import java.util.SortedSet; import java.util.TreeSet; @@ -56,6 +58,11 @@ public class ConfigurationManager { @Inject private SettingConverter settingConverter; + + /** + * Map used to cache configuration during a request. + */ + private final Map confCache = new HashMap<>(); /** * Finds all configuration classes listed by the installed modules. @@ -101,6 +108,7 @@ public class ConfigurationManager { * @throws IllegalArgumentException if the provided class is not annotated * with {@link Configuration}. */ + @SuppressWarnings("unchecked") public T findConfiguration(final Class confClass) { if (confClass == null) { throw new IllegalArgumentException("confClass can't be null"); @@ -114,8 +122,16 @@ public class ConfigurationManager { } final String confName = confClass.getName(); - - return findConfiguration(confName, confClass); + // First check if we have already retrieved the requested configuration + // during the current request. If not retrieve the configuration and + // put it into the map. + if (confCache.containsKey(confName)) { + return (T) confCache.get(confName); + } else { + final T configuration = findConfiguration(confName, confClass); + confCache.put(confName, configuration); + return configuration; + } } /** @@ -182,6 +198,13 @@ public class ConfigurationManager { ex); } } + + /** + * If the configuration is cached remove the cached version. + */ + if (confCache.containsKey(configuration.getClass().getName())) { + confCache.remove(configuration.getClass().getName()); + } } /** @@ -326,6 +349,7 @@ public class ConfigurationManager { * @return An instance of the configuration class with all setting fields * set to the values stored in the registry. */ + @SuppressWarnings("rawtypes") T findConfiguration(final String confName, final Class confClass) { final T conf; @@ -339,6 +363,12 @@ public class ConfigurationManager { return null; } + final List settingList = settingManager + .retrieveAllSettings(confName); + final Map settings = settingList.stream() + .collect(Collectors.toMap(setting -> setting.getName(), + setting -> setting)); + final Field[] fields = confClass.getDeclaredFields(); for (final Field field : fields) { field.setAccessible(true); @@ -348,17 +378,15 @@ public class ConfigurationManager { final String settingName = getSettingName(field); - final Class settingType = field.getType(); - final AbstractSetting setting = settingManager.findSetting( - confName, settingName, settingType); - if (setting != null) { + if (settings.containsKey(settingName)) { + final AbstractSetting setting = settings.get(settingName); try { LOGGER.debug("Setting \"{}#{}\" found. Value: {}", confName, settingName, setting.getValue()); field.set(conf, setting.getValue()); - } catch (IllegalAccessException ex) { + } catch(IllegalAccessException ex) { LOGGER.warn( "Failed to set value of configuration class \"{}\". " + "Ignoring.", @@ -366,6 +394,25 @@ public class ConfigurationManager { ex); } } +// +// final Class settingType = field.getType(); +// final AbstractSetting setting = settingManager.findSetting( +// confName, settingName, settingType); +// if (setting != null) { +// try { +// LOGGER.debug("Setting \"{}#{}\" found. Value: {}", +// confName, +// settingName, +// setting.getValue()); +// field.set(conf, setting.getValue()); +// } catch (IllegalAccessException ex) { +// LOGGER.warn( +// "Failed to set value of configuration class \"{}\". " +// + "Ignoring.", +// confClass.getName(), +// ex); +// } +// } } return conf; diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java index 5aea9f4b2..61d182d30 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java @@ -94,6 +94,17 @@ public class SettingManager { return settings; } + public List retrieveAllSettings(final String confName) { + Objects.requireNonNull(confName); + + final TypedQuery query = entityManager + .createNamedQuery("AbstractSetting.findAllForClass", + AbstractSetting.class); + query.setParameter("class", confName); + + return query.getResultList(); + } + /** * Create a {@link SettingInfo} instance for a setting. * @@ -134,10 +145,10 @@ public class SettingManager { ex); return null; } - + //Make the field accessible even if it has a private modifier field.setAccessible(true); - + if (field.getAnnotation(Setting.class) == null) { return null; }