Wednesday, May 24, 2006

Search Engine for Maven 2 (and other Java artifacts) from SourceLabs.

CJAR is the combination of Maven2 structured repository of Java artifacts with powerful Lucene based search engine and related tools.

Tuesday, May 23, 2006

CafeBabe bytecode editor v.1.4 - welcome back!

This is my very old project - I started it probably in 1997-1998.

By using CafeBabe you can view/edit the content of Java bytecodes. Also it understands the format of serialized files. Initially the project had some oprimization/obfuscation tools. I removed them in favor of simplicity.

Project contains libraries that can be used separately:

* classfile - parsing of Java class file;
* serfile - parsing of Java *.ser file;
* MDI - represents Multi Document Interface implementation;
* Net Lib - library for working with sockets (similar to servlet API, but not attached to any container).

Project is well modularized and uses Maven 2 as the build (...) tool.

Scriptlandia 2.1.0 has been released.

Latest update of the Scriptlandia scripting environment, version 2.1.0.

It includes support for such extensions as *.jad, *cwd (classworld file), *.class, *.apt-jelly, *.apt-fmt.

The library of examples has new examples to show what this environment can do.

Friday, May 19, 2006

How to use Ant, Maven2 and Scripting Languages together

I have used Ant tool to organize build process for a long period of time. It's pretty convenient and helps you to organize a lot of useful actions around compilation, packaging, deployment etc.

After some period of time I found that it is very convenient to use "script" task to extend basic functionality of Ant tool or dynamically customize it. For example, Javascript or Beanshell scripting languages are perfect selection for doing this.

The only one thing that Ant doesn't take care of is the project dependency resolution for libraries used within your project. Maven tool is especially designed to solve this problem.

As the result, the following architecture could cover all or the most of possible scenarios for describing build process: Ant + Maven + Some Scripting Language (Beanshell, Javascript, Groovy etc.)

Let me introduce basic steps that help you to solve the problem.


1. Ant tool should be aware of Maven. In order to achieve this, download "Maven Tasks for Ant library" (e.g. maven-artifact-ant-2.x.x-dep.jar) and install it into ${ant.home}/lib directory.


2. Once Maven Tasks for Ant are installed, we can start using them (in project.xml). First of all, describe the namespace for maven tasks:


<project name="myProject" default="run" basedir="."
         xmlns:artifact="antlib:org.apache.maven.artifact.ant">



3. Specify the location of your local Maven repository ("${repository.home}"). Usually it is ${user.home}/.m2, but you can choose any other location. Maven will download dependent libraries and save them inside this repository:

  <property name="repository.home" value="c:/local-maven-repository"/>

  <artifact:localRepository id="local.repository" location="${repository.home}" layout="default"/>



4. Load the Maven project file and assign some id for the project:


  <artifact:pom file="pom.xml" id="maven.project" />


5. Export various classpath variables from the Maven. In the following example we have access to compile-time, run-time and test-time classpath variables:


  <target name="resolve.dependencies">
    <artifact:dependencies pathId="compile.classpath" filesetId="compile.fileset" useScope="compile">
      <pom refid="maven.project"/>
    </artifact:dependencies>

    <artifact:dependencies pathId="runtime.classpath" filesetId="runtime.fileset" useScope="runtime">
      <pom refid="maven.project"/>
    </artifact:dependencies>

    <artifact:dependencies pathId="test.classpath" filesetId="test.fileset" useScope="test">
      <pom refid="maven.project"/>
    </artifact:dependencies>

  </target>



6. Now you can use Ant tasks/targets the same way as before. You don't need to build classpath manually, it will be built dynamically based on the information from "pom.xml" maven file.

You also should be aware of some commonly used properties inside Maven. For example:


${maven.project.build.sourceDirectory} -> src/main/java
${maven.project.build.directory} -> target
${maven.project.build.outputDirectory} -> target/classes
${maven.project.name} - the project name



You can find out other properties here: http://maven.apache.org/maven-model/maven.html.

