/
isis-core.xml
3156 lines (2630 loc) · 143 KB
/
isis-core.xml
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"file:./src/docbkx/dtd-4.5/docbookx.dtd">
<!--
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.
-->
<book>
<bookinfo>
<title><?eval ${docbkxGuideTitle}?></title>
<subtitle><?eval ${docbkxGuideSubTitle}?></subtitle>
<releaseinfo><?eval ${project.version}?></releaseinfo>
<authorgroup>
<author>
<firstname>Dan</firstname>
<surname>Haywood</surname>
</author>
<author>
<firstname>Robert</firstname>
<surname>Matthews</surname>
</author>
</authorgroup>
<legalnotice>
<para>Permission is granted to make and distribute verbatim copies of
this manual provided that the copyright notice and this permission
notice are preserved on all copies.</para>
</legalnotice>
</bookinfo>
<toc></toc>
<preface id="preface">
<title>Preface</title>
<para><emphasis>Apache Isis</emphasis> is designed to allow programmers
rapidly develop domain-driven applications following the <ulink
url="http://en.wikipedia.org/wiki/Naked_Objects">Naked Objects</ulink>
pattern. It is made up of a core framework that supports supports variouys
viewers, along with <acronym>API</acronym>s and implementations relating
to security, the programming model, the runtime (persistence) and profile
stores (user preferences). <emphasis>Apache Isis</emphasis> is hosted at
the <ulink url="http://incubator.apache.org/isis">Apache
Foundation</ulink>, and is licensed under <ulink
url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software
License v2</ulink>.</para>
<sect1>
<title>Who this Guide is For</title>
<para>This guide is written for programmers looking to understand how
the core framework of <emphasis>Apache Isis</emphasis> fits together,
including an understanding of its core <acronym>API</acronym>s. It is
divided into the following chapters:<itemizedlist>
<listitem>
<para>Architectural Overview</para>
<para>The introductory chapter discusses some of the main
architecture elements of the framework's design, distinguishing
and explaining the reason for the applib, the core modules, the
viewers, and the main <acronym>API</acronym>s exposed by the
core.</para>
</listitem>
<listitem>
<para>Chapters for each of core modules</para>
<para>This part of the guide goes through each of the modules that
make up the core framework. We also identify the main
<acronym>API</acronym>s exposed by the core: security, programming
models, and runtime.</para>
</listitem>
</itemizedlist></para>
<para>We <emphasis>don't</emphasis> however describe the implementations
of these <acronym>API</acronym>s; for these see their respective guides.
What that means is that we don't describe how to actually deploy an
<emphasis>Isis</emphasis> application here, because that depends upon
the runtime/viewer in use. See the relevant runtime documentation for
details.</para>
<para>You'll also find that <emphasis>this</emphasis> guide does explain
how to actually write the domain objects that make up an
<emphasis>Isis</emphasis> application; for that you should look to the
<emphasis>applib (application library)</emphasis> documentation.
Meanwhile, the <emphasis>programming model</emphasis> documentation
describe how to customize the default programming model to your own
ends. However this guide <emphasis>does</emphasis> explain why
<emphasis>Isis</emphasis> is architected to have an applib in the first
place, and it shows what the programming model looks like
<emphasis>inside</emphasis> of <emphasis>Isis</emphasis>.</para>
</sect1>
<sect1>
<title>Abbreviations used in this Guide</title>
<para><emphasis>Apache Isis</emphasis> is built using Maven, which
identifies every module with a <emphasis>groupId</emphasis>, an
<emphasis>artifactId</emphasis>, a <emphasis>version</emphasis>, and a
<emphasis>type</emphasis>. These are called the Maven
<emphasis>co-ordinates</emphasis>. In this guide we identify each module
using notation <package>(groupId:artifactId)</package>; you should
assume that the <emphasis>version</emphasis> is the latest version, and
the <emphasis>type</emphasis> is the default JAR artifact<footnote>
<para>Maven modules can create other artifacts too, such as a test
JAR artifact. This would be indicated with a type of test-jar. But
the default artifact is a regular JAR.</para>
</footnote>. Hence <package>(org.apache.isis:core)</package> is the
Maven module with a <emphasis>groupId</emphasis> of
<package>org.apache.isis</package> and an
<emphasis>artifactId</emphasis> of <package>core</package>.</para>
<para>As a further convenience, we use "oai" as an abbreviation for
<package>org.apache.isis</package>. Hence
<package>(oai.runtimes:dflt)</package> refers to the default runtime
module.</para>
<para>In this guide we also use the "oai" abbreviation within package
names. For example,
<package>oai.core.runtime.authentication.AuthenticationManager</package>
is an abbreviation of
<package>org.apache.isis.core.runtime.authentication.AuthenticationManager</package>.</para>
</sect1>
</preface>
<chapter id="chp.Intro">
<title>Architectural Overview</title>
<abstract>
<para>What's in this guide, it's relationship to the applib
documentation.</para>
</abstract>
<para><emphasis>Apache Isis</emphasis> is a full-stack open source
application development framework, designed to let you rapidly develop
enterprise business applications following a domain-driven philosophy.
Developing an application in <emphasis>Isis</emphasis> is - at least
initially - about focusing on the bit that matters to the business, the
core domain logic.</para>
<sect1>
<title>Hexagonal Architecture</title>
<para><emphasis>Apache Isis</emphasis>' architecture is a variant of the
typical <ulink
url="http://xunitpatterns.com/Layered%20Architecture.html">layered
architecture</ulink>, called the <ulink
url="http://alistair.cockburn.us/Hexagonal+architecture">hexagonal
architecture</ulink>. Like the layered architecture, the hexagonal
architecture distinguishes between the user interface layer, the
persistence (or infrastructure) layer, and the domain layer.
<emphasis>Apache Isis</emphasis>' version of this architectural style is
shown below.</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/HexagonalArchitectureOverview.png"
scale="55" />
</imageobject>
</mediaobject>
<para>The viewer modules constitute the presentation layer; these are
the means by which the end-user initiates an interaction with the domain
objects. The interaction is not directly with the domain objects,
though; instead think of the viewers as interacting through a "port"
into the hexagon. The <emphasis>Isis</emphasis> framework then adapts
this interaction for the domain objects. Indeed, another name for the
hexagonal architecture is the "ports and adapters" architecture.</para>
<para>As the domain objects are called, they are likely to interact with
other services. The most obvious of these is an interaction with the
persistence layer, either in terms of an update to themselves or the
creation/update or deletion of other objects. Again, though, this isn't
direct; instead the framework mediates/adapts to the configured
persistence mechanism.</para>
<para>Alternatively, though, the domain objects may interact with other
domain services. These services are specific to the application in
question, for example an email service, to publish an event, to generate
a <acronym>PDF</acronym>, to submit an order via a
<acronym>SOAP</acronym> web service etc. Here the framework is much less
involved; it merely will automatically inject any registered domain
services directly into domain objects in order that they can invoke the
service.</para>
<para>In order to support the interactions from the viewer to the domain
objects, and from the domain objects to the persistence mechanism, the
framework itself also calls out to other modules. The progmodel
<acronym>API</acronym> defines the programming conventions for the
domain objects; these conventions are used to build up a metamodel. Some
of these conventions depend on annotations, hence these dependency from
domain objects to the applib (application library) module which defines
such things. It's important to note that this is the only dependency
from domain objects to the framework, meaning that the domain objects
are basically pojos++. The other major <acronym>API</acronym> called by
the framework in order to do its job is the security
<acronym>API</acronym>, which is used for authentication and
authorization.</para>
<para>In the diagram you'll also see mention of the "default runtime".
In fact <emphasis>Apache Isis</emphasis> supports multiple runtimes. The
<emphasis>default runtime</emphasis> is reasonably heavyweight
implementation that supports defines a persistence
<acronym>API</acronym>, but also has support for remoting for
client/server deployments (whereby the server is configured for
persistence but the client's "persistence mechanism" is in fact the
proxy to the server). The default runtime also supports the concept of
profilestores, allowing user preferences to be stored and retrieved by
viewers. Finally, the default runtime defines a pluggable bytecode
enhancement <acronym>API</acronym>, allowing for transparent lazy
loading and object dirtying.</para>
<para>The default runtime is not the only runtime, however. One other
runtime supported is an "embedded runtime", allowing the embedding of
the Isis metamodel in any arbitrary application, for example a Maven
plugin. But we also expect to develop other - full-stack but more
lightweight - runtimes in the future. One such that is planned is to use
<ulink url="http://jcp.org/en/jsr/detail?id=299">CDI (JSR-299)</ulink>
for wiring, using <ulink url="http://db.apache.org/jdo/javadoc.html">JDO
3.0</ulink> for the persistence <acronym>API</acronym>.</para>
</sect1>
<sect1>
<title>Core Framework</title>
<para>The core of <emphasis>Apache Isis</emphasis> is, well, the core
modules. These consist of a set of Maven modules grouped under a parent
module whose Maven co-ordinates are
<package>(org.apache.isis:core)</package>.</para>
<para>Each of the core modules has a Maven co-ordinate of
<package>[org.apache.isis.core:xxx</package>], where
<emphasis>xxx</emphasis> is one of:</para>
<itemizedlist>
<listitem>
<para>testsupport</para>
<para>The <emphasis>core testsupport</emphasis> module holds helper
classes to support writing unit tests in either JUnit or
JMock.</para>
</listitem>
<listitem>
<para>commons</para>
<para>The <emphasis>core commons</emphasis> module provides a set of
common utilities and language extensions for use across the rest of
the framework.</para>
</listitem>
<listitem>
<para>metamodel</para>
<para>The <emphasis>core metamodel</emphasis> module defines the
interfaces and classes which describe the structure of the domain
objects. The most obvious use of the metamodel is by the viewer
modules which use it in order to know how to render the user
interface. It is also used by some of the runtime/persistence
implementations.</para>
</listitem>
<listitem>
<para>progmodel</para>
<para>The <emphasis>core progmodel</emphasis> module provides a set
of reusable elements that are used to build up the metamodel. Some
of these depend upon annotations/interfaces in the
<emphasis>applib</emphasis> module, others merely define a
programming convention.</para>
</listitem>
<listitem>
<para>runtime</para>
<para>The <emphasis>core runtime</emphasis> module defines security
<acronym>API</acronym> (authentication and authorization) as well as
a number of other lesser <acronym>API</acronym>s and implementations
that are likely to be of use by most runtime implementations.</para>
</listitem>
<listitem>
<para>webapp</para>
<para>The <emphasis>core webapp</emphasis> module provides a number
of supporting filters, servlets and other classes for use by any
webapp-based viewer.</para>
</listitem>
</itemizedlist>
<para>These modules are covered more extensively in the following
chapters.</para>
</sect1>
<sect1>
<title>Core <acronym>API</acronym>s</title>
<para>Across the core modules a number of key <acronym>API</acronym>s
are defined.</para>
<itemizedlist>
<listitem>
<para>programming model <acronym>API</acronym></para>
<para>The <emphasis>core metamodel</emphasis> module defines the
<classname>oai.core.metamodel.progmodel.ProgrammingModel</classname>
interface, which defines the rules and conventions that constitute
the programming model.</para>
</listitem>
<listitem>
<para>security <acronym>API</acronym></para>
<para>The <emphasis>core runtime</emphasis> module defines a
security <acronym>API</acronym> (specifically,
<package>oai.core.runtime.authentication.AuthenticationManager</package>
and
<package>oai.core.runtime.authorization.AuthorizationManager</package>)
as well as a number of other lesser <acronym>API</acronym>s and
implementations that are likely to be of use by most runtime
implementations.</para>
</listitem>
<listitem>
<para>runtime (persistence) <acronym>API</acronym></para>
<para>The responsibility of the runtime - broadly speaking - is to
perform object lifecycle management, persistence and (optionally)
client/server remoting. Runtimes may also offer other services, such
as user preference (or profile) management.</para>
<para>The runtime is not an <acronym>API</acronym> per-se, but
rather represents the environment in which the other functionality
provided by the <emphasis>Isis</emphasis> framework is called.
<emphasis>Isis</emphasis> has two runtime implementations:</para>
<itemizedlist>
<listitem>
<para>the <emphasis>default runtime</emphasis>
<package>(oai.core.runtimes:dflt)</package> that supports all of
the above (lifecycle, persistence, remoting and
profiles).</para>
<para>A key part of the design of the core runtime is the
<package>oai.core.runtime.system.context.IsisContext</package>
interface, which is used to obtain the current session<footnote>
<para>This interface is somewhat akin to <ulink
url="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html">HibernateUtil</ulink>
class used in Hibernate.</para>
</footnote>.</para>
</listitem>
<listitem>
<para>the <emphasis>embedded runtime</emphasis>
<package>(org.apache.isis.core.runtimes:embedded)</package>, to
allow the <emphasis>Isis</emphasis> metamodel to be embedded
within otherwise bespoke applications, and in utilities such as
Maven plugins.</para>
</listitem>
</itemizedlist>
<para>At the time of writing no other runtimes are currently
implemented, but the intention is that other runtimes (eg using CDI,
JDO 3.0 etc) will be supported in the future.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1>
<title>Viewers</title>
<para>The viewers can be thought of as the outermost layer of
<emphasis>Isis</emphasis>, and calls upon the services of the core
framework and the configured runtime.</para>
<para>At the time of writing, all viewers have a dependency on the
<emphasis>default runtime</emphasis>, because this is the only runtime
available. In the future we expect that this will be decoupled so that
viewers can run against multiple different runtime
implementations.</para>
<para>Slightly confusingly, the <emphasis>default runtime</emphasis>
does also provide the facility to "launch" viewers, meaning that for
bootstrapping purposes at least the runtime calls the viewer rather than
the other way around. In order to support this, the viewer
implementation must provide an implementation of the runtime's
<package>oai.runtimes.dflt.runtime.viewer.IsisViewerInstaller</package>
interface. You'll see that the <acronym>DnD</acronym> viewer does do
this, but the Scimpi and Wicket viewers do not. However, once the viewer
is "up and running", the calls are strictly from the viewer to the
metamodel and runtime.</para>
</sect1>
<sect1>
<title>Maven Modules and Conventions</title>
<para><emphasis>Apache Isis</emphasis> is a large framework consisting
of multiple modules. In order to make it easier to navigate, you'll find
that we've aligned Maven module Ids with package names. For
example:</para>
<itemizedlist>
<listitem>
<para>the <emphasis>core metamodel</emphasis> module is
<package>(oai.core:metamodel)</package>; all classes in this module
reside in the <package>oai.core.metamodel</package> package (or in
subpackages)</para>
</listitem>
<listitem>
<para>the <emphasis>applib</emphasis> module is
<package>(oai:applib)</package>; all classes in this module reside
in <package>oai.applib</package> package (or in subpackages).</para>
</listitem>
</itemizedlist>
<para>We have also grouped modules of the same nature/interface to have
a common parent. For example:</para>
<itemizedlist>
<listitem>
<para><package>(oai:viewers)</package> is the parent of
<package>(oai.viewers:dnd)</package> and
<package>(oai.viewers:html)</package> modules</para>
</listitem>
<listitem>
<para><package>(oai:security)</package> is the parent of
<package>(oai.security:dflt)</package> and
<package>(oai.security:ldap)</package> modules</para>
</listitem>
</itemizedlist>
<para>There is also a top-level "parent" module,
<package>(oai:isis)</package>. This is used to define common
build/plugin dependencies, as well as a number of Maven profiles that
can be used to build subsets of the modules, and to build the Maven
website.</para>
<para>Finally, Isis also has an <package>(oai:release)</package> module.
The purpose of this module is simply to define a set of
<emphasis>Isis</emphasis> modules/versions that are compatible with each
other and thereby constitute a release. These can be imported
using:</para>
<programlisting><dependencies>
<dependency>
<groupId>org.apache.isis</groupId
<artifactId>release</artifactId>
<version>x.x.x</version>
<scope>import</scope>
</dependency>
...
</dependencies></programlisting>
<para>The <emphasis>Isis</emphasis> quickstart archetype makes use of
the release module in this way (as do the various examples that live in
<filename>.../trunk/examples</filename>).</para>
</sect1>
</chapter>
<chapter>
<title><emphasis>Test Support</emphasis> Module</title>
<abstract>
<para>Classes and interfaces in the
<package>oai.core.testsupport</package> module.</para>
</abstract>
<para>The <emphasis>testsupport</emphasis> module holds helper classes to
support writing unit tests using either JUnit or JMock. It should only
ever be added as a dependency with a scope of test:</para>
<para><programlisting><dependencies>
<dependency>
<groupId>org.apache.isis.core</groupId
<artifactId>testsupport</artifactId>
<version>x.x.x</version>
<emphasis><scope>test</scope></emphasis>
</dependency>
...
</dependencies></programlisting></para>
<sect1>
<title>JMock Support</title>
<para>The classes in the <package>oai.core.testsupport.jmock</package>
package provide convenience adapters for <ulink
url="http://jmock.org">JMock</ulink>. For example, they provide the
<classname>MockFixture</classname> interface that allows mocks
expectations to be managed as fixture objects in their own right
(thereby making such expectations reusable across tests). They also
provide subclasses of the <package>org.jmock.Mockery</package> class
with a number of convenience methods.</para>
</sect1>
<sect1>
<title>JUnit Support</title>
<para>The classes in the
<classname>oai.core.testsupport.junit</classname> package provide helper
classes designed, among other things, to make it easier to write value
types.</para>
</sect1>
</chapter>
<chapter>
<title><emphasis>Commons</emphasis> Module</title>
<abstract>
<para>Classes and interfaces in the <package>oai.core.commons</package>
module.</para>
</abstract>
<para>The <emphasis>core commons</emphasis> module provides a set of
common utilities for use across the rest of the framework. It also defines
a number of small, mostly internal, <acronym>API</acronym>s.</para>
<para>Generally it shouldn't be necessary to add an explicit dependency to
the <emphasis>commons</emphasis> module, because it will be depended upon
transitively by other modules in <package>oai.core</package>.</para>
<sect1>
<title>Package Layering / Dependencies</title>
<para>The packages that reside within <emphasis>commons</emphasis> have
break into the following layers (top layer packages depending on lower
layers):</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/common/architecture-perspective.png"
scale="80" />
</imageobject>
</mediaobject>
<para>Alternatively we can see the actual dependencies:</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/common/composition-perspective.png"
scale="80" />
</imageobject>
</mediaobject>
<para>The relatively small number of dependencies between these packages
shows the extent to which the utility classes in common are independent
of each other.</para>
</sect1>
<sect1>
<title>APIs</title>
<sect2 id="sec.ComponentAndInstallerApi">
<title><classname>Component</classname> and
<classname>Installer</classname> <acronym>API</acronym></title>
<para><emphasis>Isis</emphasis> is a modular framework, and the
<classname>Component</classname> interface (in
<package>oai.core.commons.components</package> package) represents
this abstraction. For example, an authentication manager is a
<classname>Component</classname>, and so too is an adapter map (for
tracking object identities).</para>
<para><classname>Component</classname> has three subinterfaces to
represent different scopes (or lifetimes) of component instances,
namely:</para>
<itemizedlist>
<listitem>
<para><classname>ApplicationScopedComponent</classname>, for
components that exist for the duration of the application</para>
</listitem>
<listitem>
<para><classname>SessionScopedComponent</classname> , for
components that are created a-new for each session, and</para>
</listitem>
<listitem>
<para><classname>TransactionScopedComponent</classname>, for
components that are bound to a single transaction.</para>
</listitem>
</itemizedlist>
<para>For webapp/server-based deployments, a session is created for
each interaction<footnote>
<para>Just like JPA or Hibernate sessions.</para>
</footnote>. There is typically just one transaction per
session.</para>
<para>For client/standalone deployments, the session lasts for the
duration of the application, and so is one-to-one with the application
scope. For these cases a transaction is used to wrap each
client/server interaction<footnote>
<para>Strictly speaking, this is a statement about how the the
<emphasis>default runtime</emphasis> implementation works. Other
runtimes could conceivably take a different approach. If you are
only intending to use webapp-based viewers, then don't worry about
it... <emphasis>Isis</emphasis> works similarly to
JPA/Hibernate.</para>
</footnote>.</para>
<para>Closely related to <classname>Component</classname> is the
<classname>Installer</classname> interface, which acts as a
<classname>Component</classname> factory. Each Installer provides a
type (a string) and a name (also a string), and the combination of
(type, name) is expected to be unique. For example, the DnD viewer has
a type of "viewer" and a name of "dnd".</para>
<para>This (type, name) combination is used to determine the
configuration files that are searched for when the
<classname>Component</classname> is created. Each
<classname>Component</classname>'s <classname>Installer</classname>
will search for at least two property files:
<filename>type.properties</filename> and
<filename>type_name.properties</filename>. For example, the DnD viewer
will search for both <filename>viewer.properties</filename> and also
<filename>viewer_dnd.properties</filename> file<footnote>
<para>In fact, it is possible for an
<classname>Installer</classname> to nominate additional property
files; this is sometimes appropriate where a
<classname>Component</classname> does double-duty and plays more
than one role. At the time of writing this capability was only
used by the components that install client/server remoting for the
<emphasis>default runtime</emphasis> module.</para>
</footnote>. An Installer can also indicate whether a missing config
file should be treated as an error or can be ignored (generally the
latter).</para>
</sect2>
<sect2 id="sec.ConfigurationApi">
<title><classname>IsisConfiguration</classname> and
<classname>IsisConfigurationBuilder</classname>
<acronym>API</acronym></title>
<para>The <classname>IsisConfigurationBuilder</classname> (in
<package>oai.core.commons.config</package> package) is used to hold
the "current" configuration; as (the <classname>Installer</classname>
for) <classname>Component</classname>s are loaded each indicates the
property file(s) to load, and these are used to update the current
configuration held within
<classname>IsisConfigurationBuilder</classname>. The "current"
configuration is initially just the properties in the
<filename>isis.properties</filename> file (see <xref
linkend="sec.ResourceStreamApi" /> for details on where this file is
actually loaded from) .</para>
<para>When the <classname>Component</classname> is actually
instantiated, it is handed an immutable
<classname>IsisConfiguration</classname> that can be thought of as a
snapshot of the set of properties held by the
<classname>IsisConfigurationBuilder</classname>. A consequence of this
design is that different <classname>Component</classname>s will have
references to different <classname>IsisConfiguration</classname>
objects; though all should always have access to "their"
properties.</para>
<para>Using properties specified in the configuration files is done by
get the <classname>IsisConfiguration</classname> singleton from the
context and using one of the lookup methods to get a value, as the
example below shows. The <literal
moreinfo="none">Configuration.ROOT</literal> constant provides the
base property name ("isis."). If no value is found with the specified
property name exists then null (or 0 or false) will be
returned.</para>
<programlisting format="linespecific">String formatRequired = getConfiguration().getString(Configuration.ROOT + "value.format.date");</programlisting>
</sect2>
<sect2>
<title
id="sec.ResourceStreamApi"><classname>ResourceStreamSource</classname>
<acronym>API</acronym></title>
<para>The <classname>ResourceStreamSource</classname> interface (in
<package>oai.core.commons.resource</package> package) is an
abstraction over locating resource files. It is used predominantly to
locate configuration files (see <xref
linkend="sec.ConfigurationApi" />), with implementations to load from
the config directory or from the classpath.</para>
<para>Different implementations of
<classname>IsisConfigurationBuilder</classname> use
<classname>ResourceStreamSource</classname> in order to search for
config files in specific locations. In principle it would be
straightforward to write a new implementation of
<classname>ResourceStreamSource</classname> that loads config files
from some other location (eg LDAP, the Windows registry or a database)
and then write a new <classname>IsisConfigurationBuilder</classname>
to use it.</para>
</sect2>
<sect2>
<title>Encoding <acronym>API</acronym></title>
<para>The <package>oai.core.commons.encoding</package> package
provides a number of classes to support the custom serialization of
elements of any element:</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/common/encoding-classdiagram.png"
scale="35" />
</imageobject>
</mediaobject>
<para>The <classname>DataInputExtended</classname> and
<classname>DataOutputExtended</classname> interfaces are
straightforward extensions of <classname>java.io.DataInput</classname>
and <classname>java.io.DataOutput</classname> respectively, simply
adding the capability to serialize arrays of primitives. The
<classname>DataInputStreamExtended</classname> and
<classname>DataOutputStreamExtended</classname> implement these
interfaces, providing the ability to read from/write to an underlying
<classname>java.io.InputStream</classname>.</para>
<para>Finally, the <classname>Encodable</classname> interface defines
a contract for objects to write themselves to a
<classname>DataOutputStreamExtended</classname>, with an implied
contract that they can be re-constructed from a corresponding
<classname>DataInputStreamExtended</classname>.</para>
<para>The primary usage of the encoding API is to enable client/server
remoting, as supported by the <emphasis>default runtime</emphasis>
implementation. However, it is also used in order to create
<classname>Memento</classname>s of domain objects (again, a capability
of the <emphasis>default runtime</emphasis>). This is used by some
viewers in order to maintain a handle on transient (not-yet-persisted)
objects.</para>
</sect2>
<sect2 id="sec.AuthenticationSession">
<title><classname>AuthenticationSession</classname> Definition</title>
<para>The <classname>AuthenticationSession</classname> interface (in
the <package>oai.core.commons.authentication</package> package)
provides a representation of an authenticated user within the
system.</para>
<para>Also worth mentioning is the utility class
<classname>AuthenticationSessionUtils</classname> can be used to
create an <classname>oai.applib.security.UserMemento</classname>,
which is the corresponding type within the applib (that is, the
identity of the authenticated user as the domain objects understand
it).</para>
<para>The interface to actually authenticate users and create
<classname>AuthenticationSession</classname>s - namely
<classname>AuthenticationManager</classname> - is defined in the
<emphasis>core runtime</emphasis> module (see <xref
linkend="chp.Runtime" />). This shouldn't be confused with
<classname>AuthenticationSessionProvider</classname> which merely
returns the current <classname>AuthenticationSession</classname>
<emphasis>if one exists</emphasis>.</para>
</sect2>
<sect2>
<title><classname>Debuggable</classname>
<acronym>API</acronym></title>
<para>The <classname>Debuggable</classname> interface(in the
<classname>oai.core.commons.debug</classname> package) is used by some
<classname>Component</classname>s in order to build structured string
representations of themselves for debug purposes. A good example is
the debug menu options available within the DnD viewer.</para>
</sect2>
<sect2>
<title>Hamcrest <classname>Matcher</classname>s</title>
<para>The <classname>IsisMatchers</classname> class (in the
<classname>oai.core.commons.matchers</classname> package) provides a
collection of <ulink url="http://hamcrest.org">Hamcrest
</ulink><classname>Matcher</classname>s for use in both tests and also
production code.</para>
</sect2>
<sect2>
<title><classname>Ensure</classname> API</title>
<para>The <classname>Ensure</classname> class (in the
<package>oai.core.commons.ensure</package> package) allows assertions
to be made about arguments, state or general context, and uses
Hamcrest <classname>Matcher</classname>s to express those
assertions.</para>
</sect2>
</sect1>
</chapter>
<chapter id="chp.MetaModel">
<title><emphasis>Metamodel</emphasis> Module
(<classname>ObjectSpecification</classname>s)</title>
<abstract>
<para>First of two chapters concerning the classes and interfaces in the
<package>oai.core.metamodel</package> module, focusing on the
<classname>ObjectSpecification</classname> and related
interfaces.</para>
</abstract>
<para>The core <emphasis>metamodel</emphasis> module defines the
interfaces and classes that make up the <emphasis>Apache Isis</emphasis>
metamodel. This metamodel is at the very heart of
<emphasis>Isis</emphasis>, and used in numerous ways:</para>
<itemizedlist>
<listitem>
<para>by viewers to obtain information about the domain objects, so
that they can be rendered in a generic object-oriented user
interface;</para>
</listitem>
<listitem>
<para>by persistence mechanisms (within the <emphasis>default
runtime</emphasis> module, <package>(oai.runtimes:dflt)</package>) to
determine which data is to be persisted;</para>
</listitem>
<listitem>
<para>by client/server remoting (within the <emphasis>default
runtime</emphasis> module) , to marshall domain objects automatically
between different tiers;</para>
</listitem>
<listitem>
<para>to provide the ability to provide XML Snapshots (through the
<classname>XmlSnapshot</classname> utility class, in the
<emphasis>core runtime</emphasis> module,
<package>(oai.core:runtime)</package>).</para>
</listitem>
</itemizedlist>
<para>In addition, the metamodel provides a mechanism for the framework
and the clients of the framework to access and manipulate the domain
objects by wrapping them in an adapter. This is an important point: the
framework and its clients never interact with the domain objects
directly.</para>
<para>Note however that the <emphasis>metamodel</emphasis> module does not
itself define the programming model conventions; that is the
responsibility of the configured programming model (the default being the
one defined in the <emphasis>default progmodel</emphasis>
<package>(oai.progmodels:dflt)</package>.</para>
<sect1>
<title>Package Layering / Dependencies</title>
<para>The packages that reside within <emphasis>core
metamodel</emphasis> break into the following layers (top layer packages
depending on lower layers):</para>
<screenshot>
<screeninfo>Top-level Architecture Diagram with SpecLoader
expanded</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="images/metamodel/architecture-diagram-top-level-with-specloader-expanded.png"
scale="110" />
</imageobject>
</mediaobject>
</screenshot>
<para>Note that the diagram shows the <package>specloader</package>
package and also its subpackages. It also indicates that there is a
tangle (bidirectional dependencies)<footnote>
<para>Not a good thing, we recognize. But refactor to eliminate this
would considerably complicate the codebase.</para>
</footnote>Alternatively we can see the actual dependencies between
packages (again, with that tangle highlighted):</para>
<screenshot>
<screeninfo>Composition Diagram</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="images/metamodel/composition-diagram-top-level.png"
scale="70" />
</imageobject>
</mediaobject>
</screenshot>
</sect1>
<sect1 id="sec.ObjectSpecifications">
<title><classname>ObjectSpecification</classname>s and the
<classname>SpecificationLoader</classname></title>
<para>To make the domain objects useful within the framework the
objects' public interfaces must be exposed. <emphasis>Isis</emphasis>
uses a number of techniques to do this, but the predominant one is the
Java reflection <acronym>API</acronym>s (in the
<package>java.lang.reflect</package> package), a process we call
introspection. These are used to determine what properties and
collections an object has, what behaviour it can offer, and to find
other information such as the object's title, a suggested order of its
fields, and when its actions can or can't be used. It also is used to
flag the type of object (abstract, lookup, object, value, and whether
persistable); to refer to its superclass, any inteferfaces it implements
and to list any subclasses.</para>
<para>The details about this interface are recorded in an instance of
<classname>ObjectSpecification</classname> (in the
<package>oai.core.metamodel.spec</package> package). As each class of
domain object is loaded into the system its corresponding instance of
<classname>ObjectSpecification</classname> is generated. You can think
of <classname>ObjectSpecification</classname> as analogous to
<classname>java.lang.Class</classname>.</para>
<sect2>
<title><classname>SpecificationLoader</classname> component</title>
<para>The specification object can be retrieved directly, by name or
class, from the <classname>SpecificationLoader</classname>
component<footnote>
<para>For historical reasons the
<classname>SpecificationLoader</classname> component is also
sometimes called the reflector; indeed
<classname>ObjectReflector</classname> is a subinterface that is
used internally.</para>
</footnote></para>
<para>. When a domain object is used within the framework the
<classname>SpecificationLoader</classname> instance is asked for the
<classname>ObjectSpecification</classname> of the domain object's
class. The first time that a class is requested the loader is
responsible for performing the introspection and creating a complete
<classname>ObjectSpecification</classname>. Thereafter the
specification is returned from a cache.</para>
<para>The set of <classname>ObjectSpecification</classname>s built up
by the <classname>SpecificationLoader</classname> are all those that
are reachable from the service classes (defined in
<filename>isis.properties</filename> configuration file under
<emphasis>isis.services</emphasis> key). Because cycles between
<classname>ObjectSpecification</classname>s are permitted (that is,
<classname>ClassA</classname> can reference
<classname>ClassB</classname> and <classname>ClassB</classname> can
reference <classname>ClassA</classname>), the creation of
<classname>ObjectSpecification</classname>s is actually a two-stage
process. When a class' <classname>ObjectSpecification</classname> is
being created, any prerequisite specifications (for its class members)
will be created if necessary, however those prerequisites will not
flagged as not yet "introspected". Only when those prerequisite
<classname>ObjectSpecification</classname>s are actually requested by
name will their introspection be formed. This prevents infinite loops
from occurring in the
<classname>SpecificationLoader</classname>.</para>
<para>It is also possible - and common - to obtain the
<classname>ObjectSpecification</classname> from the domain object's
adapter (the <classname>ObjectAdapter</classname> interface, discussed
in <xref linkend="sec.ObjectAdapter" />).</para>
<sect3>
<title>Accessing the
<classname>SpecificationLoader</classname></title>
<para>If using the <emphasis>default runtime</emphasis> module
<package>(oai.runtimes:dflt)</package>, then the
<classname>SpecificationLoader</classname> can be accessed using
<methodname>IsisContext.getSpecificationLoader()</methodname>. It is
an application-scoped component, meaning that a single instance is
used for the duration of the application running.</para>
<para>Other runtime implementations will (are likely to) use
dependency injection to make the
<classname>SpecificationLoader</classname> available.</para>
</sect3>
</sect2>
<sect2 id="sec.ObjectMembers">
<title><classname>ObjectMember</classname>s</title>
<para>One of the main purposes of
<classname>ObjectSpecification</classname> is to describe the
structure of the domain object to which it relates, in other words the
members of that object's class. These are represented by
(sub-)interfaces of the <classname>ObjectMember</classname> interface
(in the <package>oai.core.metamodel.spec.feature</package> package).