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.

Contents

Other Pages