Let's create basic Ant targets, like clean-compile-jar-run:


  <property name="jar.file" value="${maven.project.build.directory}/${maven.project.name}.jar"/>

  <target name="clean" description="Removes all compiled classes">
    <delete dir="${maven.project.build.directory}"/>
  </target>

   <target name="compile" depends="resolve.dependencies" description="Compiles java sources">
    <mkdir dir="${maven.project.build.outputDirectory}"/>

    <javac destdir="${maven.project.build.outputDirectory}"
           includeAntRuntime="false"
           debug="${debug}"
           optimize="${optimize}"
           deprecation ="${deprecation}">
        <classpath refid="compile.classpath"/>
        <src path="${maven.project.build.sourceDirectory}"/>
    </javac>
  </target>

  <target name="jar" depends="compile" description="Prepare packaging for the project">
    <jar destfile="${jar.file}">
      <fileset dir="${maven.project.build.outputDirectory}"/>
    </jar>
  </target>

  <target name="run" depends="jar">
    <java jar="${jar.file}" fork="true" failonerror="true" maxmemory="128m">
      <classpath>
        <path refid="runtime.classpath"/>
        <pathelement location="${jar.file}""/>
      </classpath>
     </java>
  </target>

  <target name="run.script">
    <script language="beanshell">
      print("Hello, World!");
    </script>
  </target>



7. Your dependencies for the project are expressed in the form of "pom.xml" maven file:

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>your.group.id</groupId>
  <artifactId>your.artifact.id</artifactId>
  <version>your.version</version>

  <name>YourName</name>

  <!-- Here you have to describe all your dependencies. -->
  <dependencies>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>

    ...
  </dependencies>

  </repositories>

</project>


By using this approach we can build scripts of any level of complexity without introducing Java compilation at all. Such programs will contain light-weight code, related to implementation only. All heavy-weight parts of the program will be conveniently located in the repository.

Saturday, May 13, 2006

How to make JavaEE project with Maven2

You want to support multiple modules in your project. Suppose you plan to have these modules:

- Java Module (one or more);
- EJB Module (dependent on Java Module);
- WEB Application Module (dependent on Java and EJB Modules);
- Enterprise Application Module (dependent on Java, EJB and Web Application Module).

First of all, you have to create multi-module project. It is special type of maven project - it does not produce any artifact. Its main purpose is to host modules - single maven projects - and to perform group operations for all modules.

Each single maven project should be aware of parent project. The same is true for parent maven project - it has to be aware about all the children.

The following steps describe whole process of creating such a project.

1. Create multi-project with the following directory structure:

myMultiProject
    myJavaModule1
    myJavaModule2
    ...

    myEJBModule1
    myEJBModule2
    ...

    myWebApplicationModule1
    myWebApplicationModule2
    ...

    myEnterpriseApplicationModule


2. Create maven project "pom.xml" files inside parent directory and inside each child project. Each "pom.xml" file contains specific to given project information.

myMultiProject
    myJavaModule1
        pom.xml
    myJavaModule2
        pom.xml
    ...

    myEJBModule1
        pom.xml
    myEJBModule2
        pom.xml
    ...

    myWebApplicationModule1
        pom.xml
    myWebApplicationModule2
        pom.xml
    ...

    myEnterpriseApplicationModule
        pom.xml

    pom.xml


You can auto-generate "pom.xml" files by using special "archetype:create" command. Only these archetypes are supported now: "quickstart", "webapp", "site", "mojo" and "marmalade-mojo". For our process we can use only 2 first archetypes.

Run these commands:

- for parent multi-project (in the directory where you plan to hst whole project):

>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=myMultiProjectGroupId -DartifactId=myMultiProjectArtifactId -DpackageName= -Dversion=1.0

This command creates the directory with the name specified as artifactId: "myMultiProjectArtifactId". You have to change "packaging" value from "jar" to "pom" inside "pom.xml".

You have to change current directory to "myMultiProjectArtifactId" before running all following commands.

- for Java Module:

>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=myMultiProjectGroupId.myMultiProjectArtifactId -DartifactId=myJavaModule1 -DpackageName=my.new.package -Dversion=1.0

This command creates "myJavaModule1" with minimal set of directories/files for "quickstart" archetype.

- for EJB Module:

>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=myMultiProjectGroupId.myMultiProjectArtifactId -DartifactId=myEJBModule1 -DpackageName=my.new.package -Dversion=1.0

This command creates "myJavaModule" with minimal set of directories/files for "quickstart" archetype.

- for Web Application Module:

>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=myMultiProjectGroupId.myMultiProjectArtifactId -DartifactId=myWebApplicationModule1 -DpackageName=my.new.package -Dversion=1.0

This command creates "myWebApplicationModule1" with minimal set of directories/files for "webapp" archetype.

- for Enterprise Application Module:

>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=myMultiProjectGroupId.myMultiProjectArtifactId -DartifactId=myEnterpriseApplicationModule -DpackageName=my.new.package -Dversion=1.0

