You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2017/10/10 06:52:58 UTC

[2/4] isis-site git commit: ISIS-1465: adds section describing the structure of the helloworld app

http://git-wip-us.apache.org/repos/asf/isis-site/blob/39e88f84/content/guides/htg.html
----------------------------------------------------------------------
diff --git a/content/guides/htg.html b/content/guides/htg.html
index dd3374f..846abc9 100644
--- a/content/guides/htg.html
+++ b/content/guides/htg.html
@@ -248,7 +248,6 @@ table.CodeRay td.code>pre{padding:0}
        <a href="#" id="search-results-clear">clear</a> 
       </div> 
      </div> 
-     <span class="pdf-link"><a href="htg.pdf"><img src="../../images/PDF-50.png"></a></span> 
      <div class="page-title"> 
       <h1>Hints &amp; Tips Guide</h1> 
      </div> 

http://git-wip-us.apache.org/repos/asf/isis-site/blob/39e88f84/content/guides/htg.pdf
----------------------------------------------------------------------
diff --git a/content/guides/htg.pdf b/content/guides/htg.pdf
index 55a4bb4..3df5aa6 100644
--- a/content/guides/htg.pdf
+++ b/content/guides/htg.pdf
@@ -4,8 +4,8 @@
 << /Title (Hints & Tips Guide)
 /Creator (Asciidoctor PDF 1.5.0.alpha.11, based on Prawn 1.3.0)
 /Producer (Asciidoctor PDF 1.5.0.alpha.11, based on Prawn 1.3.0)
-/CreationDate (D:20171010004928+01'00')
-/ModDate (D:20171010004928+01'00')
+/CreationDate (D:20171010074655+01'00')
+/ModDate (D:20171010074655+01'00')
 >>
 endobj
 2 0 obj

http://git-wip-us.apache.org/repos/asf/isis-site/blob/39e88f84/content/guides/ugfun/ugfun.html
----------------------------------------------------------------------
diff --git a/content/guides/ugfun/ugfun.html b/content/guides/ugfun/ugfun.html
index 642c397..ae6c0fb 100644
--- a/content/guides/ugfun/ugfun.html
+++ b/content/guides/ugfun/ugfun.html
@@ -2234,7 +2234,292 @@ mvn clean install</code></pre>
           </div> 
          </div> 
          <div class="sect3"> 
