Monday, July 23, 2018

GeoTools Hello World on the Mac

Last time I did a hello world on Linux (Debian Testing).  This time, I'm going to go through trying it on the Mac.  If you use home brew, mac ports, or something else, you may see something different.  Also, my install of Java 9 on my mac isn't likely 100% normal.  I'm too new to know the differences.

The resulting pom.xml and App.java are exactly the same as with my prior post, which is the way it is supposed to be!

https://gist.github.com/schwehr/b433076cab0cdb99c61163c6fb56bf7f

Getting setup with JAVA_HOME is where I hit some speed bumps.  But they turned out not to be too bad.  So I know this is where I want to end up pointing my JAVA_HOME:

/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home

But first, I wanted to see what else is around.  Here is my default path:

type javac
javac is /usr/bin/javac

javac --version
javac 9

java --version
java 9
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

I wanted to see if I could use the default /usr/bin stuff.  Before I try that, I need to install maven.  I use fink, but I bet brew and macports have it too.

fink install maven

mvn --version
Error: JAVA_HOME is not defined correctly.
  We cannot execute /usr/libexec/java_home/bin/java

Uh oh!  Time to see what /usr has.

ls -ld /usr/libexec/java_home 
lrwxr-xr-x  1 root  wheel  79 Jan 31 14:36 /usr/libexec/java_home -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java_home

find /System/Library/Frameworks/JavaVM.framework/Versions -name javac
/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/javac

That doesn't look like the correct structure, so I'm going to avoid that and go with what I originally thought would work:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home

mvn --version
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /sw/share/maven
Java version: 9, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.6", arch: "x86_64", family: "mac"

So now it looks like I've got maven and a probably working Java env.  Time to start building the app.  Start by creating a space to work on it and create the initial project:

cd && mkdir maven && cd maven

mvn --batch-mode archetype:generate -DgroupId=com.example -DartifactId=geotools-hello -DarchetypeGroupId=org.apache.maven.archetypes

Now checkout what's in the default setup:

cd geotools-hello/

tree -d

find . -type f
./pom.xml
./src/test/java/com/example/AppTest.java
./src/main/java/com/example/App.java

Can I build anything with it?

mvn compile

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] Source option 1.5 is no longer supported. Use 1.6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.
[INFO] 2 errors 
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE

Nope!  This is the same issue I had on Linux.  Time to start editing the pom.xml file.  Add this:

  <properties>
    <maven.compiler.source>1.9</maven.compiler.source>
    <maven.compiler.target>1.9</maven.compiler.target>
  </properties>

Now is is actually able to build and run the application!  I added a line to print out the Java version.  On the Mac, I'm seeing "9", while on Linux I was seeing 9.0.4.

mvn compile exec:java -Dexec.mainClass="com.example.App"
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/org/codehaus/mojo/exec-maven-plugin/maven-metadata.xml
[SNIP]
Downloaded: https://repo.maven.apache.org/maven2/org/codehaus/mojo/exec-maven-plugin/1.6.0/exec-maven-plugin-1.6.0.jar (57 KB at 434.0 KB/sec)
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building geotools-hello 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ geotools-hello ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/schwehr/maven/geotools-hello/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ geotools-hello ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/schwehr/maven/geotools-hello/target/classes
[INFO] 
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ geotools-hello ---
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting-api/2.2.1/maven-reporting-api-2.2.1.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting-api/2.2.1/maven-reporting-api-2.2.1.pom (2 KB at 15.1 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting/2.2.1/maven-reporting-2.2.1.pom

[SNIP]

Downloaded: https://repo.maven.apache.org/maven2/commons-cli/commons-cli/1.2/commons-cli-1.2.jar (41 KB at 161.3 KB/sec)
Downloaded: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar (238 KB at 730.6 KB/sec)
Hello World!
9

Now I change App.java to include.  It works!

mvn compile exec:java -Dexec.mainClass="com.example.App"
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building geotools-hello 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ geotools-hello ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/schwehr/maven/geotools-hello/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ geotools-hello ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/schwehr/maven/geotools-hello/target/classes
[INFO] 
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ geotools-hello ---
Hello World!
9
GeoTools version 20-SNAPSHOT (built from rc52833cadf758699a1969d258ab6172b305f9416)
Java version: 9
Operating system: Mac OS X 10.13.6
GeoTools jars on classpath:

Tuesday, July 3, 2018

GeoTools hello world

I just wanted to get started playing with GeoTools.  When you are a beginner to Java, Maven, and GeoTools, it's impressive how many pitfalls there are.  I did just about everything wrong and found all sorts of dark alleys that involved my machine downloading junk for a hour and then declaring failure.  I can't believe how much time it took me to figure out how to get this to work on my Linux workstation.

Now that I have it working, it's time to document what I did.  My environment is pretty close to Debian Testing.  You will probably find things in this description that don't work for you.  I've redacted a few little things here and there, so expect the output you see to be much more verbose.

App.java and pom.xml as I have them at the end of this are here:

https://gist.github.com/schwehr/b433076cab0cdb99c61163c6fb56bf7f

The first hurdle is installing Java and the JDK.  I've got Java 9 preinstalled on my workstation in a funky location, so pardon that confusion.  Java lives here for me:

ls /usr/local/buildtools/java

The first thing I need to do is be explicit about which version of Java to use.  My system is setup to default to Java 8, and why not live from head?

export JAVA_HOME=/usr/local/buildtools/java/jdk9

$JAVA_HOME/bin/java -version
openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+11)
OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)