This command creates "myEnterpriseApplicationModule" with minimal set of directories/files for "quickstart" archetype.

As you can see, for Java, EJB, Enterprise Application Modules and Multi-Project we use "quickstart" archetype and for Web Application - "webapp" archetype.

The cyclic dependency between parent and children projects should be expressed in the following way: for parent project we have to use "modules" tag, for children projects - "parent" tag.

Parent project's structure looks like this:

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Specify group ID, artifact ID and version for the parent project. -->
  <groupId>myMultiProjectGroupId</groupId>
  <artifactId>myMultiProjectArtifactId</artifactId>
  <version>myMultiProjectVersion</version>

  <!-- 2. Specify "pom" type. This type indicates that this project is parent multi-project. -->
  <packaging>pom</packaging>

  <!-- 3. List all children projects names (name is directory name as well). -->
  <modules>
    <module>myJavaModule1</module>
    <module>myJavaModule2</module>
    ...
    <module>myEJBModule1</module>
    <module>myEJBModule2</module>
    ...
    <module>myWebApplicationModule1</module>
    <module>myWebApplicationModule2</module>
    ...
    <module>myEnterpriseApplicationModule</module>
  </modules>

</project>


Child project's structure looks like this:

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Specify group ID, artifact ID and version for child project. -->
  <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
  <artifactId>myJavaArtifactId</artifactId>
  <version>myJavaModuleVersion</version>

  <!-- 2. Specify the type of the project:
           "jar", "war", "ear". "ejb", "ejb3", "rar", "par", "pom", "maven-plugin" -->

  <packaging>jar</packaging>

  <!-- 3. Specify parameters and the location of the parent project. -->
  <parent>
    <groupId>myMultiProjectGroupId</groupId>
    <artifactId>myMultiProjectArtifactId</artifactId>
    <version>myMultiProjectVersion</version>
    <relativePath>../pom.xml</relativePath>
  </parent>
</project>



3. Java Module


