blob: bf97b53e84ddbad686d268c4dd7eebd98debbc75 [file] [log] [blame]
//////////////////////
* Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
//////////////////////
[[core-api-application,Application]]
= Application =
There is one and only one Application instance per Zest™ runtime instance. But there is nothing preventing code to
create additional Zest™ Runtime instances inside the same JVM. However, these runtimes are isolated from each other.
The main purpose of the Application structure artifact is to keep everything in the same box, and allowing us to
navigate the Structure. So, from a client code perspective, the Application is of no use, other than being part of
bring Zest™ to life. Zest™ doesn't start automatically and can be run in most environments, by requiring that the
bootstrapping of Zest™ is done by client code. We call this the Bootstrap Phase. The code in the custom bootstrapper
will need to access additional Jars from the regular domain code, and we strongly recommend that you make this
separation in your project as well.
== Assembly ==
<<core-bootstrap-assembly>> is the part of the bootstrap phase where the application Structure is declared (programmatically). The
Assembly will be consumed by the ApplicationBuilder, which produces an ApplicationInstance. This instance does not
contain any custom objects, and is fully serializable. All the application structure has been built, all the layers
and modules been wired up, and all the sub-composite structures are in place to quickly instantiate the various parts
of the application.
=== Initialization ===
At this point, where an ApplicationInstance exists, it is possible to initialize the application components with
instances created in, data computed in or received from, the controlling bootstrap code.
=== Activation ===
Once the initialization phase is complete, the bootstrap controller will call the ApplicationInstance.activate()
method to start things up.
=== Bootstrap Phase Summary ===
Recap of sequence;
* Create, obtain or lookup Assemblers.
* Establish the application structures.
* Create a Zest™ Runtime instance.
* Create an ApplicationAssemblyFactory.
* Create an ApplicationFactory.
* Call ApplicationFactory.newApplication() to create an ApplicationContext.
* Call ApplicationContext.newApplicationInstance() to create an ApplicationInstance.
* Do the initialization of the application.
* Call activate() on the ApplicationInstance.
== Singleton Assembler ==
For really small applications, demos, testcases and so forth, it doesn't make sense to create a elaborate Application
structure. For this purpose, there is a convenient short-cut to establish a single Layer, single Module application.
The full code looks like this;
[snippet,java]
-----------
source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
tag=application1
-----------
= Single Module Layering =
Behind the scenes of the SingletonAssembler a little bit more elaborate bootstrap sequence is happening. The code below
shows what is the actual required sequence to start up Zest.
[snippet,java]
-----------
source=core/bootstrap/src/main/java/org/qi4j/bootstrap/SingletonAssembler.java
tag=actual
-----------
In the above example we are only creating an Application with a single Layer and a single Module in that Layer. This is
derived from the fact that the factory.newApplicationAssembly() method takes a single Assembler argument.
The Assembler.assemble( ModuleAssembly assembly ) method is called when the Zest™ Runtime needs to populate the
ModuleAssembly with its Composites, Objects, Services and other information.
== "Pancake" Layering ==
Another standard setup is applications consisting of a small number of Layers that are directly on top of each other
(with out bypassing, forking and converging Layers), you can supply a Assembler[][][], with Layer in the first index,
Module in the second index and any number of Assembler instances in the last index. This will look like;
[snippet,java]
-----------
source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
tag=application2
-----------
The array initialization feature in Java is used to give us a semi-visual idea of the actual application structure. It
has been commented to highlight this further. Also note that one can pass any number of Assembler instances to each
Module. This is an important aspect of subsystem creation and re-use.
== Full Layering ==
Finally, we can assemble the Application by manually building up the Modules and Layers. This allow for a totally
free structure, as long as the rules for no cyclic reference of the Layers are kept.
[snippet,java]
-----------
source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
tag=application3
-----------