[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
This commit is contained in:
Robert von Burg 2014-03-03 23:30:35 +01:00
parent 66e70fce75
commit c7cb42724e
7 changed files with 118 additions and 22 deletions

View File

@ -31,7 +31,7 @@ public interface ComponentContainer {
public abstract boolean hasComponent(Class<?> clazz); public abstract boolean hasComponent(Class<?> clazz);
public abstract <T> T getComponent(Class<T> clazz); public abstract <T> T getComponent(Class<T> clazz) throws IllegalArgumentException;
public abstract Set<Class<?>> getComponentTypes(); public abstract Set<Class<?>> getComponentTypes();

View File

@ -15,17 +15,22 @@
*/ */
package li.strolch.agent.api; package li.strolch.agent.api;
import static ch.eitchnet.utils.helper.StringHelper.DOT;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import li.strolch.agent.impl.DataStoreMode; import li.strolch.agent.impl.DataStoreMode;
import li.strolch.agent.impl.DefaultLockHandler; import li.strolch.agent.impl.DefaultLockHandler;
import li.strolch.model.StrolchRootElement; import li.strolch.model.StrolchRootElement;
import li.strolch.persistence.api.StrolchTransaction; import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.ComponentConfiguration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ch.eitchnet.utils.dbc.DBC;
/** /**
* @author Robert von Burg <eitch@eitchnet.ch> * @author Robert von Burg <eitch@eitchnet.ch>
*/ */
@ -38,6 +43,7 @@ public abstract class StrolchRealm {
private LockHandler lockHandler; private LockHandler lockHandler;
public StrolchRealm(String realm) { public StrolchRealm(String realm) {
DBC.PRE.assertNotEmpty("RealmName may not be empty!", realm);
this.realm = realm; this.realm = realm;
} }
@ -46,6 +52,7 @@ public abstract class StrolchRealm {
} }
public void lock(StrolchRootElement element) { public void lock(StrolchRootElement element) {
DBC.PRE.assertNotNull("Can not lock a null pointer =)", element);
this.lockHandler.lock(element); this.lockHandler.lock(element);
} }
@ -54,8 +61,16 @@ public abstract class StrolchRealm {
} }
public void initialize(ComponentContainer container, ComponentConfiguration configuration) { 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"); logger.info("Using a locking try timeout of " + timeUnit.toSeconds(time) + "s");
this.lockHandler = new DefaultLockHandler(realm, timeUnit, time); this.lockHandler = new DefaultLockHandler(realm, timeUnit, time);
} }

View File

