IntelliJ Quickstart

This guide will help you setup the IntelliJ IDE in order to work with GeoTools and follow along with the rest of the GeoTools tutorial.

Pre-Requisites

This guide assumes the following:

  • You have the latest JDK installed (8 at the time this article was written) installed. If not the Eclipse Quickstart provides instructions on how to do this.

  • You have IntelliJ installed. This article targets IntelliJ CE 2016; however, previous versions at least as far back as 13 should work fine. Ultimate versions should also work fine. IntelliJ can be downloaded from JetBrains and generally works out of the box on common operating systems.

Create a New Project

To start with we’ll create a new project using the Maven quickstart archetype.

  1. Choose File -> New Project from the menu. In the New Project dialog choose Maven project, ensure Create from archetype is selected, and choose the org.apache.maven.archetypes:maven-archetype-quickstart archetype. Press Next

    ../../_images/new_project_screen.png
  2. The next screen asks us for basic identifying information for our project:

    • GroupId: org.geotools

    • ArtifactId: tutorial

    • Version: 1.0-SNAPSHOT

    ../../_images/new_project2.png
  3. Hit next. The following screen we should be able to leave with the defaults. For our purposes IntelliJ’s bundled Maven should be fine, unless the version is lower than 3, in which case you should consider using a new external version.

    ../../_images/new_project3.png
  4. Hit next. Give the project a name (this name is only used internally by IntelliJ), tutorial should work for our purposes. You can change the project location to suit your needs and hopefully leave More Settings as their defaults (recommended)

    ../../_images/new_project4.png
  5. Hit finish and our new project will be created. IntelliJ will show us our newly created Maven file and do an initial Maven build (let this finish before attempting the next steps, it shouldn’t take long). IntelliJ should also ask if you want to enable Auto Import for Maven dependencies. Let’s turn that on for the purposes of this tutorial, it will automatically detect changes we make to our POM file and automatically import them.

    ../../_images/auto_import.png

IntelliJ has created an empty App.java with a simple Hello World! along with a JUnit test case. You can run App or AppTest by right clicking on them in the Project Explorer and choosing Run from the context menu.

../../_images/run_menu.png

Adding Jars to Your Project

The pom.xml file describes the structure, configuration, dependencies and many other facets of your project. We are going to focus on the dependencies needed for your project.

When downloading jars Maven makes use of a “local repository” to store copies if the dependencies it downloads.

PLATFORM

LOCAL REPOSITORY

Windows XP:

C:\Documents and Settings\You\.m2\repository

Windows:

C:\Users\You\.m2repository

Linux and Mac:

~/.m2/repository

Maven downloads jars from public repositories on the internet where projects such as GeoTools publish their work.

  1. Open up the pom.xml file at the root of the project. You can see some of the information we entered through the wizard earlier.

  2. We’re going to add three things to this file. First, at the top of the file after moduleVersion we want to add a properties element defining the version of GeoTools we wish to use. This workbook was written for 32-SNAPSHOT although you may wish to try a different version.

    For production a stable release of 32 should be used for geotools.version:

      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <geotools.version>32-SNAPSHOT</geotools.version>
        <maven.deploy.skip>true</maven.deploy.skip>
      </properties>
    

    To make use of a nightly build set the geotools.version property to 32-SNAPSHOT .

  3. We are going to add a dependence to GeoTools gt-main and gt-swing jars. Note we are making use of the geotools.version defined above.

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13.2</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-shapefile</artifactId>
          <version>${geotools.version}</version>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-swing</artifactId>
          <version>${geotools.version}</version>
        </dependency>
      </dependencies>
    
  4. Finally we need to list the external repositories where maven can download GeoTools and other required jars from.

      <repositories>
        <repository>
        <id>osgeo</id>
        <name>OSGeo Release Repository</name>
        <url>https://repo.osgeo.org/repository/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
        </repository>
        <repository>
        <id>osgeo-snapshot</id>
        <name>OSGeo Snapshot Repository</name>
        <url>https://repo.osgeo.org/repository/snapshot/</url>
        <snapshots><enabled>true</enabled></snapshots>
        <releases><enabled>false</enabled></releases>
        </repository>
      </repositories>
    

    Note

    Note the snapshot repository above is only required if you are using a nightly build (such as 32-SNAPSHOT)

  5. GeoTools requires Java 11, you need to tell Maven to use the 11 source level

      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
    
  6. Here is what the completed pom.xml looks like:

    <project
      xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.geotools.tutorial</groupId>
      <artifactId>quickstart</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
      <name>GeoTools Quickstart</name>
      <url>http://maven.apache.org</url>
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <geotools.version>32-SNAPSHOT</geotools.version>
        <maven.deploy.skip>true</maven.deploy.skip>
      </properties>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13.2</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-shapefile</artifactId>
          <version>${geotools.version}</version>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-swing</artifactId>
          <version>${geotools.version}</version>
        </dependency>
      </dependencies>
      <repositories>
        <repository>
        <id>osgeo</id>
        <name>OSGeo Release Repository</name>
        <url>https://repo.osgeo.org/repository/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
        </repository>
        <repository>
        <id>osgeo-snapshot</id>
        <name>OSGeo Snapshot Repository</name>
        <url>https://repo.osgeo.org/repository/snapshot/</url>
        <snapshots><enabled>true</enabled></snapshots>
        <releases><enabled>false</enabled></releases>
        </repository>
      </repositories>
      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
    • Recommend cutting and pasting the above to avoid mistakes when typing, using choose Code -> Reformat Code to help fix indentation

    • You may also download pom.xml, if this opens in your browser use Save As to save to disk.

      The download has an optional quality assurance profile you can safely ignore.