Now I need Apache Maven to control the build and run process.

apt-cache show maven | grep Ver
Version: 3.5.0-5

sudo apt-get install maven

mvn -version
Apache Maven 3.5.0
Maven home: /usr/share/maven
Java version: 9.0.4
Java home: /usr/local/buildtools/java/jdk9
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.9.0-6-amd64", arch: "amd64", family: "unix"

Where is maven?

ls -l /usr/bin/mvn
lrwxrwxrwx 1 root root 21 May 24 21:56 /usr/bin/mvn -> /etc/alternatives/mvn

readlink -f /usr/bin/mvn
/usr/share/maven/bin/mvn

dpkg -S `readlink -f /usr/bin/mvn`
maven: /usr/share/maven/bin/mvn

Let's start a project that will be our starter.

mkdir maven && cd maven

mvn --batch-mode archetype:generate -DgroupId=com.example -DartifactId=geotools-hello -DarchetypeGroupId=org.apache.maven.archetypes

tree -d

cd geotools-hello

find .
.
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/com
./src/main/java/com/example
./src/main/java/com/example/App.java
./src/test
./src/test/java
./src/test/java/com
./src/test/java/com/example
./src/test/java/com/example/AppTest.java

mvn compile

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] Source option 1.5 is no longer supported. Use 1.6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.

Well, that sucks!  I've got Java 9 and this thing is trying to use 1.5?  According to Java version history, 2004 is calling and they want their old Java back.  Edit the pom.xml and tell it to get to at least the year 2017.

  <properties>
    <maven.compiler.source>1.9</maven.compiler.source>
    <maven.compiler.target>1.9</maven.compiler.target>
  </properties>

Try it again and it should work.

mvn compile

mvn exec:java -Dexec.mainClass="com.example.App"
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building geotools-hello 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ geotools-hello ---
Hello World!

Now we want to make sure the java version is what we expect.  Edit src/main/java/com/example/App.java to look like this:

package com.example;

import java.lang.System;

public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        System.out.println(System.getProperty("java.version"));
    }
}

Running it should now give a little bit more info.  We can compile and run in one maven command.  The commands added will be run in the order given on the command line.

mvn compile exec:java -Dexec.mainClass="com.example.App"
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building geotools-hello 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ geotools-hello ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /usr/local/google/home/schwehr/maven/geotools-hello/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.6.1:compile (default-compile) @ geotools-hello ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /usr/local/google/home/schwehr/maven/geotools-hello/target/classes
[INFO] 
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ geotools-hello ---
Hello World!
9.0.4

So we indeed have java 9.  Woot!

Now on to trying to do the simplest possible thing I can think of with GeoTools.  Can we print the version information?  Finding the GeoTools.getAboutInfo() method took me way to long.  Sigh.

Edit the App.java file to import org.geotools.factory.GeoTools and call the static method:

package com.example;

import java.lang.System;
import org.geotools.factory.GeoTools;

public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        System.out.println(System.getProperty("java.version"));
        System.out.println(GeoTools.getAboutInfo());
    }
}

Next you need to make your pom.xml match mine.  You need to add the geotools version to the properties.  Then you need to add the gt-metadata library to the dependencies.    And then add the repositories where the dependencies can be found.

  <properties>
    <maven.compiler.source>1.9</maven.compiler.source>
    <maven.compiler.target>1.9</maven.compiler.target>

    <geotools.version>20-SNAPSHOT</geotools.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.geotools</groupId>
      <artifactId>gt-metadata</artifactId>
      <version>${geotools.version}</version>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <id>maven2-repository.dev.java.net</id>
      <name>Java.net repository</name>
      <url>http://download.java.net/maven/2</url>
    </repository>
    <repository>
      <id>osgeo</id>
      <name>Open Source Geospatial Foundation Repository</name>
      <url>http://download.osgeo.org/webdav/geotools/</url>
    </repository>
    <repository>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <id>boundless</id>
      <name>Boundless Maven Repository</name>
      <url>http://repo.boundlessgeo.com/main</url>
    </repository>
  </repositories>

