strolch/li.strolch.website/www.strolch.li/documentation-runtime.html

395 lines
20 KiB
HTML

<!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: Runtime Configuration</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="tutorial.html">Tutorial</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: Runtime</h1>
<p class="lead page-description">This page discusses the Strolch Runtime configuration.</p>
</div>
<div class="content">
<p>A Strolch runtime configuration comprises two parts: a configuration part, and a model part. The
configuration are files located in the <code>..config/</code> folder, and the model are files located in the
<code>../data</code> folder.</p>
<p>In an absolute minimal configuration, the Strolch runtime requires the following folder structure:</p>
<ul>
<li><code>../config/</code>
<dl>
<dt>StrolchConfiguration.xml</dt>
<dd>&rarr; configures the Strolch agent</dd>
<dt>PrivilegeConfig.xml</dt>
<dd>&rarr; configures user management</dd>
<dt>PrivilegeUsers.xml</dt>
<dd>&rarr; contains the users in an XML based user management file</dd>
<dt>PrivilegeRoles.xml</dt>
<dd>&rarr; contains the roles and privileges in an XML based user management</dd>
</dl>
</li>
</ul>
<h2>StrolchConfiguration.xml</h2>
<p>The <i>StrolchConfiguration.xml</i> file configures the Strolch agent. The <i>StrolchConfiguration.xml</i>
defines the following:</p>
<ul>
<li><code>&lt;StrolchConfiguration&gt;</code> root element</li>
<li><code>&lt;env id="xxx"&gt;</code> different environments with the possibility of having a global
environment for configuration valid in multiple environments.
<ul>
<li><code>&lt;Runtime&gt;</code> element which defines the agents name and a few other properties
e.g. <code>locale</code> and <code>verbose</code>:
<ul>
<li><code>&lt;applicationName&gt;</code> the agent's name</li>
<li><code>&lt;Properties&gt;</code></li>
<li><code>&lt;locale&gt;</code> the agent's internal locale for log messages etc.</li>
<li><code>&lt;verbose&gt;</code> the logging level for some internal logging. (Logging is
mostly done using log4j over slf4j)
</li>
</ul>
</li>
</ul>
</li>
<li><code>&lt;Component&gt;</code> elements for each component used in the agent. A component is configured
by defining the following child elements:
<ul>
<li><code>&lt;name&gt;</code> the name of the component, use when defining dependencies between
components. The name is mostly set to the simple name of the interface
of the component
</li>
<li><code>&lt;api&gt;</code> the full class name to the interface of the component. During runtime
this interface will be used to access the component e.g.: <code>ServiceHandler
svcHandler
=
agent.getContainer().getComponent(ServiceHandler.class);</code>
</li>
<li><code>&lt;impl&gt;</code> the full class name of the concrete implementation of the component.
During initialization this class will be instantiated and registered
under the component name and interface. This class must extend the
class <code>li.strolch.agent.api.StrolchComponent</code>
</li>
<li><code>&lt;depends&gt;</code> any number of these elements, where the content is the name of
another component, on which this component depends. Depending
components are initialized and started after the component they
depend on and are stopped and destroyed before
</li>
<li><code>&lt;Properties&gt;</code>
<ul>
<li><code>&lt;...&gt;</code> any number of properties which the component requires. The
element's name will be the key with which the value can be
accessed at runtime.
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><b>Note:</b> When a property is missing, and the component has a hard coded default value, then when the
component is initialized, the use of the default value and its key is logged. This makes it easy
to see which new properties can be configured. Should the component not define a default value,
then the component will thrown an exception on initialization. In this case it can be a good
moment to read the JavaDoc (or source code) for the component in question to see how it is
configured.</p>
<h2 id="privilegeConfig">Privilege Configuration</h2>
<p>In Strolch authentication and authorization is baked in. To open a transaction, and thus access the Strolch
model, a Certificate object is required, which means the user has been authenticated and possibly
authorized.</p>
<p>The <i>PrivilegeConfig.xml</i> defines the following:</p>
<ul>
<li><code>&lt;Privilege&gt;</code> root element
<ul>
<li><code>&lt;Container&gt;</code> configures the individual Privilege components
<ul>
<li><code>&lt;Parameters&gt;</code> base configuration properties for Privilege</li>
<li><code>&lt;EncryptionHandler&gt;</code> configures the hashing algorithms and other
encryption specific configuration
</li>
<li><code>&lt;PersistenceHandler&gt;</code> configures the persistence of the roles and
users
</li>
<li><code>&lt;UserChallengeHandler&gt;</code> configures a challenge handler so that a user
can reset their password. The default
challenge handler is the <code>li.strolch.privilege.handler.MailUserChallengeHandler</code>
which sends a challenge to the user's defined
e-mail address.
</li>
<li><code>&lt;SsoHandler&gt;</code> the SSO Handler is used to implement a SingleSignOn and
can be used to start a session using a LDAP token, etc.
There is no default implementation as this is project
specific.
</li>
</ul>
</li>
<li><code>&lt;Policies&gt;</code> configures the available privilege policies at runtime, the name
is referenced from the model file
</li>
</ul>
</li>
</ul>
<p>The <code>PrivilegeUsers.xml</code> and <code>PrivilegeRoles.xml</code> define the users and roles and is
used when in <code>PrvilegeConfig.xml</code> the <code>PersistenceHandler</code> is set to <code>ch.eitchnet.privilege.handler.XmlPersistenceHandler</code>:
</p>
<ul>
<li><code>&lt;Users&gt;</code> configures all users
<ul>
<li><code>&lt;User&gt;</code> configures a specific user
<ul>
<li><code>&lt;Firstname&gt;</code> configures a user's first name</li>
<li><code>&lt;Lastname&gt;</code> configure a user's last name</li>
<li><code>&lt;State&gt;</code> configures the user's state, see <code>ch.eitchnet.privilege.model.UserState</code>
</li>
<li><code>&lt;Locale&gt;</code> configure the user's locale</li>
<li><code>&lt;Roles&gt;</code> configures the user's roles
<ul>
<li><code>&lt;Role&gt;</code> adds a role to the user</li>
</ul>
</li>
<li><code>&lt;Properties&gt;</code> configures user specific properties. What properties are
used is not specified and is dependent on the concrete
agent
<ul>
<li><code>&lt;Property&gt;</code> defines a single property</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><code>&lt;Roles&gt;</code> configures all roles
<ul>
<li><code>&lt;Role&gt;</code> configures a specific role
<ul>
<li><code>&lt;Privilege&gt;</code> configures a specific privilege for this role
<ul>
<li><code>&lt;AllAllowed&gt;</code> if set to true, then defines that all values
associated with this privilege are allowed
</li>
<li><code>&lt;Allow&gt;</code> defines one allowed value for this privilege
</li>
<li><code>&lt;Deny&gt;</code> defines one denied value for this privilege
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Implementing a StrolchComponent</h2>
<p>Implementing a strolch component requires an interface, which defines the component's API and a concrete
class which implements the interface and extends the class <code>StrolchComponent</code>.</p>
<p>The StrolchComponent class adds the state model to the class, which transitions as follows:<br /> <code>UNDEFINED
=&gt;
SETUP
=&gt;
INITIALIZED
=>
STARTED
&lt;=&gt;
STOPPED
=>
DESTROYED</code>
</p>
<p>Components can switch between <code>STARTED</code> and <code>STOPPED</code>, but once <code>DESTROYED</code>
no further state change is possible. The component's state is changed by changes to the agent's lifecycle.
</p>
<p>A component's state is changed by a call to the appropriate method on the component, override the methods as
necessary. Note that it is good practice that the <code>initialize()</code>-method is used to get all the
configuration properties, and that they should there be evaluated and that the method so return quickly. The
<code>start()</code>-method is called after the agent's initialization and should be where additional
threads are started. Correctly implementing these methods allows to quickly detect a wrongly configured
agent, which might take longer to start for whatever reason.</p>
<p>The following shows a basic implementation of a component on the basis of a post initializer (a component
which performs some actions in its <code>start()</code>-method which should be done after everything else is
started in the agent).</p>
<pre>
public class SimplePostInitializer
extends StrolchComponent
implements PostInitializer {
public SimplePostInitializer(ComponentContainer container,
String componentName) {
super(container, componentName);
}
@Override
public void initialize(ComponentConfiguration configuration) {
// do some initialization, validate configuration values, etc.
// now call super, to update state
super.initialize(configuration);
}
@Override
public void start() {
// start any threads, or perform long running start work
// now call super, to update state
super.start();
}
@Override
public void stop() {
// stop threads and timers, but be ready to start again
// now call super, to update state
super.stop();
}
@Override
public void destroy() {
// destroy this component, release all resources and don't worry about
// being called to start again now call super, to update state
super.destroy();
}
}
</pre>
<p>The new component would then be registered in the <code>StrolchConfiguration.xml</code> as follows:</p>
<pre>
&lt;StrolchConfiguration&gt;
&lt;env id="..."&gt;
...
&lt;Component&gt;
&lt;name&gt;SimplePostInitializer&lt;/name&gt;
&lt;api&gt;li.strolch.agent.api.PostInitializer&lt;/api&gt;
&lt;impl&gt;li.strolch.documentation.SimplePostInitializer&lt;/impl&gt;
&lt;/Component&gt;
...
&lt;/env&gt;
&lt;/StrolchConfiguration&gt;
</pre>
<p>And can be access at runtime using:</p>
<pre>
PostInitializer postInitializer = getContainer().getComponent(PostInitializer.class);
</pre>
<h2>Starting the agent</h2>
<p>When a Strolch runtime is started, then the root path to the runtime configuration must be passed. In Java
this is done by calling:</p>
<pre>
StrolchAgent agent = new StrolchAgent();
agent.setup(environment, rootPath);
agent.initialize();
agent.start();
</pre>
<p>In Servlet 3.0 applications one would implement the <code>javax.servlet.ServletContextListener</code>
interface, add the <code>@WebListener</code> annotation to the class and in the
<code>contextInitialized()</code>-method start Strolch:</p>
<pre>
String realPath = sce.getServletContext().getRealPath("/WEB-INF");
String environment = StrolchEnvironment.getEnvironmentFromEnvProperties(pathF);
this.agent = new StrolchAgent();
this.agent.setup(environment, new File(realPath));
this.agent.initialize();
this.agent.start();
</pre>
<!-- content here -->
</div>
<!-- /.content -->
<div id="footer">
<div class="container">
<p class="text-muted">&copy; 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 xsd 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>