Tips:

  • If Maven isn’t downloading dependencies automatically for some reason (maybe Auto-Import is turned off) you can manually download dependencies by right-clicking on your project and choosing Maven -> Reimport.

  • If you’d like to download the Javadoc for your dependencies you can again go to the Maven context menu and choose Download Documentation

Quickstart Application

Now that our environment is set up we can put together a simple Quickstart. This example will display a shapefile on the screen.

  1. Let’s create a class called Quickstart in the package org.geotools.tutorial.quickstart. IntelliJ can create both the package and the class for us in one shot; right click on the org.geootools package in the Project panel and in the context menu choose New -> Java Class.

    ../../_images/new_class_menu.png ../../_images/new_class_dialog.png
  2. Fill in the following code Quickstart.java:

    /*
     *    GeoTools Sample code and Tutorials by Open Source Geospatial Foundation, and others
     *    https://docs.geotools.org
     *
     *    To the extent possible under law, the author(s) have dedicated all copyright
     *    and related and neighboring rights to this software to the public domain worldwide.
     *    This software is distributed without any warranty.
     * 
     *    You should have received a copy of the CC0 Public Domain Dedication along with this
     *    software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
     */
     package org.geotools.tutorial.quickstart;
    
    import java.io.File;
    import java.util.logging.Logger;
    
    import org.geotools.api.data.FileDataStore;
    import org.geotools.api.data.FileDataStoreFinder;
    import org.geotools.api.data.SimpleFeatureSource;
    import org.geotools.map.FeatureLayer;
    import org.geotools.map.Layer;
    import org.geotools.map.MapContent;
    import org.geotools.styling.SLD;
    import org.geotools.api.style.Style;
    import org.geotools.swing.JMapFrame;
    import org.geotools.swing.data.JFileDataStoreChooser;
    
    /**
     * Prompts the user for a shapefile and displays the contents on the screen in a map frame.
     *
     * <p>This is the GeoTools Quickstart application used in documentationa and tutorials. *
     */
    public class Quickstart {
    
        private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(Quickstart.class);
        /**
         * GeoTools Quickstart demo application. Prompts the user for a shapefile and displays its
         * contents on the screen in a map frame
         */
        public static void main(String[] args) throws Exception {
            // display a data store file chooser dialog for shapefiles
            LOGGER.info( "Quickstart");
            LOGGER.config( "Welcome Developers");
            LOGGER.info("java.util.logging.config.file="+System.getProperty("java.util.logging.config.file"));
            File file = JFileDataStoreChooser.showOpenFile("shp", null);
            if (file == null) {
                return;
            }
            LOGGER.config("File selected "+file);
    
            FileDataStore store = FileDataStoreFinder.getDataStore(file);
            SimpleFeatureSource featureSource = store.getFeatureSource();
    
            // Create a map content and add our shapefile to it
            MapContent map = new MapContent();
            map.setTitle("Quickstart");
    
            Style style = SLD.createSimpleStyle(featureSource.getSchema());
            Layer layer = new FeatureLayer(featureSource, style);
            map.addLayer(layer);
    
            // Now display the map
            JMapFrame.showMap(map);
        }
    }
    
    • You may find cutting and pasting from the documentation to be easier then typing.

    • You may also download Quickstart.java

  3. We need to download some sample data to work with. The http://www.naturalearthdata.com/ project is a great project supported by the North American Cartographic Information Society. Head to the link below and download some cultural vectors. You can use the ‘Download all 50m cultural themes’ at top.

    Please unzip the above data into a location you can find easily such as the desktop.

  4. Run the application to open a file chooser. Choose a shapefile from the example data set.

    ../../_images/QuickstartOpen.png
  5. The application will connect to your shapefile, produce a map content, and display the shapefile.

    ../../_images/QuickstartMap.png
  6. A couple of things to note about the code example:

    • The shapefile is not loaded into memory - instead it is read from disk each and every time it is needed This approach allows you to work with data sets larger than available memory.

    • We are using a very basic display style here that just shows feature outlines. In the examples that follow we will see how to specify more sophisticated styles.