Below is typical "pom.xml" content for Java Module:

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Current project description. -->
   ...
  <packaging>jar</packaging>

  <!-- 2. Reference to parent project. -->
   ...

  <!-- 3. Dependencies on another libraries, projects etc. -->
  <dependencies>
    ...
  </dependencies>

  <!-- 4. Specify the content of generated artifact. -->
  <build>

    <!-- 4.1. Specify the final name of the artifact. -->
    <finalName>myJavaModule1FinalName</finalName>

    <defaultGoal>package</defaultGoal>

    <!-- 4.2. Specify the location of sources (for non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/java -->
    <sourceDirectory>../src/java</sourceDirectory>

    <!-- 4.3. Specify the location of the filter file (if filtering is used). -->
    <filters>
      <filter>target/filter.properties</filter>
    </filters>

    <!-- 4.4. Specify the location of resources (for non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/resources -->
    <resources>
      <resource>
        <directory>../src/resources</directory>
        <filtering>true</filtering>
        <excludes>
          <exclude>*web*.xml</exclude>
        </excludes>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>

          <!-- 4.5. Specify used Java version. -->
          <source>1.5</source>
          <target>1.5</target>

          <!-- 4.6. Specify files to include. -->
          <includes>
            <include>**/com/**</include>
          </includes>

          <!-- 4.7. Specify files to exclude (if required). -->
          <excludes>
            <exclude>com/sun/**/*.java</exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>


4. EJB Module

EJB Nodule is dependent on Java Module:

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Current project description. -->
   ...
  <packaging>ejb</packaging>

  <!-- 2. Reference to parent project. -->
   ...

  <!-- 3. Dependencies on another libraries, projects etc. -->
  <dependencies>
    <!-- 3.1. Specify dependencies on external libraries. -->
    ...

    <!-- 3.2. Specify dependencies on EJB libraries. -->
    <dependency>
      <groupId>javax.ejb</groupId>
      <artifactId>ejb</artifactId>
      <version>2.1</version>

      <!-- 3.2.1. This library is provided by EJB Container. -->
      <scope>provided</scope>
    </dependency>

    <!-- 3.3. Specify dependencies on internal libraries. -->
    <dependency>
      <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
      <artifactId>myJavaModule1ArtifactId</artifactId>
      <artifactId>myJavaModuleVersion</artifactId>

      <!-- 3.3.1. This library is required at runtime. -->
      <scope>runtime</scope>
    </dependency>
  </dependencies>

  <!-- 4. Specify the content of generated artifact. -->
  <build>

    <!-- 4.1. Specify the final name of the artifact. -->
    <finalName>myEJBModule1FinalName</finalName>

    <defaultGoal>package</defaultGoal>

    <!-- 4.2. Specify the location of sources (if you have non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/java -->
    <sourceDirectory>../../src/java</sourceDirectory>

    <!-- 4.3. We don't want to filter for this module: "filters" section is empty. -->

    <!-- 4.4. Specify the location of resources (for non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/resources -->
    <resources>
      <resource>
        <directory>../src/java/META-INF</directory>
        <targetPath>META-INF</targetPath>
        <filtering>false</filtering>
        <excludes>
          <exclude>*application*.xml</exclude>
        </excludes>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <!-- 4.5. Specify used Java version. -->
          <source>1.5</source>
          <target>1.5</target>

          <!-- 4.6. Specify files to include. -->
          <includes>
            <include>**/ejb/**</include>
          </includes>

          <!-- 4.7. Nothing to exclude. -->
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>



5. WEB Application Module

Web Application Module is dependent on Java and EJB Modules.

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Current project description. -->
   ...
  <packaging>war</packaging>

  <!-- 2. Reference to parent project. -->
   ...

  <!-- 3. Dependencies on another libraries, projects etc. -->
  <dependencies>
    <!-- 3.1. Specify dependencies on external libraries. -->
    ...

    <!-- 3.2. Specify dependency on servlet API library. -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.4</version>

      <!-- 3.2.1. This library is provided by Web Container. -->
      <scope>provided</scope>
    </dependency>

    <!-- 3.3. Specify dependency on JSP API library (if required). -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>

      <!-- 3.3.1. This library is provided by WEB Container. -->
      <scope>provided</scope>
    </dependency>

    <!-- 3.4. Specify dependency on other web libraries: tags, struts, tiles etc... (if required). -->
    ...

    <!-- 3.5. Specify dependency on database driver (if required). -->
    <dependency>
      <groupId>oracle</groupId>
      <artifactId>oracle-driver</artifactId>
      <version>9.2.0.5.0</version>
    </dependency>

    <!-- 3.6. Specify dependencies on EJB libraries (if required). -->
    <dependency>
      <groupId>javax.ejb</groupId>
      <artifactId>ejb</artifactId>
      <version>2.1</version>

      <!-- 3.6.1. This library is provided by EJB Container. -->
      <scope>provided</scope>
    </dependency>

    <!-- 3.7. Specify dependencies on internal libraries. -->
    <dependency>
      <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
      <artifactId>myJavaModule1ArtifactId</artifactId>
      <artifactId>myJavaModule1Version</artifactId>

      <!-- 3.7.1. This library is required at runtime. -->
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
      <artifactId>myEJBModule1ArtifactId</artifactId>
      <artifactId>myEJBModule1Version</artifactId>

      <!-- 3.7.2. This library is required at runtime. -->
      <scope>runtime</scope>
    </dependency>

  </dependencies>

  <!-- 4. Specify the content of generated artifact. -->
  <build>

    <!-- 4.1. Specify the final name of the artifact. -->
    <finalName>myWebApplicationModule1FinalName</finalName>

    <defaultGoal>package</defaultGoal>

    <!-- 4.2. Specify the location of sources (if you have non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/java -->
    <sourceDirectory>../src/java</sourceDirectory>

    <!-- 4.3. We don't want to filter for this module: "filters" section is empty. -->

    <!-- 4.4. Specify the location of resources (for non-standard location). -->
    <!-- Defailt is: ${basedir}/src/main/resources -->
    <resources>
      <resource>
        <directory>../src/config</directory>
        <filtering>false</filtering>
        <includes>
          <include>*.properties</include>
        </includes>
      </resource>

      <resource>
        <directory>../src/resources</directory>
        <filtering>false</filtering>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <!-- 4.5. Specify used Java version. -->
          <source>1.5</source>
          <target>1.5</target>

          <!-- 4.6. Specify files to include. -->
          <includes>
            ...
          </includes>

          <!-- 4.7. Specify files to exclude (if required). -->
          <excludes>
            ...
          </excludes>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <!-- 4.8. Specify the location of Web Application directory (if non-standard). -->
          <!-- Defailt is: ${basedir}/src/main/webapp -->
          <warSourceDirectory>../src/web</warSourceDirectory>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>


6. Enterprise Application Module

This module performs main assembly work plus adds some application-level resources, like "application.xml" file. You have to list all the modules to be included into "ear" file in "dependencies" section. Each module should be marked with the corresponding type: "jar", "war", "ejb", "ejb3", "ejb-client", "rar", "par", "sar".

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Current project description. -->
   ...
  <packaging>ear</packaging>

  <!-- 2. Reference to parent project. -->
   ...

  <!-- 3. Dependencies on another modules within the multi-module project. -->
  <dependencies>
    <dependency>
      <!-- 3.1. Dependency on Java Module. -->
      ...
      <type>jar</type>

      <!-- 3.2. We need to include this module into application.xml; required by EJB module. -->
      <includeInApplicationXml>true</includeInApplicationXml>
    </dependency>

    <dependency>
      <!-- 3.3. Dependency on EJB Module. -->
      ...
      <type>ejb</type>
    </dependency>

    <dependency>
      <!-- 3.4. Dependency on Web Application Module. -->
      <type>war</type>
    </dependency>
  </dependencies>

  <!-- 4. Specify the content of generated artifact. -->
  <build>

    <!-- 4.1. Specify the final name of the artifact. -->
    <finalName>myEnterpriseApplicationModuleFinalName</finalName>

    <defaultGoal>package</defaultGoal>

    <!-- 4.2. We don't want to filter for this module: "filters" section is empty. -->

    <!-- 4.3. Specify the location of resources (for non-standard location). -->
    <!-- Defailt is: ${project.build.outputDirectory} -->
    <!-- The file: application.xml will be automatically generated. -->
    <resources>
      <resource>
        <directory>../src/java/META-INF</directory>
        <targetPath>META-INF</targetPath>
        <filtering>false</filtering>
        <includes>
          <include>weblogic-application.xml</include>
        </includes>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>

        <!-- 4.4. Specify used Java version. -->
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
        <configuration>

          <!-- 4.5. Specify modules to include. -->
          <modules>

            <!-- 4.5.1. Include Java Module. -->
            <javaModule>
              <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
              <artifactId>myJavaModule1ArtifactId</artifactId>
              <artifactId>myJavaModule1Version</artifactId>

              <!-- 4.5.1.1. Only if you want different file name inside "ear" file. -->
              <bundleFileName>myBundleJavaModule1FileName</bundleFileName>
            </javaModule>

            <!-- 4.5.2. Include EJB Module. -->
            <ejbModule>
              <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
              <artifactId>myEJBModule1ArtifactId</artifactId>
              <artifactId>myEJBModule1Version</artifactId>

              <!-- 4.5.2.1. Only if you want different file name inside "ear" file. -->
              <bundleFileName>myBundleEJBModule1FileName</bundleFileName>
            </ejbModule>

            <!-- 4.5.3. Include Web Application Module. -->
            <webModule>
              <groupId>myMultiProjectGroupId.myMultiProjectArtifactId</groupId>
              <artifactId>myWebApplicationModule1ArtifactId</artifactId>
              <artifactId>myWebApplicationModule1Version</artifactId>

              <!-- 4.5.3.1. Only if you want different file name inside "ear" file. -->
              <bundleFileName>myBundleWebApplicationModule1FileName</bundleFileName>

              <!-- 4.5.3.2. Specify the context root if you need different name. -->
              <!-- Default is: "/${pom.artifactId} -->
              <contextRoot>iris</contextRoot>
            </webModule>

            <!-- 4.5.4. Maven will also treat dependent 3-rd-party libraries as modules.
                        You have to exclude them or redirect to "APP-INF/lib" directory. -->
            <javaModule>
              <groupId>antlr</groupId>
              <artifactId>antlr</artifactId>
              <bundleDir>APP-INF/lib</bundleDir>
            </javaModule>
            ...

          </modules>
        </configuration>
      </plugin>

    </plugins>
  </build>

</project>



7. Parent multi-project

Parent project can be used as convenient way to execute group commands, When you run particular command on the project, it executes this command for all children projects. Maven is able to discover the correct execution order and to detect circular dependencies.

<project>
  <modelVersion>4.0.0</modelVersion>

  <!-- 1. Parent multi-project description. -->
   ...
  <packaging>pom</packaging>

  <!-- 2. Chlidren modules description. -->
  <modules>
    ...
  </modules>

  <build>
    <defaultGoal>package</defaultGoal>
   
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <!-- 3. Specify used Java version. -->
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>

    </plugins>
  </build>

</project>



8. Usage

Now you can execute group commands, for example:

>mvn compile
>mvn install
>mvn site


These commands perform operations for each module sequentially.

Monday, May 01, 2006

How to make JavaME project with Ant

I prepared Ant script that can be used for the most of Java ME projects. It encapsulates all low-level detail dealing with tools/callses from Java ME platform.

1. Specify project name and default target:

<project name="MyFirstMidlet" default="compile" basedir=".">


2. Define useful properties that will be used throughout the project:

  <property name="java.mobile.home" value="c:/Java/j2me-2.3"/>

  <property name="midlet.class.name" value="${ant.project.name}"/>
  <property name="src.dir" value="src"/>
  <property name="target.dir" value="target"/>

  <property name="midlet.command.line" value=""/>



3. Specify the classpath that includes core mobile API and required extension APIs, e.g.:

  <path id="mobile.classpath">
    <pathelement location="${java.mobile.home}/lib/cldcapi11.jar"/>
    <pathelement location="${java.mobile.home}/lib/midpapi20.jar"/>

    <pathelement location="${java.mobile.home}/lib/wma20.jar"/>
    <pathelement location="${java.mobile.home}/lib/mmapi.jar"/>
    <pathelement location="${java.mobile.home}/lib/j2me-ws.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr75.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr082.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr184.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr179.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr177.jar"/>
    <pathelement location="${java.mobile.home}/lib/jsr211.jar"/>
  </path>


4. We need to create string version of our classpath. It will be used for executables, like "preverified.exe" and "emulator.exe":

    <property name="mobile.classpath" refid="mobile.classpath"/>

5. Prepare "compile" target. Keep in mind that target attribute should be on "1.1" level:

  <target name="compile">
    <mkdir dir="${target.dir}/classes"/>

    <javac srcdir="${src.dir}" destdir="${target.dir}/classes"
           bootclasspathref="mobile.classpath"
           source="1.1" target="1.1"/>

  </target>


6. Compiled classes should be "preverified". It means that each class file in "classes" directory will have corresponding "preverified" class file in "preverified" directory.

  <target name="preverify" depends="compile">
    <mkdir dir="${target.dir}/preverified"/>

    <exec executable="${java.mobile.home}/bin/preverify">
      <arg line="-classpath ${mobile.classpath}"/>
      <arg line="-d ${target.dir}/preverified"/>
      <arg line="${target.dir}/classes"/>
    </exec>
  </target>


7. Resulting jar file will contain "preverified" classes and resources from "res"
directory:

  <target name="jar" depends="preverify">
    <mkdir dir="${target.dir}/bin"/>

    <jar basedir="${target.dir}/preverified"
         jarfile="${target.dir}/bin/${ant.project.name}.jar"
         manifest="bin/MANIFEST.MF">
      <fileset dir="res"/>
    </jar>

    <copy file="bin/${ant.project.name}.jad"
          tofile="${target.dir}/bin/${ant.project.name}.jad"/>

  </target>



8. In order to run generated artifact you have to launch the emulator. You can run
emulator as executable file or as java class.

- as executable:

  <target name="run2" depends="jar">
    <exec executable="${java.mobile.home}/bin/emulator">
      <!-- device: DefaultColorPhone, DefaultGrayPhone, MediaControlSkin, QwertyDevice -->
      <arg line="-Xdevice:DefaultColorPhone"/>
      <arg line="-Xdescriptor:${basedir}/${target.dir}/bin/${ant.project.name}.jad"/>

      <arg line="-classpath ${mobile.classpath};${basedir}/${target.dir}/bin/${ant.project.name}.jar"/>
    </exec>
  </target>


- as java class:

  <target name="run" depends="jar">
    <java fork="yes" classname="com.sun.kvem.environment.EmulatorWrapper">
      <sysproperty key="kvem.home" value="${java.mobile.home}"/>
      <sysproperty key="java.library.path" value="${java.mobile.home}/bin"/>
      <sysproperty key="sun.java2d.ddlock" value="true"/>
      <sysproperty key="sun.java2d.gdiblit" value="false"/>

      <arg line="-Xdevice:DefaultGrayPhone"/>
      <arg line="-Xdescriptor:${basedir}/${target.dir}/bin/${ant.project.name}.jad"/>

      <arg line="-classpath ${mobile.classpath};${target.dir}/bin/${ant.project.name}.jar"/>
      <arg line="${midlet.class.name}"/>
      <arg line="${midlet.command.line}"/>
      <arg line="0"/>
    </java>
  </target>