New:
- needsCommit() -> return true if objects or commands are registered
- hasResource()
- hasOrder()
- hasActivity()
Changes:
- When tx.add(), update() or remove() is called, then get*Template(), or get*By() check the internal cache and thus e.g. a new resource is immediately available.
- the has*()-methods also check the internal cache, thus the need to get the underlying maps should now no longe be required in normal TX use.
This observer handler is enabled with the additional boolean
configuration <enableDelayedObserverUpdates> and allows for less updates
to observers as they are cached
Now execution is always performed asynchronously for each Action and an
Activity should be added to the ExecutionHandler by calling
.addForExecution(), so that it is executed later even if an action
couldn't be executed to it being reserved (for instance).
This is required because in certain instances it is important to lock
the object before retrieving it, otherwise if, for instance in
execution, we would need to fetch, lock and re-fetch to be sure we have
the latest object.
In moste of the Update*Commands this is not important as we perform a
list commit wins, where the client wants their version to be persisted.
Later a optimistic locking can be performed in that the given version
must be the latest, otherwise an exception would be thrown
Using the DurationExecution:
<Activity Id="produceBicycle" Name="Activity" Type="ToStock"
TimeOrdering="Series">
<ParameterBag Name="objectives" Id="Objectives" Type="Objectives">
<Parameter Name="Duration" Id="duration" Value="PT0.01S"
Type="Duration" />
</ParameterBag>
<Action Id="produce" Name="Produce" ResourceId="bicycle"
ResourceType="Product" Type="Produce" />
</Activity>
IActivityElement now has a new method .findParameter() to search up the
activity hierarchy to find the element
Simplified the API, removed the privileged user - now always use the
agent system user for running system actions. One method has no return
value and one has a return value. Now it is easy to perform a system
action using:
runAsAgent(ctx -> {
// do work
});
String result = runAsAgentWithResult(ctx -> {
// do work
return "done";
});
// execute a SystemAction
runAsAgent(action);
// execute a SystemActionWithResult
String result = runAsAgentWithResult(actionWithResult);
Simplified the API, removed the privileged user - now always use the
agent system user for running system actions. One method has no return
value and one has a return value. Now it is easy to perform a system
action using:
runAsAgent(ctx -> {
// do work
});
String result = runAsAgentWithResult(ctx -> {
// do work
return "done";
});
// execute a SystemAction
runAsAgent(action);
// execute a SystemActionWithResult
String result = runAsAgentWithResult(actionWithResult);
- built in User Challenge feature (currently only console)
- extended REST API to allow user to initiate a challenge and then use
the challenge to authenticate for a one time change password session
Now all root elements have a version, and if the realm has versioning
enabled, then actions through the ElementMap lead to new versions being
created. There are also methods to revert/undo changes to an object.
Some tests are still failing, this will be fixed later
- New ParameterBagContainer interface for GroupedParameterizedElement
- StrolchRootElement extends ParameterBagContainer
- StrolchRootElement is now required in Queries, not StrolchElement
- New Version object on StrolchRootElement
So now users and roles are in their own files. This makes it far easier
to add new privileges without needing to take care if the user changed
their data.
Now instead of instantiating StrolchAgent and calling the method
setup(), instantiate StrolchBootstrapper and call one of the setup
methods which is appropriate to your use-case.
New feature is to use a StrolchBootstrap.xml to configure the
environment, root, config and data paths. Each can be defined by
environment and overridden, etc.
- and from now on we don't use interfaces anymore. We use abstract
classes with StrolchPolicy as the super class.
- it would be lovely if Java would get rid of interfaces and abstract
classes. We only need one: abstract classes.
You can now add policies to Resources, Orders and Activities:
<Policies>
<Policy Type="PlanningPolicy" Value="key:SimplePlanningPolicy" />
<Policy Type="ExecutionPolicy"
Value="java:li.strolch.policy.execution.TestSimulatedExecutionPolicy" />
<Policy Type="ConfirmationPolicy" Value="key:NoConfirmation" />
</Policies>
And now there is a PolicyHandler to get the Policy:
<Component>
<name>PolicyHandler</name>
<api>li.strolch.policy.PolicyHandler</api>
<impl>li.strolch.policy.DefaultPolicyHandler</impl>
<Properties>
<readPolicyFile>true</readPolicyFile>
<policyConfigFile>StrolchPolicies.xml</policyConfigFile>
</Properties>
</Component>
Which has its own configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<StrolchPolicies>
<PolicyType Type="PlanningPolicy"
Api="li.strolch.policytest.TestPlanningPolicy">
<Policy Key="SimplePlanningPolicy"
Class="li.strolch.policytest.TestSimplePlanningPolicy" />
</PolicyType>
<PolicyType Type="ConfirmationPolicy"
Api="li.strolch.policytest.TestConfirmationPolicy">
<Policy Key="NoConfirmation"
Class="li.strolch.policytest.TestNoConfirmationPolicy" />
</PolicyType>
</StrolchPolicies>
Some tests are still broken at this state - will fix them in the next
commit
- Creating new maps for transient, transactional and cached mode
- adding to Realms; including initialization
- adding new methods to transactions e.g. getActivityBy(), etc.
- Adding new ActivityDao with InMemory implementation
- extending PersistenceHandler
- fixed compile errors in the rest of the project
Still missing is the implementation in persistence handler and fixing
the tests. Currently no tests were run, just trying to fix compile
errors
- execption handling is done in the ComponentContainerStateHandler
- clients now not need to worry about exceptions which would make them
rethrow anyhow as a runtime exception
Now a SystemUserAction is defined as follows:
<Privilege name="ch.eitchnet.privilege.handler.SystemUserAction"
policy="DefaultPrivilege">
<Allow>li.strolch.agent.impl.StartRealms</Allow>
</Privilege>
This can be very handy to not start the connection pool for realms which
you know won't connect to the DB (but is not transient) - weird isn't
it? =))
The property is: db.ignore.realm.<realmName>
The actual use case is the following:
- You have a realm which use is used normally and is not transient so
you have a configuration for it
- you have another StrolchComponent which opens its own transactions to
the DB but you only require a subset of the realms so you then use the
ignore property to ignore the other realms.
- currently the parsing of the versions is handled
- missing is the actual loading of the date into the realms
- and the performing of the code migrations
- and the registering of the performed migrations
- Now if you need to perform commands to carry on in your transaction,
you can simply use the tx.flush()-method.
- Should something go wrong, then even after a tx.flush() one can call
throw tx.fail("Reason") or tx.rollbackOnClose()
- So sadly just auto closing a TX using try-resource from Java7 is a bad idea.
- Doing that leads to problems when an exception is thrown, then the close is called (duh) but this leads to commit being called.
- Since the Java language does not offer a decent way to detect if the close is being called in the context of an exception i was forced to add a tx.commitOnClose() and tx.rollbackOnClose().
- The default is that when a TX is opened, then the close strategy is rollback; the API user must call tx.commitOnClose() before the TX is closed by the braces, or as late as possible, to make sure that if an exception is thrown the transaction is rolled back, and not committed.
- The API was also extended with a tx.fail(msg):StrolchTransactionException so that if the implementor detects an unrecoverable error, one can write: throw tx.fail(“my reason”);
This was sadly an unavoidable late 1.0.0 change
Conflicts:
li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java
- So sadly just auto closing a TX using try-resource from Java7 is a bad idea.
- Doing that leads to problems when an exception is thrown, then the close is called (duh) but this leads to commit being called.
- Since the Java language does not offer a decent way to detect if the close is being called in the context of an exception i was forced to add a tx.commitOnClose() and tx.rollbackOnClose().
- The default is that when a TX is opened, then the close strategy is rollback; the API user must call tx.commitOnClose() before the TX is closed by the braces, or as late as possible, to make sure that if an exception is thrown the transaction is rolled back, and not committed.
- The API was also extended with a tx.fail(msg):StrolchTransactionException so that if the implementor detects an unrecoverable error, one can write: throw tx.fail(“my reason”);
This was sadly an unavoidable late 1.0.0 change
- this was a big issue as the query was delegated by the TX to the
persistence handler, which meant that the current element map types
(cached, transactional, etc.) were ignored. Move the doQuery to the
element maps, and this lead to also reimplementing the way the cached
element maps work: they now use an in memory dao, instead of MapOfMaps
Now if you add the DefaultServiceHandler property 'throwOnPrivilegeFail'
and set it to true, then the service handler will throw a
StrolchAccessDeniedException which in combination with the
StrolchRestfulExceptionMapper allows rest services to quickly determine
if the error was because the user does not have access to the requested
resource.
Same goes for performing queries in AbstractTransaction only there
instead of throwing a privilege exception, we now also throw a
StrolchAccessDeniedException
When a TX is closed, all locked objects are unlocked. The but originated from multiple commands being performed for the same object, thus the object was locked multiple times i.e. the lock counter was >1. Now added a releaseLock() method which is called by the TX when the TX is closed so that the lock counter is really 0 and the lock is released.
- Added tests for this situation
- documented the LockHandler
SessionHandler now has a timer checking to make sure that sessions which haven’t been accessed for a time defined by ‘session.ttl.minutes’ are invalidated
Now PostgreSQL implementation can import a configured dataStore if the persistence handler configuration property ‘allowDataInitOnSchemaCreate’. For this to work, the schema must have a migration status of CREATED, or DROPPED_CREATED on startup, or using the new method PersistenceHandler.performDbInitialization()-method. Further the properties ‘allowSchemaDrop’ and ‘allowSchemaCreate’ must be enabled.