| ////////////////////// |
| * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved. |
| * Copyright (c) 2012, Paul Merlin. |
| * |
| * 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-bootstrap-assembly,Assembly]] |
| = Core Bootstrap = |
| |
| [devstatus] |
| -------------- |
| source=core/bootstrap/dev-status.xml |
| -------------- |
| |
| Zest™ has a distinct bootstrap phase, also known as the _Assembly_ of an application, where the applications structure |
| is defined programmatically. Once all the layers, modules and all the composite types in each module have been defined |
| the model is instantiated into an application. This enables the entire _structure_ system in Zest, where types "belongs" |
| to a module and visibility rules define default behaviors, enforcement of architectural integrity and much more. |
| |
| The _assembly_ is preceeded by the creation of the _Zest Runtime_. The _assembly_ can be declared fully by defining |
| all modules and layers, and how the layers are sitting on top of each other, OR one can utilize one of the two |
| convenience assemblies, one for a _pancake_ pattern, where all layers are top on each other, or one with a single module |
| in a single layer, useful for small applications, spikes and tests. The +bootstrap+ system has several ways to acheive |
| this, and they are listed below in <<core-bootstrap-assembly-layered>>. |
| |
| During _assembly_, the application (JVM level) architecture and the application model is defined. You define which |
| layers exist and how they relate to each other. For each layer, you define which modules it contains. And for each |
| module, you define which composites are in it, and what are the visibility rules for each of these composites. |
| |
| You can also; |
| |
| * Define default values for properties. |
| * Add additional interfaces to composites dynamically. |
| * Add concerns, mixins, constraints and side effects dynamically. |
| * Set _meta information_ on defined types. |
| * Import external services to be available as Zest™ services. |
| * Tag services with markers |
| |
| include::../../build/docs/buildinfo/artifact.txt[] |
| |
| |
| == Defining Objects == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=objects |
| -------------- |
| |
| |
| == Defining Transients == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=transients |
| -------------- |
| |
| |
| == Defining Values == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=values |
| -------------- |
| |
| |
| == Defining Entities == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=entities |
| -------------- |
| |
| |
| == Defining Services == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=services |
| -------------- |
| |
| === Tagging Services === |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=tagged-services |
| -------------- |
| |
| === Importing external Services === |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=imported-services |
| -------------- |
| |
| == Defining default values for Properties == |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=properties-defaults |
| -------------- |
| |
| == Adding additional interfaces to composites == |
| |
| |
| == Adding concerns, mixins, constraints and side effects == |
| |
| |
| == Setting meta information on assembled types == |
| |
| |
| == Using Assemblers == |
| Many <<libraries,libraries>> and <<extensions,extensions>> provides a cookie-cutter _Assembler_, to simplify the set up |
| of such component. Often these are suitable, but sometimes they won't fit the application in hand, in which case the |
| source code at least provides information of what is needed for the component to be used. |
| |
| Assemblers are typically just instantiated and then call the assemble() method with the ModuleAssembly instance, |
| such as; |
| |
| [snippet,java] |
| -------------- |
| source=libraries/rest-server/src/test/java/org/apache/zest/library/rest/server/DocumentationSupport.java |
| tag=UsingAssembler |
| -------------- |
| |
| == Defining an Entity Store == |
| Defining an _Entity Store_ is in principle as simple as defining a ServiceComposite implementing the EntityStore |
| interface. The problem is that most Entity Stores require <<core-api-service-configuration>>, and configuration requires an |
| Entity Store. This chicken-and-egg problem is resolved by having an entity store available that does not require any |
| <<core-api-service-configuration>>. Many _Assemblers_ for entity store implementations uses the MemoryEntityStore, and |
| effectively leaves the configuration in the properties file where <<core-api-service-configuration>> bootstraps from. It is |
| possible to chain this, so that for instance the Neo4J Entity Store uses the Preferences Entity Store for its |
| configuration, and the Preferences Entity Store uses the Memory Entity Store (i.e. the properties file). |
| |
| The point is that the entity store used for the configuration of the primary entity store used in the application is |
| that it must not be visible to the application itself. Sometimes it is easier to put a Memory Entity Store in the |
| same module, with Visibility set to _module_. Sometimes it makes sense to have an additional Configuration layer below |
| the infrastructure layer, which has this setup. |
| |
| As mentioned above, most entity stores defines a reasonable default _Assembler_, possibly with some constructor |
| arguments or methods to define certain aspects. An example is the popular JdbmEntityStore, which _Assembler_ can be |
| used like; |
| |
| [snippet,java] |
| -------------- |
| source=extensions/entitystore-jdbm/src/test/java/org/apache/zest/entitystore/jdbm/DocumentationSupport.java |
| tag=UsingAssembler |
| -------------- |
| |
| |
| [[core-bootstrap-assembly-layered,Layered Application Assembler]] |
| == Layered Application Assembler (RECOMMENDED!) == |
| |
| In 2.1, a new way to instantiate Zest™ applications was introduced. It starts with subclassing the |
| +LayeredApplicationAssembler+, and implementing the +assembleLayers()+ method. |
| |
| In the +assembleLayers()+ method, one is epected to either call the +createLayer()+ method in the super class |
| with the Class of the LayerAssembler, |
| |
| [source,java] |
| ---- |
| LayerAssembly domainLayer = createLayer( DomainLayer.class ); |
| ---- |
| |
| OR manually instantiate and call the LayerAssembler. |
| |
| [source,java] |
| ---- |
| LayerAssembly infraLayer = new InfrastructureLayer( configModule ).assemble( assembly.layer( InfrastructureLayer.NAME )); |
| ---- |
| |
| This is to make the normal case as simple as possible, yet allow the special needs that occssionally surfaces. |
| |
| Each LayerAssembler implementation may optionally extend the +LayeredLayerAssembler+, to get access to the |
| +createModule()+ method, which again simplifies the creation of modules in the +assemble()+ method. |
| |
| [source,java] |
| ---- |
| createModule( layer, InvoicingModule.class ); |
| ---- |
| |
| +ModuleAssembler+ implementations typically use +Assembler+ classes to put together, or call the +entities()+, |
| +values()+ methods described elsewhere on this page. There is no superclass to use. |
| |
| +ModuleAssembler+ implementations should have a name ending with "Module" and the naming will insert a human-readable |
| space within the module name, e.g. +InvoicingModule+ will be named "Invoicing Module". |
| |
| For example code, see the tutorial <<howto-assemble-application>>. |
| |
| |
| == Singleton Assembler == |
| Every Zest™ runtime instance consist of One Application, with one or more Layers and one or more Modules in each Layer. |
| So the minimal application is still one layer with one module. This is not recommended other than for testing purposes |
| and really trivial applications. |
| |
| Let's take a closer look at how it is put together. |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=singleton |
| -------------- |
| |
| Once the SingletonAssembler constructor returns, the Zest™ application is up and running. |
| |
| The SingletonAssembler also makes common system resources available from the bootstrap code, such as |
| Module, UnitOfWorkFactory and others. This is possible since there is only one Module. |
| |
| == Application Builder == |
| Some applications has no need for runtime determination of the exact application structure, and no need for |
| advanced alterations to a staright-forward layered application structure. By using the +ApplicationBuilder+ |
| it is possible to define the application structure from a JSON document, AND call the provided +main()+ class, |
| taking the JSON document as input on +System.in+. |
| |
| The format of the JSON document, directly reflects the application structure, such as |
| [source,json] |
| ---- |
| { |
| "name": "Build from JSON test.", |
| "layers": [ |
| { "name": "service", "uses": [ "domain", "config"] }, |
| { "name": "donfig" }, |
| { |
| "name": "domain", |
| "modules" : [ |
| { |
| "name" : "Invoicing", |
| "assemblers" : [ |
| "org.hedhman.niclas.bootstrap.InvoicingAssembler" |
| ] |
| } |
| ] |
| } |
| ] |
| } |
| ---- |
| |
| At the moment, the JSON format only support +Assembler+ classes to do the work. |
| |
| Another way to use the +ApplicationBuilder+ is to subclass it, optionally use the +configureFromJSON()+ method, |
| and then programmatically enhance the structure before calling +newApplication()+. |
| |
| == Pancake Assembly == |
| There is one case that stands out as a common case, and forms a reasonable middle-ground. It is where each layer sits |
| exactly on top of each other layer, like pancakes. Each layer will only use the layer directly below and only that |
| layer. For this case we have a convenience setup. You create an Assembler[][][], where the outer-most array is each |
| layer, the middle array is the modules in each layer, and the last array is a set of assemblers needed to put the |
| things togather. |
| |
| Let's look at an example; |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=pancake |
| -------------- |
| |
| == Full Assembly == |
| Full Assembly means that you have the opportunity to create any layer/module hierarchy that are within the rules of the |
| Zest™ runtime. It requires more support in your code to be useful, and the example below is by no means a recommended way |
| to organize large application assemblies. |
| |
| In principle, you first start the Zest™ runtime, call newApplication with an ApplicationAssembler instance and call |
| activate() on the returned application. The ApplicationAssembler instance will be called with an |
| ApplicationAssemblyFactory, which is used to create an ApplicationAssembly describing the application structure. |
| |
| [snippet,java] |
| -------------- |
| source=core/bootstrap/src/test/java/org/apache/zest/bootstrap/DocumentationSupport.java |
| tag=full |
| -------------- |
| |
| |