Posts tagged: Ant

Eclipse Oxygen.1 with ANT and JRE6

Post to Twitter

Long awaited, now it's here :)
The support for ANT and JRE6 with Eclipse Oxygen.1 (September 2017).

This is a follow-up post for: Eclipse NEON with ANT and JRE6

The plugin was created for:

Version: Oxygen.1 Release (4.7.1)
Build id: 20170914-1200

Don't forget the -clean start (read the original article for more details)!

Download the plugin from here. It works for us - no warranty!

For more details about the installation, read this article.

Eclipse NEON with ANT and JRE6

Post to Twitter

This is a follow-up post for: Eclipse MARS with ANT and JRE 6 (story).

New Eclipse version, same problem. We have an updated ant plugin for you.
The plugin was created for:

Version: Neon Release (4.6.0)
Build id: 20160613-1800

Don't forget the -clean start (read the original article for more details).

Download the plugin from here. It works for us - no warranty!

Eclipse MARS with ANT and JRE 6 (story)

Post to Twitter

Eclipse Mars is available since June 25th. We didn't update our IDEs because it wasn't needed.

Some days ago we played around with JavaFXPorts Eclipse plugin. This plugin requires Eclipse Mars. So far so good. We made some tests with Mars, and everything was fine. We installed all required plugins for our internal and customer projects and configured a first workspace....
After everything was done, we tried to work with Eclipse Mars - no problems... BUT we have many projects with Java 6 compatibility.

Why Java 6?

Some big legacy projects/applications and Oracle Forms compatibility. There are more reasons, but it's not unusual to be backwards compatible, especially for frameworks and libraries!

Long story, short: It's not possible to start an ANT task with Java 6, because Java 7 is required. A nice error message appears:

JRE version less than 1.7 is not supported.

BUT it's still possible to choose any JRE in Runtime configuration dialog.
Why shouldn't it be possible to start ANT with "any" JRE?

We tried to find help in the world wide web and found some postings about our problem:

http://stackoverflow.com/questions/31052878/run-eclipse-mars-with-java-1-6
http://stackoverflow.com/questions/31808102/eclipse-mars-ant-doesnt-support-jdk-1-6-anymore

And two bug database entries:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=474386
https://bugs.eclipse.org/bugs/show_bug.cgi?id=461031

It's absolutely incomprehensible why the first ticket is in state: RESOLVED INVALID and the
second one: VERIFIED FIXED.
OK, the second one was for a different requirement, but the first one explains the problem.

Why did the developer ignore the user requirement?

It's possible to call ANT with "any" JRE, without Eclipse and other IDEs don't have such crazy limitations! We didn't plan to use another IDE just for building our software!

I can't live with recommended workarounds because suggested steps were not usuable with big projects!
So, we tried to solve the problem for us. The source code of the ANT plugin is available here, so it shouldn't be a problem to "fix" the problem.

After reading source code, we found that the only reason why it's not possible to use JREs < version 7, is Java 7 Syntax:

  • Diamond operator, e.g. List<MyObject> list = new ArrayList<>();
  • try-with-resources, e.g. try (InputStream stream = createInputStream()) { ...}

And of course, the plugin was configured for execution environment JavaSE-1.7.

Our solution: Removed Java version check in class org.eclipse.ant.internal.launching.launchConfigurations.AntLaunchDelegate, method launch:

//String path = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, new String("")); //$NON-NLS-1$
//if (!path.isEmpty()) {
//      IPath jrePath = Path.fromPortableString(path);
//      IVMInstall vm = JavaRuntime.getVMInstall(jrePath);
//      if (vm instanceof AbstractVMInstall) {
//              AbstractVMInstall install = (AbstractVMInstall) vm;
//              String vmver = install.getJavaVersion();
//              // versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.9, etc
//              if (vmver.length() > 3) {
//                      vmver = vmver.substring(0, 3);
//              }
//              int ver = (int) (CompilerOptions.versionToJdkLevel(vmver) >>> 16);
//              if (ver < ClassFileConstants.MAJOR_VERSION_1_7) {
//                      // IStatus status = new Status(IStatus.ERROR, AntLaunching.PLUGIN_ID, 1,
//                      // AntLaunchConfigurationMessages.AntLaunchDelegate_Launching__0__2, null);
//                      // throw new CoreException(status);
//              }
//      }
//}

We set the execution environment for org.eclipse.ant.launching, org.eclipse.ant.core and org.eclipse.ant.ui to JavaSE-1.6 and made the source code compatible with Java 6 syntax.

After we built the required jar files, we had problems with Eclipse, because there was something like a plugin cache (not sure what exactly). We made a test with -clean command line parameter and were happy. It was possible to start ANT tasks - with JRE 6 - without modifications, directly via Eclipse.

It's not difficult to create your own ANT plugin, but here are our jar files.
The libs were built for

Version: Mars Release (4.5.0)
Build id: 20150621-1200

The tag-id of the ANT plugin source code: I20150430-1445.

Installation?

  • Download the zip archive, extract the content to <eclipse_dir>/plugins.
  • Start eclipse with parameter -clean (only once)
  • Configure JRE6 for your ANT task, via Externals Tool configuration...

Feel free to use our changed files but we don't guarantee that it doesn't destroy your Eclipse Mars installation :)
We didn't have any problems so far, but send us your impressions.

We didn't publish the changed source code right now, but let us know if you need it - it's still under EPL.

Maven deployment via Ant

Post to Twitter

We are no Maven lovers, because it helps to forget how things work. But we think the dependency management is useful. It's great for developers who need specific library versions without managing them manually.

