From c7cb42724eac7ab67c5ceb98ae34de355ba2b370 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Mon, 3 Mar 2014 23:30:35 +0100 Subject: [PATCH] [Major] Multiple issues - Documented ComponentContainer.getComponent() - StrolchRealm try lock timeout is configurable - added DataStoreMode.isTransient() - documented Command - fixed lower case name attributes in Enums.xml --- .../strolch/agent/api/ComponentContainer.java | 2 +- .../li/strolch/agent/api/StrolchRealm.java | 19 ++++++- .../agent/impl/ComponentContainerImpl.java | 2 +- .../li/strolch/agent/impl/DataStoreMode.java | 22 ++++++++ .../persistence/api/AbstractTransaction.java | 10 +++- .../java/li/strolch/service/api/Command.java | 55 ++++++++++++++++++- .../resources/transienttest/data/Enums.xml | 30 +++++----- 7 files changed, 118 insertions(+), 22 deletions(-) diff --git a/src/main/java/li/strolch/agent/api/ComponentContainer.java b/src/main/java/li/strolch/agent/api/ComponentContainer.java index cfcf09b94..54e4ee890 100644 --- a/src/main/java/li/strolch/agent/api/ComponentContainer.java +++ b/src/main/java/li/strolch/agent/api/ComponentContainer.java @@ -31,7 +31,7 @@ public interface ComponentContainer { public abstract boolean hasComponent(Class clazz); - public abstract T getComponent(Class clazz); + public abstract T getComponent(Class clazz) throws IllegalArgumentException; public abstract Set> getComponentTypes(); diff --git a/src/main/java/li/strolch/agent/api/StrolchRealm.java b/src/main/java/li/strolch/agent/api/StrolchRealm.java index 10d9eab5b..ffc0745ab 100644 --- a/src/main/java/li/strolch/agent/api/StrolchRealm.java +++ b/src/main/java/li/strolch/agent/api/StrolchRealm.java @@ -15,17 +15,22 @@ */ package li.strolch.agent.api; +import static ch.eitchnet.utils.helper.StringHelper.DOT; + import java.util.concurrent.TimeUnit; import li.strolch.agent.impl.DataStoreMode; import li.strolch.agent.impl.DefaultLockHandler; import li.strolch.model.StrolchRootElement; import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.runtime.StrolchConstants; import li.strolch.runtime.configuration.ComponentConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.eitchnet.utils.dbc.DBC; + /** * @author Robert von Burg */ @@ -38,6 +43,7 @@ public abstract class StrolchRealm { private LockHandler lockHandler; public StrolchRealm(String realm) { + DBC.PRE.assertNotEmpty("RealmName may not be empty!", realm); this.realm = realm; } @@ -46,6 +52,7 @@ public abstract class StrolchRealm { } public void lock(StrolchRootElement element) { + DBC.PRE.assertNotNull("Can not lock a null pointer =)", element); this.lockHandler.lock(element); } @@ -54,8 +61,16 @@ public abstract class StrolchRealm { } public void initialize(ComponentContainer container, ComponentConfiguration configuration) { - TimeUnit timeUnit = TimeUnit.valueOf(configuration.getString(PROP_TRY_LOCK_TIME_UNIT, TimeUnit.SECONDS.name())); - long time = configuration.getLong(PROP_TRY_LOCK_TIME, 10); + + String propTryLockTimeUnit = PROP_TRY_LOCK_TIME_UNIT; + String propTryLockTime = PROP_TRY_LOCK_TIME; + if (!StrolchConstants.DEFAULT_REALM.equals(this.realm)) { + propTryLockTimeUnit += DOT + this.realm; + propTryLockTime += DOT + this.realm; + } + + TimeUnit timeUnit = TimeUnit.valueOf(configuration.getString(propTryLockTimeUnit, TimeUnit.SECONDS.name())); + long time = configuration.getLong(propTryLockTime, 10); logger.info("Using a locking try timeout of " + timeUnit.toSeconds(time) + "s"); this.lockHandler = new DefaultLockHandler(realm, timeUnit, time); } diff --git a/src/main/java/li/strolch/agent/impl/ComponentContainerImpl.java b/src/main/java/li/strolch/agent/impl/ComponentContainerImpl.java index 370baa870..a60b0d0e7 100644 --- a/src/main/java/li/strolch/agent/impl/ComponentContainerImpl.java +++ b/src/main/java/li/strolch/agent/impl/ComponentContainerImpl.java @@ -74,7 +74,7 @@ public class ComponentContainerImpl implements ComponentContainer { @Override @SuppressWarnings("unchecked") - public T getComponent(Class clazz) { + public T getComponent(Class clazz) throws IllegalArgumentException { T component = (T) this.componentMap.get(clazz); if (component == null) { String msg = "The component does not exist for class {0}"; //$NON-NLS-1$ diff --git a/src/main/java/li/strolch/agent/impl/DataStoreMode.java b/src/main/java/li/strolch/agent/impl/DataStoreMode.java index 21a7a9523..918d138e2 100644 --- a/src/main/java/li/strolch/agent/impl/DataStoreMode.java +++ b/src/main/java/li/strolch/agent/impl/DataStoreMode.java @@ -25,24 +25,44 @@ import li.strolch.agent.api.StrolchRealm; */ public enum DataStoreMode { EMPTY { + @Override + public boolean isTransient() { + return true; + } + @Override public StrolchRealm createRealm(String realm) { return new EmptyRealm(realm); } }, // TRANSIENT { + @Override + public boolean isTransient() { + return true; + } + @Override public StrolchRealm createRealm(String realm) { return new TransientRealm(realm); } }, // CACHED { + @Override + public boolean isTransient() { + return false; + } + @Override public StrolchRealm createRealm(String realm) { return new CachedRealm(realm); } }, // TRANSACTIONAL { + @Override + public boolean isTransient() { + return false; + } + @Override public StrolchRealm createRealm(String realm) { return new TransactionalRealm(realm); @@ -51,6 +71,8 @@ public enum DataStoreMode { public abstract StrolchRealm createRealm(String realm); + public abstract boolean isTransient(); + public static DataStoreMode parseDataStoreMode(String modeS) { for (DataStoreMode dataStoreMode : values()) { if (dataStoreMode.name().endsWith(modeS)) diff --git a/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 8630186e7..9b6651406 100644 --- a/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -258,6 +258,11 @@ public abstract class AbstractTransaction implements StrolchTransaction { } catch (Exception e1) { handleFailure(start, e); } + + String msg = "Strolch Transaction for realm {0} failed due to {1}"; + msg = MessageFormat.format(msg, getRealmName(), e.getMessage()); + throw new StrolchPersistenceException(msg, e); + } finally { unlockElements(); } @@ -334,8 +339,9 @@ public abstract class AbstractTransaction implements StrolchTransaction { sb.append(StringHelper.formatNanoDuration(closeDuration)); logger.info(sb.toString()); - throw new StrolchPersistenceException( - "Strolch Transaction for realm " + getRealmName() + " failed due to " + e.getMessage(), e); //$NON-NLS-1$ + String msg = "Strolch Transaction for realm {0} failed due to {1}"; + msg = MessageFormat.format(msg, getRealmName(), e.getMessage()); + throw new StrolchPersistenceException(msg, e); } private void updateObservers() { diff --git a/src/main/java/li/strolch/service/api/Command.java b/src/main/java/li/strolch/service/api/Command.java index a124b0686..d1eacf609 100644 --- a/src/main/java/li/strolch/service/api/Command.java +++ b/src/main/java/li/strolch/service/api/Command.java @@ -16,6 +16,7 @@ package li.strolch.service.api; import li.strolch.agent.api.ComponentContainer; +import li.strolch.agent.api.StrolchComponent; import li.strolch.persistence.api.StrolchTransaction; import org.slf4j.Logger; @@ -24,6 +25,16 @@ import org.slf4j.LoggerFactory; import ch.eitchnet.privilege.model.Restrictable; /** + *

+ * Implementation of the Command Pattern to create re-usable components which are performed during + * {@link StrolchTransaction StrolchTransactions} as part of the execution of {@link Service Services} + *

+ * + *

+ * Note: Do not call {@link #doCommand()} from {@link Service Services} or other places. Add {@link Command} + * instances to a {@link StrolchTransaction} by calling {@link StrolchTransaction#addCommand(Command)} + *

+ * * @author Robert von Burg */ public abstract class Command implements Restrictable { @@ -32,12 +43,31 @@ public abstract class Command implements Restrictable { private final ComponentContainer container; private final StrolchTransaction tx; + /** + * Instantiate a new {@link Command} + * + * @param container + * the {@link ComponentContainer} to access components at runtime + * @param tx + */ public Command(ComponentContainer container, StrolchTransaction tx) { this.container = container; this.tx = tx; } - public V getComponent(Class clazz) { + /** + * Allows the concrete {@link Command} implementation access to {@link StrolchComponent StrolchComponents} at + * runtime + * + * @param clazz + * the type of component to be returned + * + * @return the component with the given {@link Class} which is registered on the {@link ComponentContainer} + * + * @throws IllegalArgumentException + * if the component with the given class does not exist + */ + protected V getComponent(Class clazz) throws IllegalArgumentException { return this.container.getComponent(clazz); } @@ -73,9 +103,32 @@ public abstract class Command implements Restrictable { return this.getClass().getName(); } + /** + * To ensure that as few possibilities for exceptions as possible occur when {@link #doCommand()} is called, the + * {@link Command} should verify any input data so that a {@link #doCommand()} can be performed without exceptions + */ public abstract void validate(); + /** + *

+ * Clients implement this method to perform the work which is to be done in this {@link Command}. + *

+ * + *

+ * Note: Do not call this method directly, this method is called by the {@link StrolchTransaction} when the + * transaction is committed. Add this {@link Command} to the transaction by calling + * {@link StrolchTransaction#addCommand(Command)} + *

+ */ public abstract void doCommand(); + /** + *

+ * Should the transaction fail, either due to a {@link Command} throwing an exception when {@link #validate()} is + * called, or while committing the transaction, then this method should properly undo any changes it has done. It is + * imperative that this method does not throw further exceptions and that the state to be rolled back is remembered + * in the Command during committing + *

+ */ public abstract void undo(); } diff --git a/src/test/resources/transienttest/data/Enums.xml b/src/test/resources/transienttest/data/Enums.xml index 62ddb9c61..eb80fda34 100644 --- a/src/test/resources/transienttest/data/Enums.xml +++ b/src/test/resources/transienttest/data/Enums.xml @@ -3,31 +3,31 @@ - - - + + + - - - + + + - - - - - - - - - + + + + + + + + +