Things to Try

Each tutorial consists of very detailed steps followed by a series of extra questions. If you get stuck at any point please ask your instructor; or sign up to the geotools-users email list.

Here are some additional challenges for you to try:

  • Try out the different sample data sets.

  • Zoom in, zoom out and show the full extent and use the info tool to examine individual countries in the sample countries.shp file.

  • Download the largest shapefile you can find and see how quickly it can be rendered. You should find that the very first time it will take a while as a spatial index is generated. After that rendering will become much faster.

  • Fast: We know that one of the ways people select a spatial library is based on speed. By design GeoTools does not load the above shapefile into memory (instead it streams it off of disk each time it is drawn using a spatial index to only bring the content required for display).

    If you would like to ask GeoTools to cache the shapefile in memory try the following code:

        /**
         * This method demonstrates using a memory-based cache to speed up the display (e.g. when
         * zooming in and out).
         *
         * <p>There is just one line extra compared to the main method, where we create an instance of
         * CachingFeatureStore.
         */
        public static void main(String[] args) throws Exception {
            // display a data store file chooser dialog for shapefiles
            File file = JFileDataStoreChooser.showOpenFile("shp", null);
            if (file == null) {
                return;
            }
    
            FileDataStore store = FileDataStoreFinder.getDataStore(file);
            SimpleFeatureSource featureSource = store.getFeatureSource();
            SimpleFeatureSource cachedSource =
                    DataUtilities.source(
                            new SpatialIndexFeatureCollection(featureSource.getFeatures()));
    
            // Create a map content and add our shapefile to it
            MapContent map = new MapContent();
            map.setTitle("Using cached features");
            Style style = SLD.createSimpleStyle(featureSource.getSchema());
            Layer layer = new FeatureLayer(cachedSource, style);
            map.addLayer(layer);
    
            // Now display the map
            JMapFrame.showMap(map);
        }
    

    For the above example to compile you will need to add the necessary imports.

    Note

    When building you may see a message that CachingFeatureSource is deprecated. It’s OK to ignore it, it’s just a warning. The class is still under test but usable.

  • Try and sort out what all the different “side car” files are – and what they are for. The sample data set includes shp, dbf and shx. How many other side car files are there?

  • Advanced: The use of FileDataStoreFinder allows us to work easily with files. The other way to do things is with a map of connection parameters. This techniques gives us a little more control over how we work with a shapefile and also allows us to connect to databases and web feature servers.

            File file = JFileDataStoreChooser.showOpenFile("shp", null);
    
            Map<String, Object> params = new HashMap<>();
            params.put("url", file.toURI().toURL());
            params.put("create spatial index", false);
            params.put("memory mapped buffer", false);
            params.put("charset", "ISO-8859-1");
    
            DataStore store = DataStoreFinder.getDataStore(params);
            SimpleFeatureSource featureSource = store.getFeatureSource(store.getTypeNames()[0]);
    
  • Important: GeoTools is an active open source project – you can quickly use maven to try out the latest nightly build by changing your pom.xml file to use a SNAPSHOT release.

    At the time of writing 32-SNAPSHOT is under active development.

    <properties>
    &nbsp;&nbsp;<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    &nbsp;&nbsp;<geotools.version>|branch|-SNAPSHOT</geotools.version>
    </properties>

    Double check your pom.xml file to include the OSGeo snapshot repository:

      <repositories>
        <repository>
        <id>osgeo</id>
        <name>OSGeo Release Repository</name>
        <url>https://repo.osgeo.org/repository/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
        </repository>
        <repository>
        <id>osgeo-snapshot</id>
        <name>OSGeo Snapshot Repository</name>
        <url>https://repo.osgeo.org/repository/snapshot/</url>
        <snapshots><enabled>true</enabled></snapshots>
        <releases><enabled>false</enabled></releases>
        </repository>
      </repositories>
      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
      <profiles>
        <profile>
          <id>qa</id>
          <activation>
            <property>
              <name>qa</name>
            </property>
          </activation>
          <properties>
            <maven.pmd.plugin.version>3.20.0</maven.pmd.plugin.version>
            <pmd.version>6.55.0</pmd.version>
            <pom.fmt.action>sort</pom.fmt.action>
          </properties>
          <build>
            <plugins>
              <plugin>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.14.0</version>
                <executions>
                  <execution>
                    <goals>
                      <goal>check</goal>
                    </goals>
                  </execution>
                </executions>
                <dependencies>
                  <dependency>
                    <groupId>net.sourceforge.pmd</groupId>
                    <artifactId>pmd-core</artifactId>
                    <version>${pmd.version}</version>
                  </dependency>
                  <dependency>
                    <groupId>net.sourceforge.pmd</groupId>
                    <artifactId>pmd-java</artifactId>
                    <version>${pmd.version}</version>
                  </dependency>
                </dependencies>
                <configuration>
                  <linkXRef>false</linkXRef>
                  <rulesets>
                    <ruleset>${project.basedir}/../../build/qa/pmd-ruleset.xml</ruleset>
                    <ruleset>${project.basedir}/../../build/qa/pmd-junit-ruleset.xml</ruleset>
                  </rulesets>
                  <failurePriority>3</failurePriority>
                  <minimumPriority>3</minimumPriority>
                  <verbose>true</verbose>
                  <printFailingErrors>true</printFailingErrors>
                  <includeTests>true</includeTests>
                </configuration>
              </plugin>
              <plugin>
                <groupId>com.github.spotbugs</groupId>
                <artifactId>spotbugs-maven-plugin</artifactId>
                <version>4.0.0</version>
                <executions>
                  <execution>
                    <goals>
                      <goal>check</goal>
                    </goals>
                  </execution>
                </executions>
                <configuration>
                  <effort>More</effort>
                  <!-- threshold>High</threshold -->
                  <xmlOutput>true</xmlOutput>
                  <maxRank>15</maxRank>
                  <excludeFilterFile>${project.basedir}/../../build/qa/spotbugs-exclude.xml</excludeFilterFile>
                  <jvmArgs>-XX:+TieredCompilation -XX:TieredStopAtLevel=1</jvmArgs>
                  <compilerArgs combine.children="append">
                    <arg>-Xlint:${lint}</arg>
                  </compilerArgs>
                </configuration>
              </plugin>
              <plugin>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>3.1.2</version>
                <executions>
                  <execution>
                    <goals>
                      <goal>check</goal>
                    </goals>
                  </execution>
                </executions>
                <dependencies>
                  <dependency>
                    <groupId>com.puppycrawl.tools</groupId>
                    <artifactId>checkstyle</artifactId>
                    <version>9.3</version>
                  </dependency>
                </dependencies>
                <configuration>
                  <logViolationsToConsole>true</logViolationsToConsole>
                  <configLocation>${project.basedir}/../..//build/qa/checkstyle-cc0.xml</configLocation>
                </configuration>
              </plugin>
              <plugin>
                <groupId>com.github.ekryd.sortpom</groupId>
                <artifactId>sortpom-maven-plugin</artifactId>
                <version>2.15.0</version>
                <executions>
                  <execution>
                    <phase>verify</phase>
                    <goals>
                      <goal>${pom.fmt.action}</goal>
                    </goals>
                  </execution>
                </executions>
                <configuration>
                  <skip>true</skip>
                </configuration>
              </plugin>
            </plugins>
          </build>
        </profile>
      </profiles>
    

    You can check the status of the build server producing current 32-SNAPSHOT here:

  • When cutting and pasting GeoTools examples often the code compile due to missing imports.

    IntelliJ should prompt to import the missing class immediately. Press Alt-Enter (^-Enter on OS X) to bring up a dialog to import any missing classes.