[Project] Extended documentation for:
- components - queries - realms - services and commands
This commit is contained in:
parent
b8834b9b82
commit
55fb3a53c8
|
@ -29,6 +29,7 @@ import li.strolch.policy.StrolchPolicy;
|
||||||
import li.strolch.privilege.base.PrivilegeException;
|
import li.strolch.privilege.base.PrivilegeException;
|
||||||
import li.strolch.privilege.handler.SystemUserAction;
|
import li.strolch.privilege.handler.SystemUserAction;
|
||||||
import li.strolch.privilege.model.Restrictable;
|
import li.strolch.privilege.model.Restrictable;
|
||||||
|
import li.strolch.runtime.StrolchConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -121,6 +122,21 @@ public abstract class Command implements Restrictable {
|
||||||
return this.container.getPrivilegeHandler().runAsSystem(username, action);
|
return this.container.getPrivilegeHandler().runAsSystem(username, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the given {@link SystemUserAction} as the privileged system user
|
||||||
|
* {@link StrolchConstants#PRIVILEGED_SYSTEM_USER}. Returns the action for chaining calls
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* the action to perform
|
||||||
|
*
|
||||||
|
* @return the action performed for chaining calls
|
||||||
|
*
|
||||||
|
* @throws PrivilegeException
|
||||||
|
*/
|
||||||
|
protected <V extends SystemUserAction> V runPrivileged(V action) throws PrivilegeException {
|
||||||
|
return this.container.getPrivilegeHandler().runAsSystem(StrolchConstants.PRIVILEGED_SYSTEM_USER, action);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link StrolchTransaction} bound to this {@link Command}'s runtime
|
* Returns the {@link StrolchTransaction} bound to this {@link Command}'s runtime
|
||||||
*
|
*
|
||||||
|
|
|
@ -55,14 +55,19 @@
|
||||||
|
|
||||||
<p>Currently we have the following topics of discussion:</p>
|
<p>Currently we have the following topics of discussion:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="documentation_runtime.html">Strolch Runtime Configuration</a></li>
|
|
||||||
<li><a href="documentation_do_and_dont.html">Strolch Do and Don’t</a></li>
|
<li><a href="documentation_do_and_dont.html">Strolch Do and Don’t</a></li>
|
||||||
</ul>
|
<li><a href="documentation_runtime.html">Strolch Runtime Configuration</a></li>
|
||||||
|
<li><a href="documentation_realms.html">Strolch Realms</a></li>
|
||||||
<p>Not yet written, but soon to come are:</p>
|
<li><a href="documentation_components.html">Strolch Components</a></li>
|
||||||
<ul>
|
<li><a href="documentation_services_and_commands.html">Strolch Services and Commands</a></li>
|
||||||
<li><a href="documentation_transactions.html">Strolch transactions</a></li>
|
<li><a href="documentation_queries.html">Strolch Queries</a></li>
|
||||||
<li><a href="documentation_business_logic.html">Business Logic in Strolch</a></li>
|
<!--
|
||||||
|
<li><a href="documentation_transactions.html">Strolch Transactions</a></li>
|
||||||
|
<li><a href="documentation_policies.html">Strolch Policies</a></li>
|
||||||
|
<li><a href="documentation_privileges.html">Strolch Privileges</a></li>
|
||||||
|
<li><a href="documentation_observers.html">Strolch Observers</a></li>
|
||||||
|
<li><a href="documentation_versioning.html">Strolch Versioning</a></li>
|
||||||
|
-->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- content here -->
|
<!-- content here -->
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
<link rel="shortcut icon" href="ico/favicon.ico">
|
|
||||||
|
|
||||||
<title>Strolch: Business Logic</title>
|
|
||||||
|
|
||||||
<!-- Bootstrap core CSS -->
|
|
||||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
<link href="css/custom.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
|
||||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
|
||||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<a class="navbar-brand" href="index.html">Strolch</a>
|
|
||||||
</div>
|
|
||||||
<div class="collapse navbar-collapse">
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li><a href="index.html">Overview</a></li>
|
|
||||||
<li><a href="api.html">API</a></li>
|
|
||||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
|
||||||
<li><a href="downloads.html">Downloads</a></li>
|
|
||||||
<li><a href="development.html">Development</a></li>
|
|
||||||
<li><a href="blog.html">Blog</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<!--/.nav-collapse -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h1 class="page-title">Documentation: Business Logic</h1>
|
|
||||||
|
|
||||||
<p class="lead page-description">This page discusses how business logic should be implemented in Strolch.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
<p>Writing business logic in Strolch</p>
|
|
||||||
|
|
||||||
<!-- content here -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.content -->
|
|
||||||
|
|
||||||
<div id="footer">
|
|
||||||
<div class="container">
|
|
||||||
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
|
||||||
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container -->
|
|
||||||
|
|
||||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
|
||||||
<script src="js/bootstrap.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Piwik -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
var _paq = _paq || [];
|
|
||||||
_paq.push(['trackPageView']);
|
|
||||||
_paq.push(['enableLinkTracking']);
|
|
||||||
(function () {
|
|
||||||
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
|
||||||
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
|
||||||
_paq.push(['setSiteId', 2]);
|
|
||||||
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
|
||||||
g.type = 'text/javascript';
|
|
||||||
g.defer = true;
|
|
||||||
g.async = true;
|
|
||||||
g.src = u + 'piwik.js';
|
|
||||||
s.parentNode.insertBefore(g, s);
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt=""/></p></noscript>
|
|
||||||
<!-- End Piwik Code -->
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
<link rel="shortcut icon" href="ico/favicon.ico">
|
||||||
|
|
||||||
|
<title>Strolch: Components</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="css/custom.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a class="navbar-brand" href="index.html">Strolch</a>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="index.html">Overview</a></li>
|
||||||
|
<li><a href="api.html">API</a></li>
|
||||||
|
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||||
|
<li><a href="downloads.html">Downloads</a></li>
|
||||||
|
<li><a href="development.html">Development</a></li>
|
||||||
|
<li><a href="blog.html">Blog</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">Documentation: Components</h1>
|
||||||
|
|
||||||
|
<p class="lead page-description">This page discusses Strolch Components</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<p>A Strolch agent can be easily extended with arbitrary components. An agent is basically a container for
|
||||||
|
classes extending <code>StrolchComponent</code>. Theses classes mostly implement an interface which
|
||||||
|
describes the
|
||||||
|
operations that are supported by the component.</p>
|
||||||
|
|
||||||
|
<p>The following represents a list of the most used components:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>RealmHandler</code>: li.strolch.agent.impl.DefaultRealmHandler</li>
|
||||||
|
<li><code>PrivilegeHandler</code>: li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</li>
|
||||||
|
<li><code>EnumHandler</code>: li.strolch.runtime.query.enums.DefaultEnumHandler</li>
|
||||||
|
<li><code>PolicyHandler</code>: li.strolch.policy.DefaultPolicyHandler</li>
|
||||||
|
<li><code>ServiceHandler</code>: li.strolch.service.api.DefaultServiceHandler</li>
|
||||||
|
<li><code>StrolchSessionHandler</code>: li.strolch.rest.DefaultStrolchSessionHandler</li>
|
||||||
|
<li><code>PersistenceHandler</code>: multiple implementations</li>
|
||||||
|
<li><code>PostInitializer</code>: project specific implementation</li>
|
||||||
|
<li><code>MailHandler</code>: li.strolch.handler.mail.SmtpMailHandler</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>A component has a life-cycle, which is governed by the Agent's own life-cycle. The life-cycle is as
|
||||||
|
follows:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
setup -> initialize -> start <-> stop -> destroy</pre>
|
||||||
|
|
||||||
|
<p>The setup step is used to instantiate the component, the initialize step is used to validate configuration
|
||||||
|
parameters, and the run step is used to start the component, i.e. start threads, etc. The stop step stops
|
||||||
|
these threads and also allows the component to be started again. The destroy step destroys the instance and
|
||||||
|
makes it unusable anymore, i.e. shutdown of the agent.</p>
|
||||||
|
|
||||||
|
<p>Each component has its own configuration parameters. A component is registered in the
|
||||||
|
<code>StrolchConfiguration.xml</code> file with a</p>
|
||||||
|
<ul>
|
||||||
|
<li>name</li>
|
||||||
|
<li>api class name</li>
|
||||||
|
<li>implementation class name</li>
|
||||||
|
<li>configuration parameters</li>
|
||||||
|
<li>any required dependencies</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The dependencies is an important feature as the dependencies of a component are always started before the
|
||||||
|
actual component.</p>
|
||||||
|
|
||||||
|
<p>By example of the <code>MailHandler</code> we shall show how a strolch component would be implemented.</p>
|
||||||
|
|
||||||
|
<p>First define an interface:</p>
|
||||||
|
<pre>
|
||||||
|
public interface MailHandler {
|
||||||
|
public void sendMail(String subject, String text, String recipient);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Then implement a concrete <code>MailHandler</code>:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
public class SmtpMailHandler extends StrolchComponent implements MailHandler {
|
||||||
|
|
||||||
|
// instance fields with configuration properties to send the mail
|
||||||
|
|
||||||
|
public SmtpMailHandler(ComponentContainer container, String componentName) {
|
||||||
|
super(container, componentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ComponentConfiguration configuration) throws Exception {
|
||||||
|
|
||||||
|
// store any properties needed from the configuration
|
||||||
|
|
||||||
|
super.initialize(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMail(String subject, String text, String recipient) {
|
||||||
|
|
||||||
|
// send the e-mail using SMTP, or store in stack to send by thread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Now that the component is written, it must be registered on the component, so that it is loaded when the
|
||||||
|
agent is started. For this the <code>StrolchConfiguration.xml</code> file must be modified to include a
|
||||||
|
component element:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<StrolchConfiguration>
|
||||||
|
<env id="dev">
|
||||||
|
...
|
||||||
|
<Component>
|
||||||
|
<name>MailHandler</name>
|
||||||
|
<api>li.strolch.handler.mail.MailHandler</api>
|
||||||
|
<impl>li.strolch.handler.mail.SmtpMailHandler</impl>
|
||||||
|
<Properties>
|
||||||
|
<username>test</username>
|
||||||
|
<password>test</password>
|
||||||
|
<hostName>localhost</hostName>
|
||||||
|
...
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
...
|
||||||
|
</env>
|
||||||
|
</StrolchConfiguration>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Now when the agent is started, the component can be retrieved and used. E.g from inside a
|
||||||
|
<code>Service</code>:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
MailHandler mailHandler = getComponent(MailHandler.class);
|
||||||
|
mailHandler.sendMail("My Subject", "Hello World", "test@test.ch");
|
||||||
|
</pre>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- content here -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
||||||
|
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.container -->
|
||||||
|
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Piwik -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _paq = _paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function () {
|
||||||
|
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
||||||
|
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', 2]);
|
||||||
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||||
|
g.type = 'text/javascript';
|
||||||
|
g.defer = true;
|
||||||
|
g.async = true;
|
||||||
|
g.src = u + 'piwik.js';
|
||||||
|
s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt=""/></p></noscript>
|
||||||
|
<!-- End Piwik Code -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,201 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
<link rel="shortcut icon" href="ico/favicon.ico">
|
||||||
|
|
||||||
|
<title>Strolch: Queries</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="css/custom.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a class="navbar-brand" href="index.html">Strolch</a>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="index.html">Overview</a></li>
|
||||||
|
<li><a href="api.html">API</a></li>
|
||||||
|
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||||
|
<li><a href="downloads.html">Downloads</a></li>
|
||||||
|
<li><a href="development.html">Development</a></li>
|
||||||
|
<li><a href="blog.html">Blog</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">Documentation: Queries</h1>
|
||||||
|
|
||||||
|
<p class="lead page-description">This page discusses Strolch Queries.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<p>As is custom for every framework, querying the model must be possible. Strolch queries are implemented using
|
||||||
|
the <code>StrolchQuery</code> interface and one of its concrete implementations: <code>ResourceQuery</code>,
|
||||||
|
<code>OrderQuery</code>,
|
||||||
|
<code>ActivityQuery</code>.</p>
|
||||||
|
|
||||||
|
<p>A Strolch element always has two identifiers: <code>Type</code> and <code>Id</code>. The type is important as
|
||||||
|
it classifies an element.
|
||||||
|
So if a car and a house would be modelled in Strolch, then those would both be a <code>Resource</code>, but
|
||||||
|
one of type
|
||||||
|
<code>Car</code> and the other of type <code>House</code>. Both would have different parameters.</p>
|
||||||
|
|
||||||
|
<p>Thus one of the inputs for every query is it's type, which is defined as the navigation. It is said that we
|
||||||
|
navigate to the Cars, or Houses. Thus when instantiating a ResourceQuery, pass the navigation to the type of
|
||||||
|
Resource as well. Same applies for Orders and Activities.</p>
|
||||||
|
|
||||||
|
<p>Further input for a StrolchQuery are the selections. These selections get translated into RDBMS
|
||||||
|
<code>WHERE</code>
|
||||||
|
clauses. Selections support boolean operations thus allowing for complex querying.</p>
|
||||||
|
|
||||||
|
<p>StrolchQueries also support Ordering and object transformation. Following classes provide the most used
|
||||||
|
scenarios:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>OrderById</code></li>
|
||||||
|
<li><code>OrderByName</code></li>
|
||||||
|
<li><code>OrderByParameter</code></li>
|
||||||
|
<li><code>*ToDomVisitor</code></li>
|
||||||
|
<li><code>*ToSaxVisitor</code></li>
|
||||||
|
<li><code>*ToJsonVisitor</code></li>
|
||||||
|
<li><code>*ToFlatJsonVisitor</code></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<Resource> query = ResourceQuery.query("Car");
|
||||||
|
query.withAny();
|
||||||
|
List<Resource> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car, order by Name and transform to JSON:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<JsonObject> query = ResourceQuery.query("Car", new ResourceToJsonVisitor(),
|
||||||
|
new OrderByName());
|
||||||
|
query.withAny();
|
||||||
|
List<JsonObject> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>the previous example can also be written as follows:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<JsonObject> query = new ResourceQuery<>();
|
||||||
|
query.setNavigation(new StrolchTypeNavigation("Car"));
|
||||||
|
query.setResourceVisitor(new ResourceToJsonVisitor());
|
||||||
|
query.withAny();
|
||||||
|
List<JsonObject> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car with color blue:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<Resource> query = ResourceQuery.query("Car");
|
||||||
|
query.with(ParameterSelection.stringSelection("parameters", "color", "blue", StringMatchMode.es()));
|
||||||
|
List<Resource> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car which are not blue:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<Resource> query = ResourceQuery.query("Car");
|
||||||
|
query.not(ParameterSelection.stringSelection("parameters", "color", "blue", StringMatchMode.es()));
|
||||||
|
List<Resource> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car with color blue or yellow:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<Resource> query = ResourceQuery.query("Car");
|
||||||
|
query.or().with(
|
||||||
|
ParameterSelection.stringSelection("parameters", "color", "blue", StringMatchMode.es()),
|
||||||
|
ParameterSelection.stringSelection("parameters", "color", "yellow", StringMatchMode.es()));
|
||||||
|
List<Resource> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p>Example: Query all resources of type Car with color blue or yellow owned by Jill:</p>
|
||||||
|
<pre>
|
||||||
|
try (StrolchTransaction tx = openTx()) {
|
||||||
|
ResourceQuery<Resource> query = ResourceQuery.query("Car");
|
||||||
|
|
||||||
|
StringParameterSelection owner = ParameterSelection.stringSelection("parameters", "owner", "Jill", StringMatchMode.es());
|
||||||
|
OrSelection colors = new OrSelection().with(
|
||||||
|
ParameterSelection.stringSelection("parameters", "color", "blue", StringMatchMode.es()),
|
||||||
|
ParameterSelection.stringSelection("parameters", "color", "yellow", StringMatchMode.es()));
|
||||||
|
|
||||||
|
query.and().with(owner, colors);
|
||||||
|
|
||||||
|
List<Resource> cars = tx.doQuery(query);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<!-- content here -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
||||||
|
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.container -->
|
||||||
|
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Piwik -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _paq = _paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function () {
|
||||||
|
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
||||||
|
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', 2]);
|
||||||
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||||
|
g.type = 'text/javascript';
|
||||||
|
g.defer = true;
|
||||||
|
g.async = true;
|
||||||
|
g.src = u + 'piwik.js';
|
||||||
|
s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt=""/></p></noscript>
|
||||||
|
<!-- End Piwik Code -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,221 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
<link rel="shortcut icon" href="ico/favicon.ico">
|
||||||
|
|
||||||
|
<title>Strolch: Realms</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="css/custom.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a class="navbar-brand" href="index.html">Strolch</a>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="index.html">Overview</a></li>
|
||||||
|
<li><a href="api.html">API</a></li>
|
||||||
|
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||||
|
<li><a href="downloads.html">Downloads</a></li>
|
||||||
|
<li><a href="development.html">Development</a></li>
|
||||||
|
<li><a href="blog.html">Blog</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">Documentation: Realms</h1>
|
||||||
|
|
||||||
|
<p class="lead page-description">This page discusses Strolch Realms</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<p>Realms implement multi-mandate capabilities. A Strolch agent can have an arbitrary number of realms
|
||||||
|
configured and each realm has its own persistence configuration, allowing to separate mandates
|
||||||
|
completely.</p>
|
||||||
|
|
||||||
|
A realm can run in one of the following modes:
|
||||||
|
<ul>
|
||||||
|
<li>EMPTY <br/>
|
||||||
|
This is a transient data store mode, where no model changes are persisted - they are only kept in
|
||||||
|
memory. When the Strolch agent is started, this realm is empty as no data is loaded.
|
||||||
|
</li>
|
||||||
|
<li>TRANSIENT <br/>
|
||||||
|
This is the same as EMPTY, but with the difference that when the Strolch agent is started, a model file
|
||||||
|
is parsed and the in-memory realm is populated with the elements parsed from the model file.
|
||||||
|
</li>
|
||||||
|
<li>CACHED <br/>
|
||||||
|
In this mode, all data is stored in-memory, and any changes made are written back to the persistence
|
||||||
|
layer. This allows for fast in-memory qeuries, but makes sure no data is lost when the agent is
|
||||||
|
restarted.
|
||||||
|
</li>
|
||||||
|
<li>TRANSACTIONAL <br/>
|
||||||
|
In this mode no data is kept in-memory and every query, and element retrieval is passed to the
|
||||||
|
persistence layer to be retrieved from the underlying database. This is similar to typical Java
|
||||||
|
applications where JPA is used.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Realms are mostly hidden from a developer as a <code>StrolchTransaction</code> exposes all important
|
||||||
|
operations needed to
|
||||||
|
access Strolch objects. A developer will however need to configure the realms for their specific project. If
|
||||||
|
the project only requires one realm, then the <code>defaultRealm</code> can be used, where the developer
|
||||||
|
only is
|
||||||
|
required to configure the mode and any relevant model file.</p>
|
||||||
|
|
||||||
|
<p>If the mode is CACHED or TRANSACTIONAL, then the <code>PersistenceHandler</code> component is required to be
|
||||||
|
configured,
|
||||||
|
so that the DAOs know how to access the underlying database.</p>
|
||||||
|
|
||||||
|
<p>The configuration in the <code>StrolchConfiguration.xml</code> file is as follows:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<StrolchConfiguration>
|
||||||
|
<env id="dev">
|
||||||
|
...
|
||||||
|
<Component>
|
||||||
|
<name>RealmHandler</name>
|
||||||
|
<api>li.strolch.agent.api.RealmHandler</api>
|
||||||
|
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||||
|
<depends>PrivilegeHandler</depends>
|
||||||
|
<!-- if CACHED or TRANSACTIONAL: -->
|
||||||
|
<!--depends>PersistenceHandler</depends-->
|
||||||
|
<Properties>
|
||||||
|
<dataStoreMode>EMPTY|TRANSIENT|CACHED|TRANSACTIONAL</dataStoreMode>
|
||||||
|
<dataStoreFile>StrolchModel.xml</dataStoreFile>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
...
|
||||||
|
</env>
|
||||||
|
</StrolchConfiguration>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>A multi-realm configuration would be as follows. Note how the <code>defaultRealm</code> is still enabled, and
|
||||||
|
has its
|
||||||
|
configuration as before. Further the PostgreSQL <code>PersistenceHandler</code> is configured to show how
|
||||||
|
the realms are
|
||||||
|
connected to the persistence handler:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<StrolchConfiguration>
|
||||||
|
<env id="dev">
|
||||||
|
...
|
||||||
|
<Component>
|
||||||
|
<name>RealmHandler</name>
|
||||||
|
<api>li.strolch.agent.api.RealmHandler</api>
|
||||||
|
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||||
|
<depends>PrivilegeHandler</depends>
|
||||||
|
<depends>PersistenceHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
<realms>defaultRealm, cachedRealm, transactionalRealm</realms>
|
||||||
|
<dataStoreMode>TRANSIENT</dataStoreMode>
|
||||||
|
<dataStoreFile>DefaultRealm.xml</dataStoreFile>
|
||||||
|
<dataStoreMode.transactionalRealm>TRANSACTIONAL</dataStoreMode.transactionalRealm>
|
||||||
|
<dataStoreMode.cachedRealm>CACHED</dataStoreMode.cachedRealm>
|
||||||
|
<dataStoreMode.emptyRealm>EMPTY</dataStoreMode.emptyRealm>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component>
|
||||||
|
<name>PersistenceHandler</name>
|
||||||
|
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||||
|
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
|
||||||
|
<Properties>
|
||||||
|
<allowSchemaCreation>true</allowSchemaCreation>
|
||||||
|
<allowSchemaDrop>true</allowSchemaDrop>
|
||||||
|
|
||||||
|
<db.url.transactionalRealm>jdbc:postgresql://localhost/testdb1</db.url.transactionalRealm>
|
||||||
|
<db.username.transactionalRealm>testuser1</db.username.transactionalRealm>
|
||||||
|
<db.password.transactionalRealm>test</db.password.transactionalRealm>
|
||||||
|
<db.pool.maximumPoolSize.transactionalRealm>1</db.pool.maximumPoolSize.transactionalRealm>
|
||||||
|
|
||||||
|
<db.url.cachedRealm>jdbc:postgresql://localhost/testdb2</db.url.cachedRealm>
|
||||||
|
<db.username.cachedRealm>testuser2</db.username.cachedRealm>
|
||||||
|
<db.password.cachedRealm>test</db.password.cachedRealm>
|
||||||
|
<db.pool.maximumPoolSize.cachedRealm>1</db.pool.maximumPoolSize.cachedRealm>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
...
|
||||||
|
</env>
|
||||||
|
</StrolchConfiguration>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Accessing a realm is done in multiple ways. Important is to note, that a user should use the
|
||||||
|
<code>StrolchTransaction</code> object, instead of accessing the Realm directly.</p>
|
||||||
|
|
||||||
|
<p>Opening a transaction is done from a <code>Service</code> by calling one of the <code>openTx()</code>-methods.
|
||||||
|
Nevertheless, the realm can be accessed as follows:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
ComponentContainer container = getAgent().getContainer();
|
||||||
|
StrolchRealm realm = container.getRealm(StrolchConstants.DEFAULT_REALM);
|
||||||
|
try(StrolchTransaction tx = realm.openTx()) {
|
||||||
|
Resource resource = tx.getResourceBy("TestType", "MyTestResource");
|
||||||
|
...
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- content here -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
||||||
|
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.container -->
|
||||||
|
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Piwik -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _paq = _paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function () {
|
||||||
|
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
||||||
|
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', 2]);
|
||||||
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||||
|
g.type = 'text/javascript';
|
||||||
|
g.defer = true;
|
||||||
|
g.async = true;
|
||||||
|
g.src = u + 'piwik.js';
|
||||||
|
s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt=""/></p></noscript>
|
||||||
|
<!-- End Piwik Code -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,216 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
<link rel="shortcut icon" href="ico/favicon.ico">
|
||||||
|
|
||||||
|
<title>Strolch: Services and Commands</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="css/custom.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a class="navbar-brand" href="index.html">Strolch</a>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="index.html">Overview</a></li>
|
||||||
|
<li><a href="api.html">API</a></li>
|
||||||
|
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||||
|
<li><a href="downloads.html">Downloads</a></li>
|
||||||
|
<li><a href="development.html">Development</a></li>
|
||||||
|
<li><a href="blog.html">Blog</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">Documentation: Services and Commands</h1>
|
||||||
|
|
||||||
|
<p class="lead page-description">This page discusses Strolch's Services and Commands API</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<p><code>Services</code> are written to implement a specific use-case. <code>Commands</code> are written to
|
||||||
|
implemente re-usable parts of a use-case. The use-case can be abstract e.g. <code>AddResourceService</code>
|
||||||
|
or very specific e.g.
|
||||||
|
<code>CreatePatientService</code>.</p>
|
||||||
|
|
||||||
|
<p>Should the use-case be re-usable in different scenarios, then commands should implement the logic, and the
|
||||||
|
services should then execute the commands. E.g. The <code>CreatePatientService</code> would use a
|
||||||
|
<code>CreatePatientResourceCommand</code> and then use an <code>AddResourceCommand</code> in a single
|
||||||
|
transaction, so that the task of
|
||||||
|
creating the actual Patient Resource can be re-used somewhere else.</p>
|
||||||
|
|
||||||
|
<p>Services extend the abstract class <code>AbstractService</code> and then implement the method
|
||||||
|
<code>internalDoService(ServiceArgument)</code>. AbstractService defines generic template arguments with
|
||||||
|
which the
|
||||||
|
concrete service can define a specific input ServiceArgument class and output ServiceResult class.</p>
|
||||||
|
|
||||||
|
<p>The AbstractService class has multiple helper methods:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>openTx():StrolchTransaction</code> - to open a transaction</li>
|
||||||
|
<li><code>runPrivileged()</code> - to perform a SystemUserAction</li>
|
||||||
|
<li><code>getComponent():V</code> - to retrieve a specific StrolchComponent</li>
|
||||||
|
</ul>
|
||||||
|
<p>there are more - check the JavaDocs</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Commands extend the <code>Command</code> class and then implement the method <code>doCommand()</code>.
|
||||||
|
Commands have helper
|
||||||
|
methods:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>tx()</code> - to get the current transaction</li>
|
||||||
|
<li><code>getPolicy()</code> - to retrieve a policy instance</li>
|
||||||
|
<li><code>runPrivileged()</code> - to perform a SystemUserAction</li>
|
||||||
|
</ul>
|
||||||
|
<p>there are more - check the JavaDocs</p>
|
||||||
|
|
||||||
|
<p>The following code snippets shows how a Service and Command are used to perform the task of adding a new
|
||||||
|
Order. Note how:</p>
|
||||||
|
<ul>
|
||||||
|
<li>the Service opens the transaction</li>
|
||||||
|
<li>adds the command to the TX</li>
|
||||||
|
<li>calls <code>tx.commitOnClose()</code></li>
|
||||||
|
<li>the command validates its input</li>
|
||||||
|
<li>locks the object</li>
|
||||||
|
<li>performs the work</li>
|
||||||
|
<li>and implements an undo</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>AddOrderService:</p>
|
||||||
|
<pre>
|
||||||
|
public class AddOrderService extends AbstractService<AddOrderService.AddOrderArg, ServiceResult> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ServiceResult getResultInstance() {
|
||||||
|
return new ServiceResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ServiceResult internalDoService(AddOrderArg arg) {
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||||
|
AddOrderCommand command = new AddOrderCommand(getContainer(), tx);
|
||||||
|
command.setOrder(arg.order);
|
||||||
|
tx.addCommand(command);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServiceResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AddOrderArg extends ServiceArgument {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public Order order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>AddOrderCommand:</p>
|
||||||
|
<pre>
|
||||||
|
public class AddOrderCommand extends Command {
|
||||||
|
|
||||||
|
private Order order;
|
||||||
|
|
||||||
|
public AddOrderCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
super(container, tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate() {
|
||||||
|
DBC.PRE.assertNotNull("Order may not be null!", this.order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doCommand() {
|
||||||
|
|
||||||
|
tx().lock(this.order);
|
||||||
|
|
||||||
|
OrderMap orderMap = tx().getOrderMap();
|
||||||
|
if (orderMap.hasElement(tx(), this.order.getType(), this.order.getId())) {
|
||||||
|
String msg = MessageFormat.format("The Order {0} already exists!", this.order.getLocator());
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
orderMap.add(tx(), this.order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
if (this.order != null && tx().isRollingBack()) {
|
||||||
|
OrderMap orderMap = tx().getOrderMap();
|
||||||
|
if (orderMap.hasElement(tx(), this.order.getType(), this.order.getId()))
|
||||||
|
orderMap.remove(tx(), this.order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- content here -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
||||||
|
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.container -->
|
||||||
|
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Piwik -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _paq = _paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function () {
|
||||||
|
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
||||||
|
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', 2]);
|
||||||
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||||
|
g.type = 'text/javascript';
|
||||||
|
g.defer = true;
|
||||||
|
g.async = true;
|
||||||
|
g.src = u + 'piwik.js';
|
||||||
|
s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt=""/></p></noscript>
|
||||||
|
<!-- End Piwik Code -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue