Project

General

Profile

Z2 Java components intro » History » Version 11

Henning Blohm, 21.09.2012 11:33

1 1 Henning Blohm
h1. An introduction to Z2 Java components
2
3 5 Henning Blohm
The one, probably most essential component type, is that of Java components. Per se, modules in Z2 are not "Java modules" (unlike in OSGi for example). From its underlying model, Java code is handled like any other component resource. There is however important conventions that do make Java components special.
4
5
Java components play an important role in Z2 modularization, as re-use of code is one of the driving motivations for modularization. Z2 offers a moderately sophisticated way of re-use via inclusion or class loading delegation that is still simple enough that typical Java and Java EE approaches still work without painful adaptations and that you can - in many cases - ignore the more complex, problematic situations. 
6
7
h2. Conventions
8
9 7 Henning Blohm
A majority of component types imply the presence of some implementation code or "class path stored" resources: A Web application may require some Servlet implementation or a Tag Library. A Datasource names a JDBC implementation class, a Spring application context needs to find Bean implementation types.
10 6 Henning Blohm
11 8 Henning Blohm
Therefore Z2 implements a module level convention (and this is actually the only place that the module granularity matters) that is used by component types to identify "the default source of implementation code": 
12
13 9 Henning Blohm
bq. Given a component *<module>/<name>*, when requiring to retrieve implementation types, look for the Java component *<module>/java*. 
14 8 Henning Blohm
15
That convention is implemented in "JavaComponentUtil":http://www.z2-environment.net/javadoc/com.zfabrik.core.api!2Fjava/api/com/zfabrik/components/java/JavaComponentUtil.html and used all over the place.
16 7 Henning Blohm
17 9 Henning Blohm
Part of that convention is that components in the module use the implementation or "private" loader of the module's Java component to look for types or class path resources. That is, components in the module are privileged to refer to implementation code that may not be visible to components of other modules (see also "IJavaComponent":http://www.z2-environment.net/javadoc/com.zfabrik.core.api!2Fjava/api/com/zfabrik/components/java/IJavaComponent.html).
18 7 Henning Blohm
19
This technically slim convention makes modules a place to implement encapsulation and information hiding.
20 6 Henning Blohm
21 5 Henning Blohm
h2. API and Implementation
22 1 Henning Blohm
23 9 Henning Blohm
Z2 supports a separation of *API* definitions, i.e. Java types or class path resources that may be referenced from other Java components, and *implementation* types or class path resources that are hidden from other Java components. This is reflected in the folder structure of Java components. You do however have the choice of ignoring this separation by using an "API vs. Implementation"-indifferent folder structure that behaves as if everything is an API.
24 1 Henning Blohm
25 9 Henning Blohm
Before explaining the details of the folder structure, here is some rational:
26
27
Ideally modules implement some coherent set of functions hat are exposed via interfaces that hide implementation details. Within the module implementation types may do however seen fit best to implement the promised interfaces. By hiding the implementation from direct access by other modules, the module contract is required to be restricted to the exposed interfaces and you reserve the freedom to modify the implementation without breaking your module's contract.
28
29
Another aspect that is in reality at least as important is that APIs effectively (in reality) imply a transitive closure that spans everything needed by the API. Without a clean separation of API and implementation, you do effectively expose also 3rd party implementations used in your implementation which can easily become a major headache due to version conflicts and accidental re-use by users of your API.
30
31
There are reasons to not separate API and implementation in a module however. For example:
32
33
* You have an extremely pure or small setup in which there is no possibility of version conflicts or accidental re-use
34
* You separate on the module level, i.e. some modules are  pure API modules, while other modules are pure implementation modules, and you do not care about hiding
35
36
We do generally recommend to split API from implementation and use the corresponding folder structure, even some folders stay empty.
37
38
On top of API and implementation, Z2 Java components support test code. Test code is part of the component's implementation code if and only if Z2 runs in development mode (i.e. the system property *com.zfabrik.mode* is set to development)
39
40
h2. Java component folder structure
41
42
Typically, Java components are defined in a folder *<module name>/java*. In the rare case that a Java component does not provide definitions on its own, a Java component can be declared as *<module name>/java.properties*. The folder structure of Java components assigns meaning to the following folders:
43
44
|z.properties|The component descriptor. Typically this looks like
45
     com.zfabrik.component.type=com.zfabrik.java
46
     java.publicReferences=<java component 1>, <java component 2>,...
47
     java.privateReferences=<java component n>, <java component n+1>,... |