-          <h4 id="__ugfun_getting-started_helloworld-archetype_running-the-app">4.2.3. Running the App</h4> 
+          <h4 id="__ugfun_getting-started_helloworld-archetype_structure-of-the-app">4.2.3. Structure of the App</h4> 
+          <div class="paragraph"> 
+           <p>As noted above, the application generated by the helloworld archetype is deliberately simplified, with everything contained within a single Maven module.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Under <code>src/main/java</code> we have:</p> 
+          </div> 
+          <div class="listingblock"> 
+           <div class="content"> 
+            <pre>domainapp/
+├── application/
+│   ├── HelloWorldAppManifest.java
+│   └── isis.properties
+├── dom/
+│   ├── HelloWorldModule.java
+│   └── impl/
+│       ├── HelloWorldObject.java
+│       ├── HelloWorldObject.layout.xml
+│       ├── HelloWorldObject.png
+│       └── HelloWorldObjects.java
+└── app/
+    ├── HelloWorldApplication.java
+    └── welcome.html</pre> 
+           </div> 
+          </div> 
+          <div class="paragraph"> 
+           <p>For simplicity, all the Java source files generated by the archetype are placed in a <code>domainapp</code> top-level package.</p> 
+          </div> 
+          <div class="admonitionblock tip"> 
+           <table> 
+            <tbody>
+             <tr> 
+              <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> 
+              <td class="content"> 
+               <div class="paragraph"> 
+                <p>While it’s more conventional to use the inverse domain name for package (eg <code>com.mycompany.myapp</code>, that’s only really appropriate for library code that will be released for reuse by multiple applications in different orgnisations (eg open source).</p> 
+               </div> 
+               <div class="paragraph"> 
+                <p>For internal application though this is less of a concern; indeed, avoiding using the domain name means that if the company is taken over then nothing needs be changed.</p> 
+               </div> 
+               <div class="paragraph"> 
+                <p>Of course, just are free to move the classes to a different package if you wish.</p> 
+               </div> </td> 
+             </tr> 
+            </tbody>
+           </table> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In <code>domainapp.application</code> package is <code>HelloWorldAppManifest</code>, which implements the <code>AppManifest</code> interface defined by the Apache Isis applib. The class is only small, so is worth showing here in its entirety:</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">HelloWorldAppManifest</span> <span class="directive">extends</span> AppManifestAbstract {
+    <span class="directive">public</span> <span class="directive">static</span> <span class="directive">final</span> Builder BUILDER = Builder
+            .forModules(HelloWorldModule.class)
+            .withConfigurationPropertiesFile(HelloWorldAppManifest.class, <span class="string"><span class="delimiter">"</span><span class="content">isis.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> HelloWorldAppManifest() {
+        <span class="local-variable">super</span>(BUILDER);
+    }
+}</code></pre> 
+           </div> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Rather than implement <code>AppManifest</code> directly, <code>HelloWorldAppManifest</code> uses the builder provided by the convenience <code>AppManifestAbstract</code>); as you’ll find when you work on bigger applications, it’s common to have variations around the app manifest, so the builder makes it easy to create these variations without lots of boilerplate.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>For now, we see that (using the builder) the app manifest defines three things:</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p>a list of modules - there’s just one, <code>HelloWorldModule</code> for this class</p> </li> 
+            <li> <p>the location of a configuration file, <code>isis.properties</code>, read in as a resource from the classpath</p> </li> 
+            <li> <p>specifying an authentication/authorisation mechanism, in this case Apache Shiro integration.</p> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In Apache Isis a module is simply an empty class, which is used simply to obtain a package name. The framework uses classpath scanning to find certain classes; rather than scan the entire classpath it limits its search to the package(s) obtained from the modules.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>The packages are scanned to identify three types of classes:</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p>all entities.</p> 
+             <div class="paragraph"> 
+              <p>These are entities that are annotated with <code>@javax.jdo.annotations.PersistenceCapable</code>. These are passed through to the JDO (DataNucleus) object store, in order to create database mappings from the entities to relational tables</p> 
+             </div> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In the helloworld application, the only entity is <code>HelloWorldObject</code>.</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p>all domain services</p> 
+             <div class="paragraph"> 
+              <p>These are classes that are annotated with the framework’s <code>@DomainService</code> annotation. Depending on their nature, services are used to build up the menu, or are available to call programmatically, eg repositories. The framework instantiates an instance of each and will automatically inject the services into other domain objects and services.</p> 
+             </div> 
+             <div class="paragraph"> 
+              <p>In the helloworld application, the only domain service is <code>HelloWorldObjects</code>. This appears in the menu, and also acts as a repository for the <code>HelloWorldObject</code> entity.</p> 
+             </div> </li> 
+            <li> <p>all fixture scripts</p> 
+             <div class="paragraph"> 
+              <p>These are classes that extend from the applib <code>FixtureScript</code> class, and are used to setup the database when running in prototype mode (against an in-memory database.</p> 
+             </div> 
+             <div class="paragraph"> 
+              <p>The helloworld application doesn’t provide any examples of these.</p> 
+             </div> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>The app manifest also identifies the <code>isis.properties</code> file (in the same package as <code>HelloWorldAppManifest</code>) as containing various configuration options. The helloworld application uses these for settings that are unlikely to change and so are loaded as a static resource from the classpath.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>You’ll find that there’s another file called <code>isis.properties</code> that’s in <code>WEB-INF/isis.properties</code>. This also provides configuration options (the framework simply combines them) but those in <code>WEB-INF/isis.properties</code> are restricted to settings that are likely to change from environment to environment, most notably JDBC URL connection strings. Separating these out makes it easy to reconfigure the application to run against different databases in different environments (dev, test, production etc).</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Finally, the app manifest identifies Apache Shiro for authentication and authorisation. Shiro in turn is configured using the <code>WEB-INF/shiro.ini</code> file.</p> 
+          </div> 
+          <div class="admonitionblock tip"> 
+           <table> 
+            <tbody>
+             <tr> 
+              <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> 
+              <td class="content"> 
+               <div class="paragraph"> 
+                <p>The security integration provided by Apache Isis and Shiro is quite sophisticated; to get started though you can just login using:</p> 
+               </div> 
+               <div class="ulist"> 
+                <ul> 
+                 <li> <p>username: <code>sven</code></p> </li> 
+                 <li> <p>password: <code>pass</code></p> </li> 
+                </ul> 
+               </div> </td> 
+             </tr> 
+            </tbody>
+           </table> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In the <code>domainapp.dom</code> module ("dom" stands for "domain object model") is the <code>HelloWorldModule</code>:</p> 
+          </div> 
+          <div class="listingblock"> 
+           <div class="content"> 
+            <pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">package</span> <span class="namespace">domainapp.dom</span>;
+<span class="directive">public</span> <span class="directive">final</span> <span class="type">class</span> <span class="class">HelloWorldModule</span> {
+    <span class="directive">private</span> HelloWorldModule(){}
+}</code></pre> 
+           </div> 
+          </div> 
+          <div class="paragraph"> 
+           <p>As already explained, this is simply used by the app manifest to identify "domainapp.dom" as the package to scan to locate entities (<code>HelloWorldObject</code>), services (<code>HelloWorldObjects</code>) and fixture scripts (none provided).</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In the <code>domainapp.dom.impl</code> we have the classes that actually comprise our domain object. These are a little large to list here in their entirety, but it’s worth calling out:</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p><code>HelloWorldObject</code>:</p> 
+             <div class="ulist"> 
+              <ul> 
+               <li> <p>is annotated with a bunch of JDO annotations, <code>@PersistenceCapable</code> being the most important.</p> 
+                <div class="paragraph"> 
+                 <p>This annotation is what identifies the class as an entity, so that Apache Isis passes through to JDO/DataNucleus during bootstrapping (to create the ORM mappings).</p> 
+                </div> </li> 
+               <li> <p>is also annotated with Isis' own <code>@DomainObject</code>.</p> 
+                <div class="paragraph"> 
+                 <p>This isn’t mandatory, but since entities are the real building blocks on which Isis applications are built, it’s very common to use this annotation.</p> 
+                </div> </li> 
+               <li> <p>also uses various Project Lombok annotations to remove boilerplate.</p> </li> 
+              </ul> 
+             </div> </li> 
+            <li> <p><code>HelloWorldObject.layout.xml</code> defines the layout of the properties and actions of the <code>HelloWorldObject</code> (this class doesn’t have any collections).</p> </li> 
+            <li> <p><code>HelloWorldObject.png</code> is used as an icon for any instances of the domain object shown in the (Wicket) viewer</p> </li> 
+            <li> <p><code>HelloWorldObjects</code> is a domain service by virtue of the fact that it is annotated with Isis' <code>@DomainService</code>.</p> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>This acts as both a menu (the <code>@DomainService#nature</code> attribute) and also a repository to find/create instances of <code>HelloWorldObject</code>.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Finally, in the <code>domainapp.webapp</code> we have <code>HelloWorldApplication</code>. This 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> 
+          </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">HelloWorldApplication</span> <span class="directive">extends</span> IsisWicketApplication {
+    ...
+    <span class="annotation">@Override</span>
+    <span class="directive">protected</span> Module newIsisWicketModule() {
+        <span class="directive">final</span> Module isisDefaults = <span class="local-variable">super</span>.newIsisWicketModule();
+        <span class="directive">final</span> Module overrides = <span class="keyword">new</span> AbstractModule() {
+            <span class="annotation">@Override</span>
+            <span class="directive">protected</span> <span class="type">void</span> configure() {
+                ...
+            }
+        };
+        <span class="keyword">return</span> Modules.override(isisDefaults).with(overrides);
+    }
+}</code></pre> 
+           </div> 
+          </div> 
+          <div class="paragraph"> 
+           <p>The <code>configure()</code> method is the place to change the name of the application for example, or to change the initial about and welcome messages. The text of the welcome page shown by the Wicket viewer can be found in <code>welcome.html</code>, loaded from the classpath and in the same package as <code>HelloWorldApplication</code>.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Under <code>src/main/webapp</code> we have various resources that are used to configure the webapp, or that are served up by the running webapp:</p> 
+          </div> 
+          <div class="listingblock"> 
+           <div class="content"> 
+            <pre>about/
+└── index.html
+css/
+└── application.css
+scripts/
+└── application.js
+swagger-ui/
+WEB-INF/
+├── isis.properties
+├── logging.properties
+├── shiro.ini
+└── web.xml</pre> 
+           </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> 
+          </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 Swagger. In a production application this is usually replaced with a page that does an HTTP 302 redirect to the Wicket viewer.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In <code>css/application.css</code> you can use to customise CSS, typically to highlight certain fields or states. The pages generated by the Wicket viewer have plenty of CSS classes to target. You can also implement the <code>cssClass()</code> method in each domain object to provide additional CSS classes to target.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Similarly, in <code>scripts/application.js</code> you have the option to add arbitrary Javascript. JQuery is available by default.</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>In <code>swagger-ui</code> is a copy of the Swagger 2.x UI classes, preconfigured to run against the REST API exposed by the Restful Objects viewer. This can be useful for developing custom applications, and is accessible from the initial page (served up by <code>about/index.html</code>).</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Finally in <code>WEB-INF</code> we have the standard <code>web.xml</code> (already briefly discussed) along with several other files:</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p><code>isis.properties</code> contains further configuration settings for Apache Isis itself.</p> 
+             <div class="paragraph"> 
+              <p>(As already discsussed), these are in addition to the configuration files found in the <code>isis.properties</code> that lives alongside the <code>HelloWorldAppManifest</code> class. Those in the WEB-INF/isis.properties file are those that are likely to change when running the application in different environments.</p> 
+             </div> </li> 
+            <li> <p><code>logging.properties</code> configures log4j.</p> 
+             <div class="paragraph"> 
+              <p>The framework is configured to use slf4j running against log4j.</p> 
+             </div> </li> 
+            <li> <p><code>shiro.ini</code> configures Apache Shiro, used for security (authentication and authorisation)</p> </li> 
+            <li> <p><code>web.xml</code> configures the Wicket viewer and Restful Objects viewer. It also sets up various filters for serving up static resources with caching HTTP headers.</p> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Under <code>src/test/java</code> we have:</p> 
+          </div> 
+          <div class="listingblock"> 
+           <div class="content"> 
+            <pre>domainapp
+└── dom
+    └── impl
+        ├── HelloWorldObjectTest_delete.java
+        └── HelloWorldObjectTest_updateName.java</pre> 
+           </div> 
+          </div> 
+          <div class="paragraph"> 
+           <p>These are very simple unit tests of <code>HelloWorldObject</code>. They use JMock as the mocking library (with some minor extensions provided by Apache Isis itself).</p> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Finally, at the root directory we of course have the <code>pom.xml</code>. Some notable points:</p> 
+          </div> 
+          <div class="ulist"> 
+           <ul> 
+            <li> <p>since this module generates a WAR file, the <code>pom.xml</code> uses <code>&lt;packaging&gt;war&lt;/packaging&gt;</code></p> </li> 
+            <li> <p>maven mixins are used to remove boilerplate configuration of standard plugins (resources, compile, jar etc), for the DataNucleus enhancer, for surefire (tests), and for running the application using jetty plugin</p> </li> 
+           </ul> 
+          </div> 
+          <div class="paragraph"> 
+           <p>Now you know your way around the code generated by the archetype, lets see how to run it.</p> 
+          </div> 
+         </div> 
+         <div class="sect3"> 
+          <h4 id="__ugfun_getting-started_helloworld-archetype_running-the-app">4.2.4. Running the App</h4> 
           <div class="paragraph"> 
            <p>The <code>helloworld</code> archetype generates a single WAR file, configured to run both the <a href="../ugvw/ugvw.html">Wicket viewer</a> and the <a href="../ugvro/ugvro.html">Restful Objects viewer</a>. The archetype also configures the DataNucleus/JDO Objectstore to use an in-memory HSQLDB connection.</p> 
           </div> 