Now try it and hopefully you will succeed with the about showing you a couple of lines about GeoTools.

mvn compile exec:java -Dexec.mainClass="com.example.App"

Hello World!
9.0.4
GeoTools version 20-SNAPSHOT (built from r9accd1de3af6dcbd69ee56eebd4375a5b5ceb19b)
Java version: 9.0.4
Operating system: Linux 4.9.0-6-amd64
GeoTools jars on classpath:

Finding that GeoTools.getAboutInfo() was in gt-metadata was a bit painful.  I wandered through the upstream source's pom.xml files and got very confused.  In the end, I confirmed the location after thrashing about and having maven download a huge amount of stuff to ~/.m2 (maven's cache directory) and inspecting the compiled jars.  Silliness ensued...

cd ~/.m2

find . -name \*.jar | while read f ; do (jar tf $f | awk '{print "'"$f"'" " " $0}' | grep -i "GeoTools") ; done

jar tf ./repository/org/geotools/gt-metadata/20-SNAPSHOT/gt-metadata-20-SNAPSHOT.jar | grep factory/GeoTools.class
org/geotools/factory/GeoTools.class

mkdir foo

cp ./repository/org/geotools/gt-metadata/20-SNAPSHOT/gt-metadata-20-SNAPSHOT.jar ~/foo

cd ~/foo

jar xf gt-metadata-20-SNAPSHOT.jar

find . -name GeoTools.class
./org/geotools/factory/GeoTools.class

strings org/geotools/factory/GeoTools.class | grep About
getAboutInfo

Now to do stuff with GeoTools that is more interesting than just a hello world.

Monday, May 21, 2018

What could the HDFGroup do to improve HDF5 (and HDF4)

Back in 2014, I tried to do a bit of cleanup on HDF4 & HDF5.  I'm sure my comments are long out of date...


A few things would accelerate contributions from the community:

  • Mirror the git repos to github and set them up to automatically get updated
  • Setup continuous integration (VI) with travis-ci, appveyor, coveralls, and/or other providers
  • Allow bugs and pull requests on github.  Then people can propose patches and make sure they don't break the builds
  • Make sure primary development is going towards the "master" branch.  That's were people expect to look for the latest changes with git based code.  That's what people expect to send you patches against.

Even and I wrote down some of what we do for GDAL, but it's getting out of date after a few years.  Use these and any other tool you can (e.g. clang-tidy modernize).

http://erouault.blogspot.com/2016/01/software-quality-improvements-in-gdal.html

Other things that I personally think would be great for the HDF team to do:

  • Sign up for OSS Fuzz.  Use google resources try to crash the code and send you bug reports
  • Change the tests to only write into a user controllable temp location.  I run tests from a CAS filesystem that is read only and the runner gets passed the location of where it is allowed to write.
  • Define what the acronyms are in files.  I don't remember what the "AC" means even when I'm in H5AC.c.
  • Drop things like who created each file and when.  Those things are in the version control history and are noise when debugging
  • Have more tests that try to do things in isolation - true unit tests.  e.g. just test a single function.  I usually expect that testing code should be as long or longer than each file.  And each test case only tests one thing
  • Make sure that the code becomes and stays whitespace clean.  Best is to use clang-format, but things like perl -pi -e 's/\s+\n/\n/g' work quite well
  • Don't use line feed characters in the source.  That makes viewing on large screens harder with some tools
  • Consider using a test framework like googletest/gunit.  Many people are experienced with these frameworks and can better follow your tests and contribute back
  • Switch to C++11 as the minimum version of C++.  So many things get easier/better e.g. https://trac.osgeo.org/gdal/wiki/rfc68_cplusplus11

Monday, May 7, 2018

Paywalled docs

"Maritime navigation and radiocommunication equipment and systems - Digital interfaces - Part 460: Multiple talkers and multiple listeners - Ethernet interconnection - Safety and security"

This doc is out, but I have never read it. If the maritine community wants this stuff to really work, you need to be engaging security experts.  None of us that work on computer security are going to pay for this doc or any of it's siblings. It is time for the IEC to release all AIS/eNav standards as free docs. You need to get them in as many hands as possible if you want to get towards better systems.   Not just the big hardware and software providers...