The user aspect is one thing, but nobody tells you that it's not trivial to release libraries. One problem is the pre-deployment process. Before you are able to deploy your jar files, you have to do a lot of things like GPG key generation, publishing GPG key, find the right repository, prepare your build, special pom cration and so on.

If you already have release builds with version numbers, javadoc and source archives, you'll save a lot of time. If you don't have complete and clean release builds - see you later.

Let's start with a good documentation about requirements:
https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide

Of course, it assumes that you'll use Sonatype as your repository, but all others are not too different.

This posting is not a complete documentation. It simply shows the problems we had.

Our simple pom files:
pom.xml (jvxall)
pom.xml (jvxclient)

The first is with dependencies and the second without, because our client doesn't have dependencies.

The real problems started with the integration in our ant script, because the documentation of Maven plugins were awful. It's easier to read the source code than to find out how plugins work. One example: Read following plugin documentation and tell me the valid values for "types" and "classifier". There are no examples on the page! Google around and copy/paste a little bit - awful!

Here's a working ant call

<typedef resource="org/apache/maven/artifact/ant/antlib.xml"
            uri="antlib:org.apache.maven.artifact.ant"
            classpath="${build}/maven/maven-ant-tasks-2.1.3.jar" />

<condition property="gpgexecutable"
     value="C:\Program Files\GNU\GnuPG\pub\gpg.exe" else="gpg">
    <and>
        <os family="Windows" />
   </and>
</condition>

<artifact:mvn>
    <arg value="org.apache.maven.plugins:maven-gpg-plugin:1.4:sign-and-deploy-file" />
    <arg value="-Durl=${mvn.url}" />
    <arg value="-DrepositoryId=${mvn.id}" />
    <arg value="-DpomFile=${maven.tmp}/jvxall/pom.xml" />
    <arg value="-Dfile=${mvn.jvx.jar}" />
    <arg value="-Dfiles=${mvn.jvx.sources.jar},${mvn.jvx.javadoc.jar}" />
    <arg value="-Dclassifiers=sources,javadoc" />
    <arg value="-Dtypes=jar,jar" />
    <arg value="-Pgpg" />
    <arg value="-Dgpg.executable=${gpgexecutable}" />
</artifact:mvn>

Above call submits e.g. jvx-1.1.jar, jvx-1.1-javadoc.jar and jvx-1.1-sources.jar to the repository.

Why one call instead of 3 separate calls, as described in the documentation?

Short: It's better :)
Long: It's better to submit all dependent files in one "maven session". Above call creates a new maven project and if you call this command per file, there's no logical connection between them. If you plan to deploy snapshot releases - forget it - it doesn't work with different calls because every upload gets a new buildnumber. But all files need the same buildnumber! Such deployments can't be used. If you read the Sonatype document, you saw that "deploy" task didn't deploy javadoc and sources! The "stage" task did. I'm not sure, but I think they had the same problem with separate uploads! Trust me, above call works with snapshots and final releases.

Our naming conventions

<property name="mvn.jvx.jar" value="${release}/maven/${release.name}-${versionnumber}${maven.version.postfix}.jar" />
<property name="mvn.jvx.sources.jar" value="${release}/maven/${release.name}-${versionnumber}${maven.version.postfix}-sources.jar" />
<property name="mvn.jvx.javadoc.jar" value="${release}/maven/${release.name}-${versionnumber}${maven.version.postfix}-javadoc.jar" />

(${maven.version.postfix} is -SNAPSHOT for snapshot releases and empty for final releases)

Repository Id, URL

${mvn.id} = sonatype-nexus-staging
${mvn.url} = https://oss.sonatype.org/service/local/staging/deploy/maven2

Other problems?

Proxy settings for Maven, Use an external GPG key, Autentication.

If you copy the following settings.xml to <users.home>/.m2 and modify it to fit your needs, it should solve all problems:

<?xml version="1.0" encoding="UTF-8"?>

<settings>
  <servers>
    <server>
      <id>sonatype-nexus-snapshots</id>
      <username>username</username>
      <password>password</password>
    </server>
    <server>
      <id>sonatype-nexus-staging</id>
      <username>username</username>
      <password>password</password>
    </server>
  </servers>
  <profiles>
    <profile>
      <id>gpg</id>
      <properties>
        <gpg.passphrase>gpgkey</gpg.passphrase>
      </properties>
    </profile>
  </profiles>
  <proxies>
    <proxy>
      <id>firewall</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>10.0.0.1</host>
      <port>3128</port>
      <username></username>
      <password></password>
      <nonProxyHosts>localhost,127.0.0.1</nonProxyHosts>
    </proxy>
    <proxy>
      <id>firewall-2</id>
      <active>true</active>
      <protocol>https</protocol>
      <host>10.0.0.1</host>
      <port>3128</port>
      <username></username>
      <password></password>
      <nonProxyHosts>localhost,127.0.0.1</nonProxyHosts>
    </proxy>
  </proxies>
</settings>

We configured the proxy via ant build.xml

<target name="proxy.check">
  <condition property="proxy.enabled">
    <and>
      <socket server="10.0.0.1" port="3128"/>
    </and>
  </condition>
</target>

<target name="proxy" depends="proxy.check" if="proxy.enabled">
  <property name="proxy.host" value="10.0.0.1"/>
  <property name="proxy.port" value="3128"/>
  <property name="proxy.user" value=""/>
  <property name="proxy.pass" value=""/>
   
  <setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
            proxyuser="${proxy.user}" proxypassword="${proxy.password}"/>
</target>

Simply add "proxy" task as dependency of another task.

Maybe it's easier to release libraries with other build systems or maybe it works out-of-the-box with Maven itself, but the whole process is really bad.

Good luck!