Introduction
This document will give you a practical understanding of how Krypton
works, and how you can use it on your own projekts. The walkthrough
takes about 15 minutes to run from start to finish.
In this walkthrough, we will start with an existing project. We will
examine it's structure, and how Krypton has been configured to build
it. Once we are comfortable with the projekt and have seen how we
can build it's artifacts, we will move on to customizing the projekt
and will see how the build can be rewired to cater for new build
requirements.
From
HOWTO: Install Krypton on Windows
Install Krypton
TODO: Insert from HOWTO: Install Krypton
Unpack Walkthrough Projekt
The walkthrough projekt is built from the javacomponent template.
It is deliberately a simple projekt so as not to distract from the
Krypton concepts that we are trying to illustrate here.
First lets get the example projekt:
- Download the walkthrough sample projekt from
SourceForge
- Unzip the projekt somewhere on your workstation, for example:
C:\Work\x17_krypton_walkthroughprojekt_2_0_0_b1
The example projekt's krypton.xml retrieves some environmental meta
data from the file environment.properties in the root of the projekt
directory structure. Open that file in a text editor and check the
values:
- environment.repo.maven2.local should point at a local Maven
2 repository. If you don't have one, just set it to a temp
directory, like C:/temp/Maven2Repo. The directory will be
created if it doesn't already exist. Afterwards you can
delete that directory if you don't want to keep it.
- environment.repo.maven2.remote should point at a
web-accessible remote Maven 2 repository. You can leave
this with it's existing value of
http://www.ibiblio.org/maven if you like, or point it at
another repository if you have one you prefer.
- environment.java.home must point at the root directory of a
JDK installation. Generally a 1.4 or 1.5 JDK is best.
- environment.ant.home must point at the root directory of an
Ant installation. Krypton's Ant-based plugins will work
with Ant 1.5.x or 1.6.x.
Note that you can ignore the Maven 1 repository properties for this
example because the walkthrough projekt doesn't use them. They are
there because they are part of the template projekt, which the
walkthrough was built on.
Now we're ready to start building artifacts from this projekt.
Build Artifacts
Let's take a quick look at the existing artifact definitions in
krypton.xml. Open krypton.xml in a text editor and compare the
artifact declarations you see with this artifact graph:
Let's also take a look at the sources in our projekt:
The main artifact for our projekt is coreapp. This is really the
final produkt as it assembles all the intermediate artifacts
together into a runnable Java application. The coreapp artifact
pulls the log4j_jar and corejar artifacts into it's lib dependency,
the coreclasstree source into it's classtree dependency and the
coreetc source into it's etc dependency.
Okay, let's run a build. Open a shell or command prompt window,
and change directory to the root of the example projekt. Then, run
the command:
> kr coreapp
Krypton will read the krypton.xml descriptor file, and start the
build process. The first thing you'll see in it's output is a
couple of lines that say:
Collecting meta data: com.x1seven.krypton.stdlib.Properties
Collecting meta data: com.x1seven.krypton.stdlib.Component
Krypton is processing each of the metadata bundles defined in
krypton.xml. There are two for our projekt. The first simply reads
environment.properties. The second one (Component) reads both
project.properties and component.properties, and builds up a number
of useful strings that are used to name our various artifacts. For
example, it takes the version number components from
project.properties and builds up the full version string "1.0.0".
Next Krypton analyzes the artifacts and their dependencies, and
figures out what order they must be built in. It generates a
production list, and then works through that list, building each
artifact in turn. You'll now see the output from the artifact
producers:
Producing artifact: log4j_jar
[copy] Copying 1 file to C:\walkthrough_projekt\target\
artifacts\log4j_jar
Producing artifact: coreclasstree
[javac] Compiling 13 source files to C:\walkthrough_projekt\
target\artifacts\coreclasstree
Producing artifact: corejar
[jar] Building jar: C:\walkthrough_projekt\target\artifacts\
corejar\addbk-1.0.0.jar
Producing artifact: coreapp
[mkdir] Created dir: C:\walkthrough_projekt\target\artifacts\
coreapp\lib
[mkdir] Created dir: C:\walkthrough_projekt\target\artifacts\
coreapp\classes
[copy] Copying 1 file to C:\walkthrough_projekt\target\
artifacts\coreapp
[copy] Copying 1 file to C:\walkthrough_projekt\target\
artifacts\coreapp\classes
[copy] Copying 2 files to C:\walkthrough_projekt\target\
artifacts\coreapp\lib
Once the build is finished you'll find that Krypton has create a
"target/artifacts" directory inside the projekt's root directory.
In the artifacts directory you'll find a sub-directory for each
artifact that was built. Browse through those directories to get an
idea about what Krypton has done.
Krypton knows how to clean a build out. In your shell prompt, enter
the command:
kr --cleanall
or
kr –ca
Add an Artifact
Now that we've seen Krypton build artifacts, lets add a new one to
the projekt. For distribution purposes, it would be nice to ZIP the
coreapp artifact up in a version-stamped ZIP file. Krypton has a
ZIP artifact producer that we can use to do this.
Open krypton.xml in a text editor, and add the following artifact
declaration after the coreapp artifact:
<artifact name="distro_zip"
type="com.x1seven.krypton.stdlib.ZipFile">
<setting name="zipFilename" value="${project.identity.name}-
${project.version.full.dotted}.zip" />
<dependency name="files">
<item type="artifact" name="coreapp" />
</dependency>
</artifact>
We are declaring a new artifact called distro_zip
- It will be produced by the ZipFile artifact producer from the
Krypton Standard Library.
- We're setting the zip filename to be named using meta
information we retrieved in a metainfo bundle.
- We've wired the coreapp artifact in as the only item for the
ZipFile producer's files dependency.
Save your changes, and back in your shell prompt type
kr distro_zip
Because we cleaned our build out before, Krypton will re-build all
the intermediate artifacts before building our new distro_zip
artifact.
Alter Meta Info
When designing Krypton, we didn't want to lock projekts into using a
single standardized set of meta-information because we just don't
think it's practical. Every projekt is different, and the type of
meta-information that needs to be available differs across projekts,
so Krypton provides a generic metainfo system. At the same time
though, many development shops (us included) like to have the
metainfo tagged against projekts standardized per projekt-type.
Metainfo bundles are the mechanism you can use to retrieve data from
external sources to be applied to your artifacts, and also to
externalize properties that you don't want to have hard-coded into
your krypton.xml file.
The Properties collector is about as simple as you can get, because
it simply reads name-value pairs from a properties file and exposes
those as a metainfo bundle. Like artifact producers, metainfo
collectors are plugins that can be implemented as Java classes or
Ant scripts, so you can perform more complex logic to build up
metainfo.
An example of a more complex metainfo collector is the
com.x1seven.helium.Component metainfo collector which as we
mentioned before takes values from project.properties and
component.properties and combines them to form a number of useful
strings.
Our example projekt has been setup to retrieve metainfo using the
Properties and Component collectors from the Krypton Standard
Library. The project.properties file which is imported by the
Component collector looks like this:
project.name=addbk
project.version.major=1
project.version.minor=0
project.version.revision=0
#project.version.alpha=
#project.version.beta=
This metainfo is used on our corejar artifact, and on the new
distro_zip artifact that we just created. To use metainfo we just
use reference it using the standard ${name} format. In the corejar
artifact declaration we put a couple of pieces of metainfo together
to come up with the filename for the JAR:
<artifact name="corejar" type="com.x1seven.krypton.stdlib.JarFile">
<setting name="jarFilename" value="${component.identity.id}-
${project.version.full.dotted}.jar" />
<dependency name="classtree">
<item type="artifact" name="coreclasstree" />
</dependency>
</artifact>
Let's make some simple changes to project.properties and check that
it flows through.
- Open project.properties from the root of the example projekt in
your text editor
- Uncomment project.version.beta, and set it's value to 2
- Save your change
Back in your shell prompt clean and re-build the corejar artifact:
kr –ca
kr corejar
Observe that the corejar artifact is now built with the new version
number "1.0.0-b2". The Component metainfo collector took the beta
value and incorporated it into the dotted version number.
Use Operations
Operations are things you can do to completed artifacts. If you
like, artifacts are nouns and operations are verbs. Typical
examples might include an "upload" operation you attached to our
distro_zip artifact to publish it to a distribution server, or a
"publishtomaven" operation to send our corejar artifact to a local
Maven repository.
Krypton builds our projekt, but to try it out, we need to drop into
a command prompt, change directory to the coreapp artifact, and run
the shell script there. To make life easier, let's attach a "run"
operation to the coreapp artifact so we can launch the built app via
Krypton.
In your text editor, find the coreapp artifact, and after the etc
dependency, add the operation declaration shown in bold in the
following code fragment:
<artifact name="coreapp" type="com.x1seven.krypton.stdlib.JavaApp">
<dependency name="lib">
<item type="artifact" name="corejar" />
<item type="artifact" name="log4j_jar" />
</dependency>
<dependency name="classes">
<item type="source" name="coreclasstree" />
</dependency>
<dependency name="etc">
<tem type="source" name="coreetc" />
</dependency>
<operation name="run"
type="com.x1seven.krypton.stdlib.JavaAppRunner">
<setting name="className"
value="com.x1seven.addressbook.ui.CommandLineInterface" />
</operation>
</artifact>
Our operation is called "run", so when we want to invoke it, we'll
issue the command kr coreapp:run
- This operation will be executed by the JavaAppRunner executor
from the Krypton Standard Library.
- We have supplied the name of our application's main class
through the className setting.
- Save your changes
Switch back to your shell prompt and issue the command to invoke
our new run operation:
kr coreapp:run
Krypton will run through the build again to make sure that coreapp
is up to date. It will then invoke our run command, and you'll see
the Address Book application's interactive prompt:
Address Book
>
Note: Type "help" for help on using the address book application,
or "exit" to leave it. It's a very simple app, so don't get too
excited!
Rewire Artifacts
Krypton's artifact-oriented paradigm means that adding new artifacts
into the mix, or restructuring the output of an artifact becomes a
task of re-wiring the build rather than
re-writing it.
As an example, let's say we wanted to generate a JavaDoc bundle for
our source code, and include that in the ZIP file produced for the
distro_zip artifact we added earlier.
First, let's add a new corejavadoc artifact. Add the following
artifact declaration to krypton.xml:
<artifact name="corejavadoc"
type="com.x1seven.krypton.stdlib.Javadoc">
<dependency name="java">
<item type="source" name="corejava" />
</dependency>
</artifact>
Now, when we incorporate corejavadoc artifact into the ZIP file
we'll want it to be in a sub-directory. Let's put it into a
doc/api subdirectory. To do that, we need to define a new artifact
that will take the JavaDoc artifact and package it in a different
subdirectory.
<artifact name="corejavadoc_subdir"
type="com.x1seven.krypton.stdlib.Subdirectory">
<setting name="path" value="doc/api" />
<dependency name="files">
<item type="artifact" name="corejavadoc" />
</dependency>
</artifact>
Now we can wire the JavaDoc into our distro_zip artifact:
<artifact name="distro_zip"
type="com.x1seven.krypton.stdlib.ZipFile">
<setting name="zipFilename" value="${project.identity.name}_
${project.version.full.underscored}.zip" />
<dependency name="files">
<item type="artifact" name="coreapp" />
<item type="artifact" name="corejavadoc_subdir" />
</dependency>
</artifact>
Drop back to your shell prompt, and re-build distro_zip:
kr distro_zip
This time, you'll see Krypton build the corejavadoc and
corejavadoc_subdir artifacts, and then re-create the distro_zip
artifact. When the build is finished, unzip the distro_zip
artifact, and you'll find the corejavadoc artifact inside it in the
subdirectory we wanted, in addition to the built application.
Conclusion
In this walkthrough we have seen the key concepts underlying
Krypton:
- Meta Information / Collectors
- Artifacts / Producers
- Operations / Executors
We have also made a number of adjustements to our projekt and have
seen how these affect our projekt's build.
|