48 11 Henning Blohm
|src.api|Public type definitions that will be compiled and exposed so that they are visible by other Java components. See below.|
49 9 Henning Blohm
|bin.api/lib|JAR libraries to be added to the public types of the Java Component.|
50
|bin.api/classes|Pre-compiled Java code, i.e. .class files and other resources to be added to the public types of the Java Component.|
51
|src| Equivalent to src.api and may be combined |
52
|bin/lib| Equivalent to bin.api/lib and may be combined |
53
|bin/classes| Equivalent to bin.api/classes and may be combined |
54 11 Henning Blohm
|src.impl|Type definitions that will be compiled and made available for use within the project (see above) but will not be exposed to other Java components. See below.|
55 9 Henning Blohm
|bin.impl/lib|JAR libraries to be added to the private types of the Java Component.|
56
|bin.impl/classes|Pre-compiled Java code, i.e. .class files and other resources to be added to the private types of the Java Component.|
57
|src.test|Type definitions that will be compiled and made available for use just like the types defined in src.impl. In contrast to src.impl, the source files in src.test will be ignored unless the runtime runs in development mode, that is the system property "Foundation.MODE":http://www.z2-environment.net/javadoc/com.zfabrik.core.api!2Fjava/api/com/zfabrik/util/runtime/Foundation.html#MODE is set to "development".|
58
|bin.test/lib|JAR libraries to be added to the private types of the Java Component iff running in development mode.|
59
|bin.test/classes|Pre-compiled Java code, i.e. .class files and other resources to be added to the private types of the Java Component iff running in development mode.|
60
61
Java components may "include" components of type *com.zfabrik.files* and *com.zfabrik.java*. This can be useful for libraries that cannot be shared by just re-using the classes but instead require to be used within the using component's context, e.g. to load classes by name that would not be within the library's scope. This is true for older versions of the Spring framework for example.
62
63
Files components may be included as API or impl provisioning depending on the reference used. The included source files or pre-compiled binaries are expected to comply to the following folder structure:
64
65
|src| Source files that require compilation before execution.|
66
|bin/lib|JAR libraries|
67
|bin/classes|Pre-compiled Java code, i.e. .class files and other resources |
68
69 1 Henning Blohm
h2. Referencing and including Java resources from other modules
70 9 Henning Blohm
71
Via the following component properties, re-use of Java definitions from other Java components can be controlled:
72
73 10 Henning Blohm
|java.publicReferences|Points to other java components whose public types will be shared with this one (and maybe others).
74 1 Henning Blohm
Everything referenced as public reference will be visible to the public interface of the referencing component as well as to all referencing the referencing component. In other words: References are transitive. In particular, anything required to compile the public types of a Java component must be referenced via this reference property.
75 9 Henning Blohm
Components may be specified as a comma-separated list. Component names that have no "/" will be defaulted by appending "/java". |
76
|java.publicIncludes|Points to com.zfabrik.files or com.zfabrik.java components that must have a bin (or alternatively a bin.api, for Java components) folder that will be included into this java component's public java resources. The component may also have a src (or alternatively src.api, for Java components) folder that will be copied before compilation into src.api. |
77 10 Henning Blohm
|java.privateReferences|Points to other java components whose public types will be shared with this one (and maybe others) Nothing referenced as private reference will be automatically exposed to the public interface of the referencing component nor to other components. Anything needed to compile the private types of a Java component, must be referenced as a public reference, be part of the public types of that component, or be referenced via this reference property.
78 1 Henning Blohm
In other words: The private types automatically see the public types and transitively anything referenced publicly as described above. In addition, to use more types in the "private implementation section" of a Java component, types that will not be exposed to referencing components, use this reference property.
79
Components may be specified as a comma-separated list. Component names that have no "/" will be defaulted by appending "/java". |
80
|java.privateIncludes|Points to com.zfabrik.files or com.zfabrik.java components that must have a bin (or alternatively a bin.api, for Java components) folder that will be included into this java component's private java resources. The component may also have a src (or alternatively src.api, for Java components) folder that will be copied before compilation into src.impl. |
81
|java.testReferences|Points to another java component whose public types will be shared with this one (and maybe others) if the execution mode, as defined by the system property Foundation.MODE is set to "development". Test references extend the private references. In conjunction with the tests source folder this allows to add test code and corresponding dependencies that will be ignored by the runtime unless running in development mode. |
82 9 Henning Blohm
|java.testIncludes|Points to com.zfabrik.files or com.zfabrik.java components that must have a bin (or alternatively a bin.api, for Java components) folder that will be included into this java component's test java resources. The component may also have a src (or alternatively src.api, for Java components) folder that will be copied before compilation into src.test. |
83 10 Henning Blohm
84
The following picture illustrates the relationships established via references and includes:
85
86
!java.png!
87 9 Henning Blohm
88
h2. Classloading in Z2
89 5 Henning Blohm
90 11 Henning Blohm
The class loader concept of the Java platform provides a powerful name spacing mechanism on the type system. While in the beginning that seems to be of little concern, in more complex scenarios isolation within the type system in conjunction of sharing of types between modules of a solution becomes the catalyst of successful modularization.
91 1 Henning Blohm
92 11 Henning Blohm
The class loading system in Z2 is based on a delegate-first, multi-delegation scheme. Effectively, a Java component will have two class loaders at runtime. One for the API, one for the Implementation and both ask their delegation targets (other class loaders) first before searching local resources.
93 1 Henning Blohm
94 11 Henning Blohm
The API class loader will have delegation loaders corresponding to all Java components identified by the public references. The implementation class loader will have the API class loader as parent and delegation loaders corresponding to all Java components identified by the private references of the Java component (see above).
95 1 Henning Blohm
96 11 Henning Blohm
Java references that lead to cyclic dependencies between Java modules are not supported.
97
98
h2. More Java component configuration
99
100
Apart from refrences and includes, the following configuration properties may be used
101
102 6 Henning Blohm
|com.zfabrik.component.type|com.zfabrik.java|
103
|java.compile.order|The compile order must be defined in java components that also contain non-java sources - e.g. scala. This property can be omitted for pure java components, otherwise one has to define all compilers in the right order - e.g: scala, java|
104 5 Henning Blohm
105
h2. References
106
107
* http://www.z2-environment.eu/v21doc#javaComponents