Project

General

Profile

Getting Started » History » Version 1

Henning Blohm, 08.02.2015 17:02

1 1 Henning Blohm
h1. Getting Started
2
3
See also [[FAQ]]
4
5
To understand how z2 works, you need to understand at most what are z2 modules and components and what are component repositories and how these concepts interplay. 
6
7
Check out [[wiki#Understanding-Z2|understanding-z2]] for that.
8
9
It is simplest to start by running a simple Java main program in z2 or a simple Web App. 
10
11
Follow this trail:
12
13
* [[Getting Started#Building-z2env-core|Building the core]]
14
* [[Getting Started#Running-a-Hello-World-main-program|Running a Hello World main program]]
15
* [[Getting Started#Running-a-Hello-World-Web-App|Running a Hello World Web App]]
16
* [[Getting Started#Developing-with-Eclipse-or-IntelliJ|Developing with Eclipse or IntelliJ]]
17
* [[Getting Started#Going-Multi-Module|Going Multi Module]]
18
19
20
h2. Building z2env-core
21
22
(For now, we need to build the core).
23
24
h3. Pre-requisites
25
26
* You need Git installed
27
* You need a JDK, at least version 7
28
* You need the ANT build tool
29
30
First clone http://git.z2-environment.net/z2env.core
31
32
<pre>
33
git clone http://git.z2-environment.net/z2env.core
34
</pre>
35
36
Change into *org.z2env.core.main* and run 
37
38
<pre>
39
ant -Doutput=<z2home> -Dsetup=<setup> 
40
</pre>
41
42
where <z2home> is where you want to install z2 (the *z2 home* that is) and <setup> is a choice of pre-configured content, actually component repositories.
43
44
If you omit *output* it will default to *gen/dist*. If you omit *setup*, no content will be pre-configured will be modified. 
45
46
Check the folder *setups* for available setups of the core build. These can be local (all repos will be cloned locally) or remote (repos will be remoted).
47
48
In general this build always updates only boot, z.jar, roots. It will not remove anything.
49
50
51
Example to install/update a core only into ../../z2env:
52
53
<pre>
54
ant -Doutput=../../z2env 
55
</pre>
56
57
To install/update a web-basic setup (with tomcat and eclipsoid support) with updates from remote repos:
58
59
<pre>
60
ant -Doutput=../../z2env -Dsetup=web-basic-remote
61
</pre>
62
63
Check out [[wiki#Understanding-the-ltHOMEgt|Understanding the <HOME>]] to learn more about the generated structure.
64
65
66
h2. Running a Hello World main program
67
68
For now, we will assume you have a z2 core installed in <HOME>. In its purest form, all the core can actually execute is simple Java main programs. 
69
70
Being in a modular environment, even if we only want to say „Hello World“, we need a module. Let's call it the greeter module. In order to have a main program run by z2, we need to also declare a  component for it, as that is what we tell z2 to run (not a class – mind you – but rather a component in a module). Assuming we use the local component name hello, than the absolut component name is 
71
72
<pre>
73
greeter/hello
74
</pre>
75
76
Finally, as this component actually has implementation code, we need to declare a Java component. By convention this is 
77
78
<pre>
79
greeter/java
80
</pre>
81
82
Now, after installing in <HOME> the place to simply drop a module is under <HOME>/modules. You might need to create that folder.
83
84
All in all, here is the complete structure to create:
85
86
| <HOME>/modules/greeter/hello.properties | 
87
<pre><code class="ruby">org.z2env.component.type=org.z2env.main
88
component.className=greetings.Main
89
</code></pre> |
90
| <HOME>/modules/greeter/java/z.properties | 
91
<pre><code class="ruby">org.z2env.component.type=org.z2env.java
92
</code></pre> |
93
| <HOME>/modules/greeter/java/src.impl/greetings/Main.java |
94
<pre><code class="java">
95
package greetings;
96
97
public class Main {
98
  public static void main(String[] args) {
99
    System.out.println("Hello!");
100
  }
101
}
102
</code></pre> |
103
104
That gives us the two components of module greeter. To run this on the command line, run
105
106
<pre>
107
java -DcomponentName=greeter/hello -jar z.jar
108
</pre>
109
110
Now, obviously this sample is not worth a modular execution environment. But even from here, you could check your module in with some Git repository that is referenced from the roots and all other users of the same repo would be able to run your component without installing anything.
111
112
h2. Running a Hello World Web App
113
114
This introduction explains how to connect a z2 core to a given Tomcat installation and how to develop a simple Web Application.
115
116
Furthermore it describes how to use the Dev Repository and the Eclipsoid plugin for the Eclipse or the IntelliJ development environment.
117
118
h3. Pre-Requisites
119
120
* We assume a development workspace in *workspace*.
121
* Have a local Tomcat (7 or higher) installation.*
122
123
h3. Steps we are going to take
124
125
# Create a module with a simple Web app
126
# Make it visible to Z2
127
# Run the Web App in a Tomcat Web Container
128
129
At first get yourself a z2env core with the *web-basic-local* or *web-basic-remote* setup. Make sure it is in your *workspace*. If you follow [[wiki#Building-z2env-core|Building the core]] this means running 
130
131
<pre>
132
ant -Doutput=workspace/z2env -Dsetup=web-basic-remote
133
</pre>
134
135
(*Note:* If in doubt, use an absolute path for *workspace*)
136
137
Using your IDE create a new project *hello* in *workspace* with the following structure:
138
139
| java/z.properties | 
140
<pre><code class="ruby">
141
org.z2env.component.type=org.z2env.java
142
java.privateReferences=\
143
	javax.servlet
144
</code></pre> |
145
| web/z.properties |
146
<pre><code class="ruby">
147
org.z2env.component.type=org.z2env.tomcat.webapp
148
webapp.path=/hello
149
</code></pre> |
150
| web/WebContent/index.jsp |
151
<pre><code class="html"><html><body>Hello! Did you know that 7*7=<%=7*7%>?</body></html></code></pre> |
152
| LOCAL | <empty file> |
153
154
Your *workspace* folder now contains two subfolders *z2env* and *hello*.
155
156
So far, that's it.  We will touch on the LOCAL file later. 
157
158
When we run Z2 knowing this Web Application, it will attempt to start a Tomcat Web Container that will serve the application's content. To do that, it needs to find one. 
159
160
In order to tell Z2 where to look, you can either set an environment variable *CATALINA_HOME* (you might have already – it's the Tomcat standard) or specify an environment variable *catalina.home*. 
161
162
To be on the safe side and assuming the location is */home/me/tomcat*, we open a terminal, change into *workspace/z2env* and run
163
164
<pre>
165
java -Dcatalina.home=/home/me/tomcat -jar z.jar hello/web
166
</pre>
167
168
Note, unlike for the main program, the command line will not return. Instead you can enter „q“ to quit or „s“ to synchronize. But first let's open a browser and check out 
169
170
<pre>
171
http://localhost:8080/hello
172
</pre>
173
174
*Note:* What you just created is a prototypical z2 module structure containing a Java component *java* (holding implementation) and a Web component *web*. 
175
176
Instead of creating the structure yourself, you could use the Eclipsoid plugin (introduced below) for that:
177
* In Eclipse: New / Others / new z2...., 
178
* In IntelliJ: New / Module / z2....
179
180
... but beware of the pre-generated configuration. Where it says *com.zfabrik* change to *org.z2env*.
181
182
183
*Note:* Now on to that LOCAL file. Unlike for the Hello World main program, this time it was to so-called Dev Repo that made our module available to z2. 
184
185
The dev repo is a key component to the development approach with z2. It checks for all modules that have a LOCAL file and that are stored some levels deep, relative to the parent folder of the z2 home (by default), which not so coincidentally is our workspace.
186
187
We call modules with a LOCAL file _armed_.
188
189
*Note:* By default the dev repo looks for modules beneath the parent folder of the <home> location. Use the system property *org.z2env.dev.local.workspace* to specify other locations (separated by comma) to check for modules.
190
191
192
Try this: 
193
194
# Remove LOCAL
195
# Enter „s“ for synchronization. 
196
# Check the URL above (should say „not found“)
197
# Create a LOCAL file again
198
# Synchronize
199
# Check again.
200
201
Similarly, from now on, changes made to the hello module will be picked up, whenever you synchronize.
202
203
h2. Developing with Eclipse or IntelliJ
204
205
In this section we will add some code to the hello Web app and see how to develop using an integrated development environment like the Eclipse IDE or Jetbrains' IntelliJ IDEA.
206
207
h3. Pre-Requisite
208
209
* Have an Eclipse or IntelliJ installation
210
* Install the Eclipsoid plugin from http://z2-environment.net/eclipsoid/update/site.xml or by searching for "z2" in the IntelliJ Plugin Repository respectively
211
212
h3. Steps we are going to take
213
214
# Complete the development workspace setup
215
# Add a simple Controller
216
217
h4. In Eclipse
218
219
Use the workspace *workspace*. Create a Java project *hello* where we created the *hello* module. That is, we use the existing module as project content. You should now have an Eclipse development workspace that has one Java project named "hello". Right-click on the project and choose "Transform into z2 Project". A small "Z" icon should not decorate the project icon. 
220
221
Add a source folder *java/src.impl* to the project.
222
223
Try "Arm Z2 Projects" and "Disarm Z2 Projects" from the context menu. You should see a LOCAL file showing up and disappearing as well as the "Z" decoration showing a green halo and going back to normal. 
224
225
Go into Window/Preferences, pick "z2-Environment". Change the port to 8081, set the user to "z*" and the password to "z". Done.
226
227
h4. In IntelliJ
228
229
Add a source folder *java/src.impl* to the module.
230
231
Start a new Project with root folder *workspace*. Press the "Manage z2-Modules" button in the toolbar. Import the *hello* module into your IntelliJ project. Open the Settings dialog, pick "z2-Environment". Change the port to 8081, set the user to "z*" and the password to "z". Done.
232
233
h4. Independently of whether you use IntelliJ or Eclipse
234
235
Start z2 as in the previous section but make sure the development support is enabled. Use this command line:
236
237
<pre>
238
java -Dcatalina.home=/home/me/tomcat -jar z.jar org.z2env.dev.shared/ready hello/web
239
</pre>
240
241
(possibly you want to turn this into a shell script)
242
243
*Note:* The _system state_ *org.z2env.dev.shared/ready* will pull up all necessary development support components. Make sure this is part of your to-be-run list.
244
245
246
Regardless whether you are using Eclipse or IntelliJ, press the "Resolve Classpath from Z2" button in the toolbar. This will make sure that all required dependencies for Z2 modules, as far as Java code is concerned, will be resolved for your workspace. 
247
248
Now add a class *SimpleController* and change the following files:
249
250
| java/src.impl/hello/SimpleController.java | 
251
<pre><code class="java">
252
package hello;
253
254
import javax.servlet.*;
255
import javax.servlet.http.*;
256
import java.io.IOException;
257
258
public class SimpleController extends HttpServlet {
259
260
    @Override
261
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
262
        String input = req.getParameter("input");
263
        if (input!=null && input.trim().length()>0) {
264
            req.setAttribute("output","You said: "+input);
265
        }
266
        req.getRequestDispatcher("/").forward(req,resp);
267
    }
268
}
269
</code></pre> |
270
| java/z.properties | 
271
<pre><code class="ruby">
272
org.z2env.component.type = org.z2env.java
273
274
java.privateReferences=\
275
  javax.servlet,\
276
  javax.servlet.jsp.jstl
277
</code></pre> |
278
| web/WebContent/WEB-INF/web.xml | 
279
<pre><code class="xml">
280
<?xml version="1.0" encoding="UTF-8"?>
281
<web-app id="hello" version="2.5"
282
		xmlns="http://java.sun.com/xml/ns/javaee"
283
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
284
		xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
285
286
    <servlet>
287
        <servlet-name>controller</servlet-name>
288
        <servlet-class>hello.SimpleController</servlet-class>
289
    </servlet>
290
    
291
    <servlet-mapping>
292
        <servlet-name>controller</servlet-name>
293
        <url-pattern>/do</url-pattern>
294
    </servlet-mapping>    
295
</web-app>
296
</code></pre> |
297
| web/WebContent/index.jsp |
298
<pre><code class="html">
299
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core_1_1" %>
300
<html>
301
<body>
302
  <c:if test="${not empty output}">
303
    <p><c:out value="${output}"/></p>
304
  </c:if>
305
  <form method="POST" action="<c:url value='/do'/>">
306
    Input: <input type="text" name="input"><input type="submit" value="go!">
307
  </form>
308
</body>
309
</html>
310
</code></pre>|
311
312
Make sure the *hello* module is armed (right-click) by having a LOCAL file.
313
314
Now synchronize your running z2 by either:
315
316
* Pressing the "Sync with z2-Environment" button in the toolbar
317
* Pressing ALT+y in your IDE
318
* Entering "s" on the command line running z2.
319
320
Go to http://localhost:8080/hello and check it out.
321
322
323
h2. Going Multi-Module
324
325
In this section we will extend the previous work by a simple service module. 
326
327
h3. Pre-Requisites
328
329
# Have all the results from the previous section ready.
330
# Start IDE and z2 as above.
331
332
333
h3. Steps we are going to take
334
335
# add a new module with a service API
336
# reference the module API from the *hello* module and invoke the service.
337
338
339
In your workspace, use Eclipsoid to create a new z2 Java module *goodbye*. Open *java/z.properties* and change all *com.zfabrik.* prefixes to *org.z2env*. Essentially the file only needs the line
340
341
<pre><code class="ruby">
342
org.z2env.component.type=org.z2env.java
343
</code></pre>
344
345
In our API we will only expose an interface and rather leave the implementation hidden in the implementation parts of the module. We do that, as we prefer a strong separation of API and implementation. This is not at all required but a conscious design choice. 
346
347
348
| java/src.api/goodbye/GoodbyeService.java | 
349
<pre><code class="java">
350
package goodbye;
351
352
public interface GoodbyeService {
353
354
	String sayGoodbye(String in);
355
	
356
}
357
358
</code></pre> |
359
| java/src.impl/goodbye/GoodbyeServiceImpl.java | 
360
<pre><code class="java">
361
package goodbye;
362
363
public class GoodbyeServiceImpl implements GoodbyeService {
364
365
	@Override
366
	public String sayGoodbye(String in) {
367
		return "Goodbye "+in+"!";
368
	}
369
370
}
371
</code></pre> |
372
| java/service.properties | 
373
<pre><code class="ruby">
374
org.z2env.component.type=org.z2env.any
375
component.className=goodbye.GoodbyeServiceImpl
376
</code></pre> |
377
| java/z.properties | 
378
<pre><code class="ruby">
379
org.z2env.component.type=org.z2env.java
380
</code></pre> |
381
382
In effect we created the following:
383
384
* A module *goodbye* that has 
385
* A Java component with API and Implementation source code
386
* An _any_ component *goodbye/service* that manages the service implementation (as we will see below)
387
388
Back in the *hello* module, we want to use the _goodbye service_. We apply the following changes:
389
390
| java/z.properties | 
391
<pre><code class="ruby">
392
org.z2env.component.type=org.z2env.java
393
394
java.privateReferences=\
395
    javax.servlet,\
396
    javax.servlet.jsp.jstl,\
397
    goodbye
398
</code></pre> |
399
| java/src.impl/hello/SimpleController.java | 
400
<pre><code class="java">
401
package hello;
402
403
import goodbye.GoodbyeService;
404
405
import java.io.IOException;
406
407
import javax.servlet.ServletException;
408
import javax.servlet.http.HttpServlet;
409
import javax.servlet.http.HttpServletRequest;
410
import javax.servlet.http.HttpServletResponse;
411
412
import org.z2env.components.IComponentsLookup;
413
414
public class SimpleController extends HttpServlet {
415
416
    @Override
417
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
418
    	GoodbyeService gb = IComponentsLookup.CL.lookup("goodbye/service", GoodbyeService.class);
419
        String input = req.getParameter("input");
420
        if (input!=null && input.trim().length()>0) {
421
            req.setAttribute(
422
        		"output",
423
        		gb.sayGoodbye(input)
424
        	);
425
        }
426
        req.getRequestDispatcher("/").forward(req,resp);
427
    }
428
}
429
</code></pre> |
430
431
After you have changed the Java references in *java/z.properties* you might want to press Alt-R or the "Resolve Classpath from Z2" button in the toolbar to have the IDE resolve the dependency for the *goodbye* module and so that
432
your IDE will not complain about using the *GoodbyeService* interface.
433
434
Now synchronize your running z2 by either:
435
436
* Pressing the "Sync with z2-Environment" button in the toolbar
437
* Pressing ALT+y in your IDE
438
* Entering "s" on the command line running z2.
439
440
Go to http://localhost:8080/hello and check it out.
441
442
h3. Discussion
443
444
What you just implemented is a programmatic component lookup. The first time <code>IComponentsLookup.CL.lookup("goodbye/service", GoodbyeService.class)</code> was invoked, z2 searched for a factory for *org.z2env.any* components. This specific factory simply created a singleton instance of the Goodbye Service and checked whether the requested interface is implemented. As that held, it returned the actual instance.
445
446
In later sections (for now check out [[z2-environment:How_to_Spring]]) we will explain how to that extends to the Spring Framework and Dependency Injection in general.
447
448
Feel free to apply changes to the Goodbye Service implementation class and have them made effective by synchronizing Z2.
449
450
h2. Going System-Centric
451
452
TBD
453
454
Getting more real by adding a remote repo as system repo.
455
456
Develop by checking out modules and using the Dev Repo.
457
458
459
h2. Understanding the <HOME>
460
461
We call an installation of a z2env core a *<home>*. The file structure of the *<home>* consists of few but important locations
462
463
h3. Layout
464
465
| z.jar | The actual core implementation. This is precompiled.|
466
| boot/ | A component repository adding to the core and provides the most basic capabilities such as compiling Java code and running a main program. |
467
| roots/ | A file system component repository that is always registered by the core. This is typically filled with other repository components linking to remote or local component repositories. |
468
| modules/ | A file system repository declared under roots/ that is useful to locally augment a core installation.|
469
470
We use the modules repository for example for command line experiments and simple hacks. It is not as useful for regular development operations as is the dev repo.
471
472
h3. Folders and Properties
473
474
When running z2 from the command line, some logic is applied to derive where stuff is and some defaults apply:
475
476
|_. What |_. System property |_. Defaults |
477
| Z2 home - the installation location | org.z2env.home | If no system property is set, the environment variable Z2_HOME will be checked. If that is not set, the z2 home location will be derived from the location of the z.jar file |
478
| Dev Repo workspaces - where the Dev Repo checks for local modules | org.z2env.dev.local.workspaces | Defaults to ${z2.home}/.. assuming modules will be next to the home or one level deeper |
479
480
481
h2. Understanding Z2
482
483
Most of the concepts that make up z2 can be derived from the desire to efficiently develop standard Java Web Applications that are defined in a central system definition. Add to that the wish to avoid all that build complexity and the desire for a practically usable modularization approach.
484
485
Once you loose the ability to tweak some build script or configuration to describe how to package a Web app or some libraries, you need some structural hint and simple declarations providing sufficient information.
486
487
Secondy, assuming you want to apply changes at runtime, you need some way of determining what to unload at runtime, given some changed file. Again: Structural information needs to present that maps to runtime state. 
488
489
Finally, as we want some support for modular application development anyway, why not make modules our essential structure. As we have not only code but also Web Applications, Data Sources,  Background Jobs and much more to consider, we add components with type into the mix. Voila.
490
491
*Component Repositories* provides modules and components to z2. A component is prefixed by the module name:
492
493
<pre>
494
<global component name> = <module name>/<local component name>
495
</pre>
496
497
In fact, the typical component repository has a file system style structure that is made up exactly like that. 
498
499
Structure from repo root:
500
501
| /<module>/<cmp>.properties | A component <cmp> in module <module> that has no resources on its own.|
502
| /<module>/<cmp>/z.properties | A component <cmp> in module <module> that may have additional resources on its own.|
503
504
Note that some components, like Web applications and typically Java components have file resources, such as HTML files or Java source code files, while other components, such as main program declarations or data source declarations, so not.
505
506
There are some conventions around this naming scheme. In particular, by convention, whenever a component requires Java implementation, z2 will first look for a component named *java* of the same module. As for example in the Hello World example.
507
508
To give you an idea what this model translates to at runtime consider this: At runtime, the static component is turned into a Resource instance by a component type implementation (that, in fact, is provided by another, built-in component type). 
509
510
!uml1.png!
511
512
Dependencies, for example those between Java components, translate into dependencies between resources that are observed during invalidation of resources. This introduces invalidation and synchronization.
513
514
h3. A crucial concept of z2 is that of a synchronization. 
515
516
For fast development roundtrips and in some cases for general configuration updates, it is desirable to not require a complete restart of a Java Virtual Machine process but rather just to change runtime state accordingly. 
517
518
In z2 a synchronization describes the following process:
519
520
# Check for changes in component repositories
521
# Based on changes found, identify components affected and invalidate associated runtime resources incl. dependent resources.
522
# Try to attain target states
523
524
That is, whenever you do a change and trigger a synchronization from your IDE, this is exactly what happens: Identify what needs to be thrown away, make sure to remove dependent stuff as well,  bring up what needs to be running.
525
526
h3. A second crucial concept of z2 is that of *System Centric Development*
527
528
When working on a software system with many access points and high re-use on a service level, as is typical for business systems, staying quick integration with a team's changes is key. Component repositories can be fed from remotely accessible version control systems such as Subversion and Git. When connecting to a central, team-shared repository, every synchronization will make sure that you are up-to-date with the real source of truth. 
529
530
Using the dev repo, you can still isolate yourself from changes on part of the system that you are actively working on. After your modifications are completed, rebased, and locally tested, getting a clean and consistent state is just one synchronization away.
531
532
h3. The third and final concept is that of a compile-free environment
533
534
It is within the nature of the synchronization concept, that anything required to happen to have your software available for execution must have happened after synchronization completed. Most preparation steps are executed at first use. This includes the compilation of Java code. Z2 uses the Eclipse Java Compiler for that purpose.
535
536
h2. The Component Model
537
538
See [[z2-environment:Z2_Modules_intro]]
539
540
h2. Java Components
541
542
See [[z2-environment:Z2_Java_components_intro]]