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

Former-commit-id: e510224845
pull/2/head
jensp 2017-02-18 13:48:46 +00:00
parent 2ff03eb176
commit b644548c87
3 changed files with 91 additions and 28 deletions

View File

@ -51,10 +51,15 @@ import static org.libreccm.core.CoreConstants.*;
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQueries({ @NamedQueries({
@NamedQuery( @NamedQuery(
name = "AbstractSetting.findByClassAndName", name = "AbstractSetting.findAllForClass",
query = "SELECT s FROM AbstractSetting s " query = "SELECT s FROM AbstractSetting s "
+ "WHERE configurationClass = :class " + "WHERE s.configurationClass = :class")
+ "AND name = :name") ,
@NamedQuery(
name = "AbstractSetting.findByClassAndName",
query = "SELECT s FROM AbstractSetting s "
+ "WHERE s.configurationClass = :class "
+ "AND s.name = :name")
}) })
public abstract class AbstractSetting<T> implements Serializable { public abstract class AbstractSetting<T> implements Serializable {
@ -95,11 +100,11 @@ public abstract class AbstractSetting<T> implements Serializable {
public String getConfigurationClass() { public String getConfigurationClass() {
return configurationClass; return configurationClass;
} }
public void setConfigurationClass(final String configurationClass) { public void setConfigurationClass(final String configurationClass) {
this.configurationClass = configurationClass; this.configurationClass = configurationClass;
} }
public String getName() { public String getName() {
return name; return name;
} }
@ -151,10 +156,10 @@ public abstract class AbstractSetting<T> implements Serializable {
return false; return false;
} }
if (!Objects.equals(configurationClass, other.configurationClass)) { if (!Objects.equals(configurationClass, other.getConfigurationClass())) {
return false; return false;
} }
return Objects.equals(name, other.name); return Objects.equals(name, other.getName());
} }
public boolean canEqual(final Object obj) { public boolean canEqual(final Object obj) {
@ -168,17 +173,17 @@ public abstract class AbstractSetting<T> implements Serializable {
public String toString(final String data) { public String toString(final String data) {
return String.format( return String.format(
"%s{ " "%s{ "
+ "settingId = %d, " + "settingId = %d, "
+ "configurationClass = \"%s\" " + "configurationClass = \"%s\" "
+ "name = \"%s\" " + "name = \"%s\" "
+ "%s" + "%s"
+ " }", + " }",
super.toString(), super.toString(),
settingId, settingId,
configurationClass, configurationClass,
name, name,
data); data);
} }
} }

View File

@ -34,7 +34,9 @@ import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -56,6 +58,11 @@ public class ConfigurationManager {
@Inject @Inject
private SettingConverter settingConverter; private SettingConverter settingConverter;
/**
* Map used to cache configuration during a request.
*/
private final Map<String, Object> confCache = new HashMap<>();
/** /**
* Finds all configuration classes listed by the installed modules. * 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 * @throws IllegalArgumentException if the provided class is not annotated
* with {@link Configuration}. * with {@link Configuration}.
*/ */
@SuppressWarnings("unchecked")
public <T> T findConfiguration(final Class<T> confClass) { public <T> T findConfiguration(final Class<T> confClass) {
if (confClass == null) { if (confClass == null) {
throw new IllegalArgumentException("confClass can't be null"); throw new IllegalArgumentException("confClass can't be null");
@ -114,8 +122,16 @@ public class ConfigurationManager {
} }
final String confName = confClass.getName(); final String confName = confClass.getName();
// First check if we have already retrieved the requested configuration
return findConfiguration(confName, confClass); // 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); 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 * @return An instance of the configuration class with all setting fields
* set to the values stored in the registry. * set to the values stored in the registry.
*/ */
@SuppressWarnings("rawtypes")
<T> T findConfiguration(final String confName, final Class<T> confClass) { <T> T findConfiguration(final String confName, final Class<T> confClass) {
final T conf; final T conf;
@ -339,6 +363,12 @@ public class ConfigurationManager {
return null; return null;
} }
final List<AbstractSetting> settingList = settingManager
.retrieveAllSettings(confName);
final Map<String, AbstractSetting> settings = settingList.stream()
.collect(Collectors.toMap(setting -> setting.getName(),
setting -> setting));
final Field[] fields = confClass.getDeclaredFields(); final Field[] fields = confClass.getDeclaredFields();
for (final Field field : fields) { for (final Field field : fields) {
field.setAccessible(true); field.setAccessible(true);
@ -348,17 +378,15 @@ public class ConfigurationManager {
final String settingName = getSettingName(field); final String settingName = getSettingName(field);
final Class<?> settingType = field.getType(); if (settings.containsKey(settingName)) {
final AbstractSetting<?> setting = settingManager.findSetting( final AbstractSetting<?> setting = settings.get(settingName);
confName, settingName, settingType);
if (setting != null) {
try { try {
LOGGER.debug("Setting \"{}#{}\" found. Value: {}", LOGGER.debug("Setting \"{}#{}\" found. Value: {}",
confName, confName,
settingName, settingName,
setting.getValue()); setting.getValue());
field.set(conf, setting.getValue()); field.set(conf, setting.getValue());
} catch (IllegalAccessException ex) { } catch(IllegalAccessException ex) {
LOGGER.warn( LOGGER.warn(
"Failed to set value of configuration class \"{}\". " "Failed to set value of configuration class \"{}\". "
+ "Ignoring.", + "Ignoring.",
@ -366,6 +394,25 @@ public class ConfigurationManager {
ex); 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; return conf;

View File

@ -94,6 +94,17 @@ public class SettingManager {
return settings; return settings;
} }
public List<AbstractSetting> retrieveAllSettings(final String confName) {
Objects.requireNonNull(confName);
final TypedQuery<AbstractSetting> query = entityManager
.createNamedQuery("AbstractSetting.findAllForClass",
AbstractSetting.class);
query.setParameter("class", confName);
return query.getResultList();
}
/** /**
* Create a {@link SettingInfo} instance for a setting. * Create a {@link SettingInfo} instance for a setting.
* *
@ -134,10 +145,10 @@ public class SettingManager {
ex); ex);
return null; return null;
} }
//Make the field accessible even if it has a private modifier //Make the field accessible even if it has a private modifier
field.setAccessible(true); field.setAccessible(true);
if (field.getAnnotation(Setting.class) == null) { if (field.getAnnotation(Setting.class) == null) {
return null; return null;
} }