/
ten-minutes-intro.html
168 lines (144 loc) · 13.7 KB
/
ten-minutes-intro.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Qi4j in 10 minutes</title><link rel="stylesheet" href="css/style.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /><link rel="home" href="index.html" title="" /><link rel="up" href="tutorials.html" title="Tutorials" /><link rel="prev" href="two-minutes-intro.html" title="Qi4j in 2 minutes" /><link rel="next" href="thirty-minutes-intro.html" title="Qi4j in 30 minutes" />
<!-- favicon -->
<link rel="shortcut icon" href="http://qi4j.org/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="icon" href="http://qi4j.org/favicon.ico" type="image/x-icon" />
<!-- style -->
<link href="css/shCore.css" rel="stylesheet" type="text/css" />
<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" />
<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" />
<link href="css/qi4j.css" rel="stylesheet" type="text/css" />
<!-- Syntax Highlighter -->
<script type="text/javascript" src="js/shCore.js"></script>
<script type="text/javascript" src="js/shBrushJava.js"></script>
<script type="text/javascript" src="js/shBrushScala.js"></script>
<script type="text/javascript" src="js/shBrushJScript.js"></script>
<script type="text/javascript" src="js/shBrushBash.js"></script>
<script type="text/javascript" src="js/shBrushPlain.js"></script>
<script type="text/javascript" src="js/shBrushXml.js"></script>
<script type="text/javascript" src="js/shBrushGroovy.js"></script>
<script type="text/javascript" src="js/shBrushPython.js"></script>
<script type="text/javascript" src="js/shBrushRuby.js"></script>
<script type="text/javascript" src="js/shBrushCSharp.js"></script>
<script type="text/javascript">
SyntaxHighlighter.defaults['tab-size'] = 4;
SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all()
</script>
<!-- JQuery -->
<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>
<!-- Image Scaler -->
<script type="text/javascript" src="js/imagescaler.js"></script>
<!-- Table Styler -->
<script type="text/javascript" src="js/tablestyler.js"></script>
<!-- Qi4j WebSite Progressive Enhancement -->
<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script>
<script type="text/javascript" src="js/progressive-enhancement.js"></script>
<!-- Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-3118496-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="top-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl><dt><span class="section"><a href="index.html#home">Qi4j</a></span></dt><dt><span class="section"><a href="intro.html">Introduction</a></span></dt><dt><span class="section"><span xmlns="" href="tutorials.html">Tutorials</span></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="sub-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl><dt><span class="section"><a href="tutorials.html#_overview">Overview</a></span></dt><dt><span class="section"><a href="two-minutes-intro.html">Qi4j in 2 minutes</a></span></dt><dt><span class="section"><span xmlns="" href="ten-minutes-intro.html">Qi4j in 10 minutes</span></span></dt><dt><span class="section"><a href="thirty-minutes-intro.html">Qi4j in 30 minutes</a></span></dt><dt><span class="section"><a href="two-hours-intro.html">Qi4j in 2 hours</a></span></dt><dt><span class="section"><a href="howto-depend-on-qi4j.html">Depend on Qi4j in your build</a></span></dt><dt><span class="section"><a href="howto-assemble-application.html">Assemble an Application</a></span></dt><dt><span class="section"><a href="tut-composites.html">Transient Composites Tutorial</a></span></dt><dt><span class="section"><a href="tut-services.html">Services Composites Tutorial</a></span></dt><dt><span class="section"><a href="howto-contextual-fragments.html">Use contextual fragments</a></span></dt><dt><span class="section"><a href="howto-leverage-properties.html">Leverage Properties</a></span></dt><dt><span class="section"><a href="howto-create-constraint.html">Create a Constraint</a></span></dt><dt><span class="section"><a href="howto-create-concern.html">Create a Concern</a></span></dt><dt><span class="section"><a href="howto-create-sideeffect.html">Create a SideEffect</a></span></dt><dt><span class="section"><a href="howto-create-entity.html">Create an Entity</a></span></dt><dt><span class="section"><a href="howto-configure-service.html">Configure a Service</a></span></dt><dt><span class="section"><a href="howto-use-io.html">Use I/O API</a></span></dt><dt><span class="section"><a href="build-system.html">Build System</a></span></dt><dt><span class="section"><a href="community-docs.html">Writing Qi4j Documentation</a></span></dt></dl></div></div><div class="section" title="Qi4j in 10 minutes"><div class="titlepage"><div><div><h3 class="title"><a id="ten-minutes-intro"></a>Qi4j in 10 minutes</h3></div></div></div><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>Theses tutorials are based on actual code found in the <code class="literal">tutorials/</code> directory of the
<a class="ulink" href="http://qi4j.org/downloads.html" target="_top">Qi4j SDK sources</a>. You should start your favorite editor and find the code related to
this tutorial, run it and play with it.</p></div><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem">
Qi4j does not introduce any new programming language, no additional compilers needed and all your existing tools
work just like before. It is pure Java.
</li><li class="listitem">
Qi4j works with Composites.
</li><li class="listitem">
The equivalent of an Object instance in OOP, is a Composite instance in Qi4j.
</li><li class="listitem">
Composites are constructed from Fragments.
</li><li class="listitem">
Fragments are Mixins, Concerns, Constraints and SideEffects.
</li><li class="listitem">
Only Mixins carry Composite state. The others are shared between Composite instances.
</li></ul></div><p>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:</p><div class="table"><a id="idp18919664"></a><p class="title"><b>Table 2. Artifact</b></p><div class="table-contents"><table summary="Artifact" border="1"><colgroup><col /><col /><col /></colgroup><thead><tr><th align="left" valign="top">Group ID</th><th align="left" valign="top">Artifact ID</th><th align="left" valign="top">Version</th></tr></thead><tbody><tr><td align="left" valign="top"><p>org.qi4j.core</p></td><td align="left" valign="top"><p>org.qi4j.core.runtime</p></td><td align="left" valign="top"><p>2.0</p></td></tr></tbody></table></div></div><br class="table-break" /><p>Moreover, you’ll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available
implementations listed in the <a class="xref" href="extensions.html" title="Extensions">Extensions</a> section.</p><p>See the <a class="xref" href="howto-depend-on-qi4j.html" title="Depend on Qi4j in your build">Depend on Qi4j in your build</a> tutorial for details.</p><p>Composition is done with Java interfaces and Annotations. Example;</p><pre class="programlisting brush: java">@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } )
public interface OrderEntity
extends Order, Confirmable,
HasSequenceNumber, HasCustomer, HasLineItems,
EntityComposite
{
}
</pre><p>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;</p><pre class="programlisting brush: java">public class InventoryConcern extends ConcernOf<Order>
implements Order
{
@Service
private InventoryService inventory;
@Override
public void addLineItem( LineItem item )
{
String productCode = item.productCode().get();
int quantity = item.quantity().get();
inventory.remove( productCode, quantity );
next.addLineItem( item );
}
@Override
public void removeLineItem( LineItem item )
{
String productCode = item.productCode().get();
int quantity = item.quantity().get();
inventory.add( productCode, quantity );
next.removeLineItem( item );
}
}
</pre><p>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 <code class="literal">next</code> field, which is
set up by the Qi4j runtime and points to the next fragment in the call stack.</p><p>We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Qi4j
also supports dependency injection via constructors and methods.</p><p>The above example is obviously doing persistence, and we have no code handling this. But Qi4j supports persistence
directly in its Core, and it is taken care of by Qi4j, since it is declared as an EntityComposite.
Nothing else is needed, provided that the Qi4j 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.</p><p>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.</p><p>Now, let’s say that we want to send a mail to <a class="ulink" href="mailto:sales@mycompany.com" target="_top">sales@mycompany.com</a> 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;</p><pre class="programlisting brush: java">@SideEffects( MailNotifySideEffect.class )
@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } )
public interface OrderEntity
extends Order, Confirmable,
HasSequenceNumber, HasCustomer, HasLineItems,
EntityComposite
{
</pre><p>The SideEffect implementation is fairly simple.</p><pre class="programlisting brush: java">public abstract class MailNotifySideEffect extends SideEffectOf<Confirmable>
implements Confirmable
{
@Service
private MailService mailer;
@This
private HasLineItems hasItems;
@This
private HasCustomer hasCustomer;
@Override
public void confirm()
{
StringBuilder builder = new StringBuilder();
builder.append( "An Order has been made.\n\n\n" );
builder.append( "Customer:" );
builder.append( hasCustomer.name().get() );
builder.append( "\n\nItems ordered:\n" );
for( LineItem item : hasItems.lineItems().get() )
{
builder.append( item.name().get() );
builder.append( " : " );
builder.append( item.quantity().get() );
builder.append( "\n" );
}
mailer.send( "sales@mycompany.com", builder.toString() );
}
}
</pre><p>The MailService is dependency injected, as we have seen before.</p><p>@This is telling Qi4j that the SideEffect needs a reference to the Composite instance that it belongs to.</p><p>By asking for both the HasCustomer and the HasLineItems types, we get type-safety and don’t need to bother with casts.
In fact, Qi4j will ensure that you can’t even cast the <code class="literal">hasCustomer</code> instance to the HasLineItems type.</p><p>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.</p><p>So, build the report, send it via the MailService.</p><div class="section" title="Conclusion"><div class="titlepage"><div><div><h4 class="title"><a id="_conclusion"></a>Conclusion</h4></div></div></div><p>In this short introduction, we have covered the essence of Qi4j. 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.</p></div></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="footer">(c) 2012 The Qi4j Community</div></body></html>