http://git-wip-us.apache.org/repos/asf/isis-site/blob/1e14c189/content/guides/ugfun/ugfun.html
----------------------------------------------------------------------
diff --git a/content/guides/ugfun/ugfun.html b/content/guides/ugfun/ugfun.html
index b6e8bbd..c34edad 100644
--- a/content/guides/ugfun/ugfun.html
+++ b/content/guides/ugfun/ugfun.html
@@ -2811,6 +2811,16 @@ mvn clean install</code></pre>
</ul>
</div>
<div class="sectionbody">
+ <div class="admonitionblock note">
+ <table>
+ <tbody>
+ <tr>
+ <td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
+ <td class="content"> this document has been updated for
<code>1.16.0-SNAPSHOT</code>. </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
<div class="paragraph">
<p>The quickest way to get started building an application "for real"
is to run the <code>simpleapp</code> archetype. Like the <a
href="#_ugfun_getting-started_helloworld-archetype">helloworld archetype</a>,
this too will generate a very simple one-class domain model (an entity called
<code>SimpleObject</code> with a couple of properties).</p>
</div>
@@ -2941,20 +2951,29 @@ mvn clean install</code></pre>
<div class="sect3">
<h4 id="_myapp_application">5.2.2. myapp-application</h4>
<div class="paragraph">
- <p>The <code>myapp-application</code> module has three main
packages, the most important being
<code>domainapp.application.manifest</code>.</p>
- </div>
- <div class="paragraph">
- <p>Classes for this package can be found under
<code>src/main/java</code>:</p>
+ <p>The production classes for <code>myapp-application</code> module
(in <code>src/main/java</code>) are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>domainapp/
âââ application/
- âââ manifest/
- âââ DomainAppAppManifest.java
- âââ DomainAppAppManifestBypassSecurity.java
- âââ DomainAppAppManifestWithFixtures.java
- âââ DomainAppAppManifestWithFixturesBypassSecurity.java</pre>
+ âââ DomainAppApplicationModule.java
+ âââ fixture/
+ â âââ DomainAppFixtureScriptsSpecificationProvider.java
+ â âââ scenarios/
+ â âââ DomainAppDemo.java
+ âââ manifest/
+ â âââ DomainAppAppManifest.java
+ â âââ DomainAppAppManifestBypassSecurity.java
+ â âââ DomainAppAppManifestWithFixtures.java
+ â âââ DomainAppAppManifestWithFixturesBypassSecurity.java
+ â âââ menubars.layout.xml
+ âââ services
+ âââ homepage
+ âââ HomePageService.java
+ âââ HomePageViewModel.java
+ âââ HomePageViewModel.layout.xml
+ âââ HomePageViewModel.layout.png</pre>
</div>
</div>
<div class="paragraph">
@@ -2977,20 +2996,17 @@ mvn clean install</code></pre>
</div>
<div class="listingblock">
<div class="content">
- <pre class="CodeRay highlight"><code data-lang="java"><span
class="directive">public</span> <span class="type">class</span> <span
class="class">DomainAppAppManifest</span> <span
class="directive">extends</span> AppManifestAbstract {
+ <pre class="CodeRay highlight"><code data-lang="java"><span
class="directive">public</span> <span class="type">class</span> <span
class="class">DomainAppAppManifest</span> <span
class="directive">extends</span> AppManifestAbstract2 {
- <span class="directive">public</span> <span
class="directive">static</span> <span class="directive">final</span> Builder
BUILDER = Builder.forModules(
- SimpleModuleDomSubmodule.class,
- DomainAppApplicationModuleFixtureSubmodule.class,
- DomainAppApplicationModuleServicesSubmodule.class
- )
+ <span class="directive">public</span> <span
class="directive">static</span> <span class="directive">final</span> Builder
BUILDER = Builder
+ .forModule(<span class="keyword">new</span>
DomainAppApplicationModule())
.withConfigurationPropertiesFile(DomainAppAppManifest.class,
<span class="string"><span class="delimiter">"</span><span
class="content">isis.properties</span><span class="delimiter">"</span></span>,
<span class="string"><span class="delimiter">"</span><span
class="content">authentication_shiro.properties</span><span
class="delimiter">"</span></span>,
<span class="string"><span class="delimiter">"</span><span
class="content">persistor_datanucleus.properties</span><span
class="delimiter">"</span></span>,
<span class="string"><span class="delimiter">"</span><span
class="content">viewer_restfulobjects.properties</span><span
class="delimiter">"</span></span>,
- <span class="string"><span class="delimiter">"</span><span
class="content">viewer_wicket.properties</span><span
class="delimiter">"</span></span>
- ).withAuthMechanism(<span class="string"><span
class="delimiter">"</span><span class="content">shiro</span><span
class="delimiter">"</span></span>);
+ <span class="string"><span class="delimiter">"</span><span
class="content">viewer_wicket.properties</span><span
class="delimiter">"</span></span>)
+ .withAuthMechanism(<span class="string"><span
class="delimiter">"</span><span class="content">shiro</span><span
class="delimiter">"</span></span>);
<span class="directive">public</span> DomainAppAppManifest() {
<span class="local-variable">super</span>(BUILDER);
@@ -2999,32 +3015,35 @@ mvn clean install</code></pre>
</div>
</div>
<div class="paragraph">
- <p>The manifest uses the builder defined by
<code>AppManifestAbstract</code> and references 3 (Isis) modules. These are
simply classes that identify packages to search for entities, domain services
and fixtures; one defined in the <code>myapp-module-simple</code> module, and
two package within the <code>myapp-application</code> module itself (for
additional fixtures and services, namely the home page which weâll discuss
below).</p>
+ <p>The manifest uses the builder defined by
<code>AppManifestAbstract2</code> and references a single top-level (Isis)
module, namely <code>DomainAppApplicationModule</code>:</p>
+ </div>
+ <div class="listingblock">
+ <div class="content">
+ <pre class="CodeRay highlight"><code data-lang="java"><span
class="directive">public</span> <span class="type">class</span> <span
class="class">DomainAppApplicationModule</span> <span
class="directive">extends</span> ModuleAbstract {
+ <span class="annotation">@Override</span>
+ <span class="directive">public</span> <span
class="predefined-type">Set</span><Module> getDependencies() {
+ <span class="keyword">return</span>
Sets.<Module>newHashSet(<span class="keyword">new</span> SimpleModule());
+ }
+}</code></pre>
+ </div>
+ </div>
+ <div class="paragraph">
+ <p>where <code>SimpleModule</code> in defined in the
<code>mypp-module-simple</code> module (below).</p>
</div>
<div class="paragraph">
- <p>The manifest also defines a number of static configuration
files, all loaded from the classpath. Each file contains configuration setting
for a different part of the runtime (<code>isis.properties</code> for the core
framework, shiro for security, datanucleus for the objectstore, and the two
viewers).</p>
+ <p>The primary purpose of the module class is to identify packages
and subpackages that the framework should scan for entities and domain
services. The transitive dependencies between modules are automatically
resolved. The net effect is that all the domain services and entities in this
module as well as those modules referenced are included into the app.</p>
</div>
<div class="paragraph">
- <p>There are also several variations on the app manifest; these can
be used to bootstrap the application with fixtures, or disabling security.</p>
+ <p>Going back to the manifest, it also defines a number of static
configuration files, all loaded from the classpath. Each file contains
configuration setting for a different part of the runtime
(<code>isis.properties</code> for the core framework, shiro for security,
datanucleus for the objectstore, and the two viewers).</p>
</div>
<div class="paragraph">
- <p>The next package is
<code>domainapp.application.services</code>:</p>
+ <p>The <code>menubars.layout.xml</code> file also resides in the
same package as the manifest; this defines the menubar structure.</p>
</div>
- <div class="listingblock">
- <div class="content">
- <pre>domainapp/
-âââ application/
- âââ services/
- âââ DomainAppApplicationModuleServicesSubmodule.java
- âââ homepage/
- âââ HomePageService.java
- âââ HomePageViewModel.java
- âââ HomePageViewModel.layout.xml
- âââ HomePageViewModel.png</pre>
- </div>
+ <div class="paragraph">
+ <p>There are also several variations on the app manifest; these can
be used to bootstrap the application with fixtures, or disabling security.</p>
</div>
<div class="paragraph">
- <p>The <code>DomainAppApplicationModuleServicesSubmodule</code>
class is referenced as a module within the app manifest, meaning that the
<code>HomePageService</code> that sits in a subpackage underneath it is picked
up automatically. This domain service simply has a single action annotated with
<code>@HomePage</code>:</p>
+ <p>The <code>domainapp.application.services</code> package contains
the <code>HomePageService</code> domain service. This simply has a single
action annotated with <code>@HomePage</code>:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -3039,26 +3058,7 @@ mvn clean install</code></pre>
<p>which returns the <code>HomePageViewModel</code> for use as the
home page. The <code>HomePageViewModel</code> itself just renders a collection
of <code>SimpleObject</code>s in a list
(<code>HomePageViewModel.layout.xml</code> defines the UI layout).</p>
</div>
<div class="paragraph">
- <p>The final package in the application module is
<code>domainapp.application.fixture</code>:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre>domainapp/
-âââ application/
- âââ fixture/
- âââ DomainAppApplicationModuleFixtureSubmodule.java
- âââ DomainAppFixtureScriptsSpecificationProvider.java
- âââ scenarios/
- â âââ DomainAppDemo.java
- âââ teardown/
- âââ DomainAppTearDown.java</pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The important class here is <code>DomainAppDemo</code>, which is
a fixture script that can be used to setup the application with some dummy
data. This is used in the app itself when running in prototype mode (against an
in-memory database), and can also be used by integration tests.</p>
- </div>
- <div class="paragraph">
- <p>The <code>DomainAppApplicationModuleFixtureSubmodule</code> is
referenced by the app manifest, meaning that the framework knows to search for
domain services and fixtures under its package.</p>
+ <p>The final package in the application module is
<code>domainapp.application.fixture</code>. The important class here is
<code>DomainAppDemo</code>, a fixture script that can be used to setup the
application with some dummy data. This is used in the app itself when running
in prototype mode (against an in-memory database), and can also be used by
integration tests.</p>
</div>
<div class="paragraph">
<p>There is in fact also a domain service defined here, namely
<code>DomainAppFixtureScriptsSpecificationProvider</code>. This is just used to
configure the run fixture script menu item shown on the "Prototyping" menu.</p>
@@ -3080,6 +3080,9 @@ mvn clean install</code></pre>
</div>
</div>
<div class="paragraph">
+ <p>Here the <code>BootstrappingGlue</code> glue class inherits from
the frameworkâs <code>CukeGlueBootstrappingAbstract</code> class, and
bootstraps using the <code>DomainAppApplicationModule</code> mentioned
above.</p>
+ </div>
+ <div class="paragraph">
<p>There is just one feature file:
<code>SimpleObjectSpec_listAllAndCreate.feature</code>, which is pretty
simple:</p>
</div>
<div class="listingblock">
@@ -3087,18 +3090,17 @@ mvn clean install</code></pre>
<pre class="CodeRay highlight"><code
data-lang="feature">@DomainAppDemo
Feature: List and Create New Simple Objects
- @integration
Scenario: Existing simple objects can be listed and new ones created
- Given there are initially 3 simple objects
+ Given there are initially 10 simple objects
When I create a new simple object
- Then there are 4 simple objects</code></pre>
+ Then there are 11 simple objects</code></pre>
</div>
</div>
<div class="paragraph">
- <p>The <code>@DomainAppDemo</code> annotation causes the
<code>DomainAppDemo</code> fixture script to be run; this sets up 3 objects.
The "glue" defines both in the <code>myapp-application</code> module and in the
<code>myapp-module-simple</code> module</p>
+ <p>The <code>@DomainAppDemo</code> annotation causes the
<code>DomainAppDemo</code> fixture script to be run; this is the purpose of the
<code>CatalogOfFixturesGlue</code> glue class.</p>
</div>
<div class="paragraph">
- <p>The tests themselves are run by the
<code>RunIntegBddSpecs.java</code> class; this is standard Cucumber
bootstrapping.</p>
+ <p>The specs themselves are run by the
<code>RunIntegBddSpecs.java</code> class, which specifies which packages to
search for "glue". This is just standard Cucumber bootstrapping.</p>
</div>
<div class="paragraph">
<p>The integration tests meanwhile are in
<code>domainapp.application.integtests</code>:</p>
@@ -3113,10 +3115,10 @@ Feature: List and Create New Simple Objects
</div>
</div>
<div class="paragraph">
- <p>The <code>Smoke_IntegTest</code> inherits
<code>DomainAppIntegTestAbstract</code>, with the latter bootstrapping the
framework using the <code>DomainAppAppManifest</code> already discussed that is
used for running the application itself. Moreover, the
<code>Smoke_IntegTest</code> uses the same <code>DomainAppDemo</code> fixture
script. The application and the smoke tests therefore run with the exact same
state, making debugging easy.</p>
+ <p>The <code>Smoke_IntegTest</code> inherits
<code>DomainAppIntegTestAbstract</code>, which in turn inherits from
<code>IntegrationTestAbstract3</code> and uses the
<code>DomainAppApplicationModule</code> previously discussed. Moreover, the
<code>Smoke_IntegTest</code> uses the same <code>DomainAppDemo</code> fixture
script. The application and the smoke tests therefore run with the exact same
state, making debugging easy.</p>
</div>
<div class="paragraph">
- <p>The BDD specs and integration tests are named according to the
naming convention required by the "surefire" mavenmixin that configures the
maven surefire plugin.</p>
+ <p>With regard to the naming of these various BDD specs and
integration tests, they follow the naming convention required by the (non-ASF)
<a href="http://github.com/danhaywood/java-mavenmixin-surefire">"surefire"
mavenmixin</a> that configures the maven surefire plugin.</p>
</div>
</div>
<div class="sect3">
@@ -3148,9 +3150,9 @@ Feature: List and Create New Simple Objects
<pre>domainapp/
âââ modules/
âââ simple/
+ âââ SimpleModule.java
âââ SimpleModuleManifest.java
âââ dom/
- â âââ SimpleModuleDomSubmodule.java
â âââ impl/
â âââ SimpleObject.java
â âââ SimpleObject.layout.xml
@@ -3158,39 +3160,45 @@ Feature: List and Create New Simple Objects
â âââ SimpleObjectMenu.java
â âââ SimpleObjectRepository.java
âââ fixture/
- âââ SimpleModuleFixtureSubmodule.java
- âââ scenario/
- â âââ CreateSimpleObjects.java
- â âââ SimpleObjectData.java
- âââ teardown/
- âââ SimpleModuleTearDown.java
+ âââ SimpleObject_persona.java
+ âââ SimpleObjectBuilder.java
META-INF/
âââ persistence.xml</pre>
</div>
</div>
<div class="paragraph">
- <p>Note once more that the module class
(<code>SimpleModuleDomSubmodule</code>) is referenced in the app manifest
class, meaning that all the entities, domain services and fixtures within it
are included within the application. Speaking of whichâ¦â</p>
- </div>
- <div class="paragraph">
- <p><code>SimpleObject</code> is the (one-and-only) domain entity
defined (with <code>SimpleObject.layout.xml</code> defines its layout in the
UI). In contrast to the helloworld app, though, there are <em>two</em>
associated domain services:</p>
+ <p>The <code>SimpleModule</code> is the (single) module class
referenced from the previously discussed
<code>DomainAppApplicationModule</code>, meaning that all the entities, domain
services and fixtures within it are included within the application.</p>
</div>
<div class="ulist">
<ul>
- <li> <p><code>SimpleObjectMenu</code> domain serviceâs actions
appear as menu items, to create and find <code>SimpleObject</code>s. This
delegates in turn to:</p> </li>
- <li> <p><code>SimpleObjectRepository</code>, which is a repository
domain service that actually does the fetching and creating in the
database.</p> </li>
+ <li> <p><code>SimpleObject</code> is the (one-and-only) domain
entity defined (with <code>SimpleObject.layout.xml</code> defines its layout in
the UI).</p> </li>
+ <li> <p><code>SimpleObjects</code> domain serviceâs whos actions
appear as menu items and which acts as a repository to create and find
<code>SimpleObject</code>s.</p> </li>
</ul>
</div>
<div class="paragraph">
- <p>Splitting out domain services like this is quite common since it
allows more flexibility with the menu structure.</p>
+ <p>The <code>SimpleModule</code> class also defines a teardown
fixture, automatically called by integration tests.</p>
</div>
- <div class="paragraph">
- <p>The module also defines its own manifest,
<code>SimpleModuleManifest</code>. This is used to run Isis' own <a
href="../rgmvn/rgmvn.html">maven plugin</a> to <a
href="../rgmvn/rgmvn.html#_rgmvn_validate">validate</a> the domain object model
(eg to detect orphaned supported methods).</p>
+ <div class="listingblock">
+ <div class="content">
+ <pre class="CodeRay highlight"><code data-lang="java"><span
class="directive">public</span> <span class="type">class</span> <span
class="class">SimpleModule</span> <span class="directive">extends</span>
ModuleAbstract {
+ <span class="annotation">@Override</span>
+ <span class="directive">public</span> FixtureScript getTeardownFixture() {
+ <span class="keyword">return</span> <span class="keyword">new</span>
TeardownFixtureAbstract2() {
+ <span class="annotation">@Override</span>
+ <span class="directive">protected</span> <span
class="type">void</span> execute(ExecutionContext ec) {
+ deleteFrom(SimpleObject.class);
+ }
+ };
+ }
+ ...
+}</code></pre>
+ </div>
</div>
<div class="paragraph">
- <p>Under <code>fixture.scenario</code> subpackage are fixture
scripts that are used by integration tests and by the demo fixture script
defined in the <code>myapp-application</code> module (discussed above).</p>
+ <p>In the <code>fixture</code> subpackage is the
<code>SimpleObject_persona</code> "persona" which uses the corresponding
<code>SimpleObjectBuilder</code> builder script; further discussion on this
pattern <a
href="../ugtst/ugtst.html#_ugtst_fixture-scripts_api-and-usage_persona-and-builders">here</a>.
These fixtures are also used by "local" integration tests, which reside under
<code>src/test/java</code>.</p>
</div>
<div class="paragraph">
- <p>These fixtures are also used by "local" integration tests, which
reside under <code>src/test/java</code>. There are also unit tests and "glue"
for the BDD specs:</p>
+ <p>There are also unit tests and "glue" for the BDD specs:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -3214,7 +3222,10 @@ META-INF/
<p>The simpleapp application has both "local" integration tests
(defined within the <code>myapp-module-simple</code> module) and also "global"
integration tests (the "smoke" tests in <code>myapp-application</code> module).
Thereâs a role for both: local integration tests should fully exercise the
module but may need to mock out collaborations between modules, while global
integration tests exercise the whole application (but an over-reliance on these
can cause test run times to bloat).</p>
</div>
<div class="paragraph">
- <p>The surefire mavenmixin plugin configured in the
<code>pom.xml</code> establishes the convention that integration tests include
the name "IntegTest", while unit tests contain merely "Test". The
<code>SimpleModuleIntegTestAbstract</code> also uses the
<code>SimpleAppManifest</code> (mentioned above) to define a "cut-down" version
of the application that just bootstraps the simple module.</p>
+ <p>With regard to the naming of these various BDD specs and
integration tests, they follow the naming convention required by the (non-ASF)
<a href="http://github.com/danhaywood/java-mavenmixin-surefire">"surefire"
mavenmixin</a> that configures the maven surefire plugin. Integration tests
include the name "IntegTest", while unit tests contain merely "Test".</p>
+ </div>
+ <div class="paragraph">
+ <p>The module also defines its own manifest,
<code>SimpleModuleManifest</code>. This is used to run Isis' own <a
href="../rgmvn/rgmvn.html">maven plugin</a> to <a
href="../rgmvn/rgmvn.html#_rgmvn_validate">validate</a> the domain object model
(eg to detect orphaned supported methods).</p>
</div>
</div>
<div class="sect3">
@@ -3234,7 +3245,7 @@ META-INF/
</div>
</div>
<div class="paragraph">
- <p>The <code>DomainApplication</code> is required to bootstrap the
Wicket viewer (it is configured in <code>WEB-INF/web.xml</code>). Internally it
uses Google Guice to configure various static resources served up by
Wicket:</p>
+ <p>The <code>DomainApplication</code> is required to bootstrap the
Wicket viewer (it is configured in <code>WEB-INF/web.xml</code>, discussed
below). Within <code>DomainApplication</code> is the bootstrapping of the
Wicket viewer. Internally it uses Google Guice to configure various static
resources served up by Wicket:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -3277,7 +3288,33 @@ WEB-INF/
</div>
</div>
<div class="paragraph">
- <p>Most important of these is <code>WEB-INF/web.xml</code>, which
bootstraps both the Wicket viewer and the Restful Objects viewer (the REST API
derived from the domain object model).</p>
+ <p>Most important of these is <code>WEB-INF/web.xml</code>, which
bootstraps both the Wicket viewer and the Restful Objects viewer (the REST API
derived from the domain object model):</p>
+ </div>
+ <div class="listingblock">
+ <div class="title">
+ web.xml
+ </div>
+ <div class="content">
+ <pre class="CodeRay highlight"><code data-lang="xml"><span
class="tag"><web-app</span> <span class="attribute-name">...</span><span
class="tag">></span>
+ ...
+ <span class="tag"><filter></span>
+ <span class="tag"><filter-name></span>WicketFilter<span
class="tag"></filter-name></span>
+ <span
class="tag"><filter-class></span>org.apache.wicket.protocol.http.WicketFilter<span
class="tag"></filter-class></span>
+ <span class="tag"><init-param></span>
+ <span class="tag"><param-name></span>applicationClassName<span
class="tag"></param-name></span>
+ <span
class="tag"><param-value></span>domainapp.webapp.DomainApplication<span
class="tag"></param-value></span>
+ <span class="tag"></init-param></span>
+ <span class="tag"></filter></span>
+ ...
+ <span class="tag"><context-param></span>
+ <span class="tag"><param-name></span>javax.ws.rs.Application<span
class="tag"></param-name></span>
+ <span class="tag"><param-value></span>
+ org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplication
+ <span class="tag"></param-value></span>
+ <span class="tag"></context-param></span>
+ ...
+<span class="tag"></web-app></span></code></pre>
+ </div>
</div>
<div class="paragraph">
<p>The <code>about/index.html</code> is the page shown at the root
of the package, providing links to either the Wicket viewer or to the Swagger
UI. In a production application this is usually replaced with a page that does
an HTTP 302 redirect to the Wicket viewer.</p>