@@ -2290,7 +2575,7 @@ mvn clean install</code></pre>
           </div> 
          </div> 
          <div class="sect3"> 
-          <h4 id="__ugfun_getting-started_helloworld-archetype_using-the-app">4.2.4. Using the App</h4> 
+          <h4 id="__ugfun_getting-started_helloworld-archetype_using-the-app">4.2.5. Using the App</h4> 
           <div class="paragraph"> 
            <p>When you start the app, you’ll be presented with a welcome page from which you can access the webapp using either the <a href="../ugvw/ugvw.html">Wicket viewer</a> or the <a href="../ugvro/ugvro.html">Restful Objects viewer</a>:</p> 
           </div> 
@@ -2495,9 +2780,9 @@ mvn clean install</code></pre>
           </div> 
          </div> 
          <div class="sect3"> 
-          <h4 id="__ugfun_getting-started_helloworld-archetype_experimenting">4.2.5. Experimenting</h4> 
+          <h4 id="__ugfun_getting-started_helloworld-archetype_experimenting">4.2.6. Experimenting with the App</h4> 
           <div class="paragraph"> 
-           <p>Once you are familiar with the generated app, try modifying it. There is plenty of guidance on this site; start with this guide (fundamentals) and then look at the other guides available the main <a href="../../documentation.html">documentation</a> page.</p> 
+           <p>Once you are familiar with the generated app, try modifying it. There is plenty more guidance on this site; start with this guide (fundamentals) and then look at the other guides available the main <a href="../../documentation.html">documentation</a> page.</p> 
           </div> 
           <div class="paragraph"> 
            <p>If you use IntelliJ IDEA or Eclipse, do also install the <a href="../dg/dg.html#<em>dg_ide_intellij_live-templates">live templates (for IntelliJ)</a> / <a href="../dg/dg.html#</em>dg_ide_eclipse_editor-templates">editor templates (for Eclipse)</a>; these will help you follow the Apache Isis naming conventions.</p> 
@@ -2507,7 +2792,7 @@ mvn clean install</code></pre>
           </div> 
          </div> 
          <div class="sect3"> 
-          <h4 id="__ugfun_getting-started_helloworld-archetype_moving-on">4.2.6. Moving on</h4> 
+          <h4 id="__ugfun_getting-started_helloworld-archetype_moving-on">4.2.7. Moving on</h4> 
           <div class="paragraph"> 
            <p>When you are ready to start working on your own app, we <em>don’t</em> recommend building on top of the helloworld app.</p> 
           </div>