@ -74,7 +74,7 @@ public class ComponentContainerImpl implements ComponentContainer {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> clazz) { public <T> T getComponent(Class<T> clazz) throws IllegalArgumentException {
T component = (T) this.componentMap.get(clazz); T component = (T) this.componentMap.get(clazz);
if (component == null) { if (component == null) {
String msg = "The component does not exist for class {0}"; //$NON-NLS-1$ String msg = "The component does not exist for class {0}"; //$NON-NLS-1$

View File

@ -25,24 +25,44 @@ import li.strolch.agent.api.StrolchRealm;
*/ */
public enum DataStoreMode { public enum DataStoreMode {
EMPTY { EMPTY {
@Override
public boolean isTransient() {
return true;
}
@Override @Override
public StrolchRealm createRealm(String realm) { public StrolchRealm createRealm(String realm) {
return new EmptyRealm(realm); return new EmptyRealm(realm);
} }
}, // }, //
TRANSIENT { TRANSIENT {
@Override
public boolean isTransient() {
return true;
}
@Override @Override
public StrolchRealm createRealm(String realm) { public StrolchRealm createRealm(String realm) {
return new TransientRealm(realm); return new TransientRealm(realm);
} }
}, // }, //
CACHED { CACHED {
@Override
public boolean isTransient() {
return false;
}
@Override @Override
public StrolchRealm createRealm(String realm) { public StrolchRealm createRealm(String realm) {
return new CachedRealm(realm); return new CachedRealm(realm);
} }
}, // }, //
TRANSACTIONAL { TRANSACTIONAL {
@Override
public boolean isTransient() {
return false;
}
@Override @Override
public StrolchRealm createRealm(String realm) { public StrolchRealm createRealm(String realm) {
return new TransactionalRealm(realm); return new TransactionalRealm(realm);
@ -51,6 +71,8 @@ public enum DataStoreMode {
public abstract StrolchRealm createRealm(String realm); public abstract StrolchRealm createRealm(String realm);
public abstract boolean isTransient();
public static DataStoreMode parseDataStoreMode(String modeS) { public static DataStoreMode parseDataStoreMode(String modeS) {
for (DataStoreMode dataStoreMode : values()) { for (DataStoreMode dataStoreMode : values()) {
if (dataStoreMode.name().endsWith(modeS)) if (dataStoreMode.name().endsWith(modeS))

View File

@ -258,6 +258,11 @@ public abstract class AbstractTransaction implements StrolchTransaction {
} catch (Exception e1) { } catch (Exception e1) {
handleFailure(start, e); 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 { } finally {
unlockElements(); unlockElements();
} }
@ -334,8 +339,9 @@ public abstract class AbstractTransaction implements StrolchTransaction {
sb.append(StringHelper.formatNanoDuration(closeDuration)); sb.append(StringHelper.formatNanoDuration(closeDuration));
logger.info(sb.toString()); logger.info(sb.toString());
throw new StrolchPersistenceException( String msg = "Strolch Transaction for realm {0} failed due to {1}";
"Strolch Transaction for realm " + getRealmName() + " failed due to " + e.getMessage(), e); //$NON-NLS-1$ msg = MessageFormat.format(msg, getRealmName(), e.getMessage());
throw new StrolchPersistenceException(msg, e);
} }
private void updateObservers() { private void updateObservers() {

View File

@ -16,6 +16,7 @@
package li.strolch.service.api; package li.strolch.service.api;
import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.persistence.api.StrolchTransaction; import li.strolch.persistence.api.StrolchTransaction;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -24,6 +25,16 @@ import org.slf4j.LoggerFactory;
import ch.eitchnet.privilege.model.Restrictable; import ch.eitchnet.privilege.model.Restrictable;
/** /**
* <p>
* 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}
* </p>
*
* <p>
* <b>Note:</b> 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)}
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch> * @author Robert von Burg <eitch@eitchnet.ch>
*/ */
public abstract class Command implements Restrictable { public abstract class Command implements Restrictable {
@ -32,12 +43,31 @@ public abstract class Command implements Restrictable {
private final ComponentContainer container; private final ComponentContainer container;
private final StrolchTransaction tx; 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) { public Command(ComponentContainer container, StrolchTransaction tx) {
this.container = container; this.container = container;
this.tx = tx; this.tx = tx;
} }
public <V> V getComponent(Class<V> 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> V getComponent(Class<V> clazz) throws IllegalArgumentException {
return this.container.getComponent(clazz); return this.container.getComponent(clazz);
} }
@ -73,9 +103,32 @@ public abstract class Command implements Restrictable {
return this.getClass().getName(); 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(); public abstract void validate();
/**
* <p>
* Clients implement this method to perform the work which is to be done in this {@link Command}.
* </p>
*
* <p>
* <b>Note:</b> 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)}
* </p>
*/
public abstract void doCommand(); public abstract void doCommand();
/**
* <p>
* 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
* </p>
*/
public abstract void undo(); public abstract void undo();
} }

View File

@ -3,31 +3,31 @@
<Resource Id="salutations" Name="Salutations" Type="Enumeration"> <Resource Id="salutations" Name="Salutations" Type="Enumeration">
<ParameterBag Id="en" Name="Salutations" Type="Enumeration"> <ParameterBag Id="en" Name="Salutations" Type="Enumeration">
<Parameter Id="mr" name="Mr" Type="String" Value="Mr" /> <Parameter Id="mr" Name="Mr" Type="String" Value="Mr" />
<Parameter Id="mrs" name="Mrs" Type="String" Value="Mrs" /> <Parameter Id="mrs" Name="Mrs" Type="String" Value="Mrs" />
<Parameter Id="ms" name="Ms" Type="String" Value="Ms" /> <Parameter Id="ms" Name="Ms" Type="String" Value="Ms" />
</ParameterBag> </ParameterBag>
</Resource> </Resource>
<Resource Id="sex" Name="Sex" Type="Enumeration"> <Resource Id="sex" Name="Sex" Type="Enumeration">
<ParameterBag Id="en" Name="Sex" Type="Enumeration"> <ParameterBag Id="en" Name="Sex" Type="Enumeration">
<Parameter Id="male" name="Male" Type="String" Value="male" /> <Parameter Id="male" Name="Male" Type="String" Value="male" />
<Parameter Id="female" name="Female" Type="String" Value="female" /> <Parameter Id="female" Name="Female" Type="String" Value="female" />
<Parameter Id="both" name="Both" Type="String" Value="both" /> <Parameter Id="both" Name="Both" Type="String" Value="both" />
</ParameterBag> </ParameterBag>
</Resource> </Resource>
<Resource Id="religions" Name="Religions" Type="Enumeration"> <Resource Id="religions" Name="Religions" Type="Enumeration">
<ParameterBag Id="en" Name="Religions" Type="Enumeration"> <ParameterBag Id="en" Name="Religions" Type="Enumeration">
<Parameter Id="Roman Catholic" name="Roman Catholic" Type="String" Value="Roman Catholic" /> <Parameter Id="Roman Catholic" Name="Roman Catholic" Type="String" Value="Roman Catholic" />
<Parameter Id="Protestant" name="Protestant" Type="String" Value="Protestant" /> <Parameter Id="Protestant" Name="Protestant" Type="String" Value="Protestant" />
<Parameter Id="Orthodox" name="Orthodox" Type="String" Value="Orthodox" /> <Parameter Id="Orthodox" Name="Orthodox" Type="String" Value="Orthodox" />
<Parameter Id="Christian" name="Anglican" Type="String" Value="Anglican" /> <Parameter Id="Christian" Name="Anglican" Type="String" Value="Anglican" />
<Parameter Id="Muslim" name="Muslim" Type="String" Value="Muslim" /> <Parameter Id="Muslim" Name="Muslim" Type="String" Value="Muslim" />
<Parameter Id="Hindu" name="Hindu" Type="String" Value="Hindu" /> <Parameter Id="Hindu" Name="Hindu" Type="String" Value="Hindu" />
<Parameter Id="Buddhist" name="Buddhist" Type="String" Value="Buddhist" /> <Parameter Id="Buddhist" Name="Buddhist" Type="String" Value="Buddhist" />
<Parameter Id="Jewish" name="Jewish" Type="String" Value="Jewish" /> <Parameter Id="Jewish" Name="Jewish" Type="String" Value="Jewish" />
<Parameter Id="Atheist" name="Atheist" Type="String" Value="Atheist" /> <Parameter Id="Atheist" Name="Atheist" Type="String" Value="Atheist" />
</ParameterBag> </ParameterBag>
</Resource> </Resource>