blob: dc86b5f097771608b2777684a254d7cf79a84d67 [file] [log] [blame]
///////////////////////////////////////////////////////////////
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
///////////////////////////////////////////////////////////////
[[ten-minutes-intro,Zest™ in 10 minutes]]
= Zest™ in 10 minutes =
TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
this tutorial, run it and play with it.
* Zest™ does not introduce any new programming language, no additional compilers needed and all your existing tools
work just like before. It is pure Java.
* Zest™ works with Composites.
* The equivalent of an Object instance in OOP, is a Composite instance in Zest™.
* Composites are constructed from Fragments.
* Fragments are Mixins, Concerns, Constraints and SideEffects.
* Only Mixins carry Composite state. The others are shared between Composite instances.
If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
include::../../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
Moreover, you'll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available
implementations listed in the <<extensions>> section.
See the <<howto-depend-on-zest>> tutorial for details.
Composition is done with Java interfaces and Annotations. Example;
[snippet,java]
-----------
source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
tag=mainClass
-----------
This Composite is potentially complete. The Composite interface has a Mixin declared which is always present, the
PropertyMixin, which will handle all properties we use. The two Concerns are interceptors that are placed on the
methods that they declare, for instance;
[snippet,java]
-----------
source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java
tag=allClass
-----------
Extending the ConcernOf is a convenience mechanism, instead of an explicit @ConcernFor annotation on a private field,
which can be used in rare occasions when you are not able to extend. This base class defines the `next` field, which is
set up by the Zest™ runtime and points to the next fragment in the call stack.
We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Zest™
also supports dependency injection via constructors and methods.
The above example is obviously doing persistence, and we have no code handling this. But Zest™ supports persistence
directly in its Core, and it is taken care of by Zest™, since it is declared as an EntityComposite.
Nothing else is needed, provided that the Zest™ Runtime has been setup with one or more persisted EntityStores. But
we have a naming convention that EntityComposites have "Entity" as the suffix in its name.
There are other built-in Composite subtypes as well, such as ValueComposite and ServiceComposite. This distinction helps
both to communicate intent as well as having more precisely defined functionality.
Now, let's say that we want to send a mail to sales@mycompany.com when the order is confirmed. This is a SideEffect, and
will execute after the Constraints, Concerns and Mixins. We add the SideEffect to the OrderEntity;
[snippet,java]
-----------
source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
tag=sideEffect
-----------
The SideEffect implementation is fairly simple.
[snippet,java]
-----------
source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java
tag=allClass
-----------
The MailService is dependency injected, as we have seen before.
@This is telling Zest™ that the SideEffect needs a reference to the Composite instance that it belongs to.
By asking for both the HasCustomer and the HasLineItems types, we get type-safety and don't need to bother with casts.
In fact, Zest™ will ensure that you can't even cast the `hasCustomer` instance to the HasLineItems type.
By not referencing the aggregated interface OrderEntity, we reduce the coupling of this SideEffect and it can be used
in any other Composite where the HasCustomer and HasLineItems combination is used, for instance in an InvoiceEntity.
So, build the report, send it via the MailService.
== Conclusion ==
In this short introduction, we have covered the essence of Zest™. We have looked at what is a Composite, seen some of the
Fragments in action, and how simple it is to turn a Composite into a persisted Composite, known as an EntityComposite.