Maven Simplifies the Reuse of NetBeans Platform Components in Plain Applications

DZone 's Guide to

Maven Simplifies the Reuse of NetBeans Platform Components in Plain Applications

· Java Zone ·
Free Resource
Did you ever need to reuse a component you've written for the NetBeans Platform in a plain Java application? It happened to me a couple of times in the past - not a big deal, but a bit of annoyance in having to manage duplicated artifacts, that is a .jar file used by the plain application for every .nbm produced for the Platform applications.

With Maven, the annoyance is completely over, because a Maven Platform project produces and deploys both the two types of artifacts (jar and nbm).

In this 30-sec tutorial (with the exception of the time required to download artifacts from the network) we're going to learn how to use two components from forceTen in a simple, plain Java application.

First copy the following XML to the pom.xml in your working directory:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
<name>forceTen Example2 (master)</name>

<name>NetBeans Platform Maven Repository</name>
<name>NBPWR Maven Release Repository</name>
<name>OpenBlueSky Maven Release Repository</name>
<name>forceTen Maven Release Repository</name>




Note that, repositories apart, there's nothing about NetBeans; it's just a simple pom where I declare that I want to use two artifacts (the GeoCoding API and a service provider for it).  

Now copy the following Java code into a file named Main.java in a subdirectory src/main/java of your current path:

import javax.annotation.Nonnull;
import it.tidalwave.netbeans.util.Finder;
import it.tidalwave.netbeans.util.Locator;
import it.tidalwave.netbeans.util.NotFoundException;
import it.tidalwave.geo.Coordinate;
import it.tidalwave.geo.geocoding.GeoCoder;
import it.tidalwave.geo.geocoding.GeoCoderEntity;
import it.tidalwave.geo.geocoding.GeoCoderEntity.FactSheet;
import static it.tidalwave.netbeans.util.Displayable.Displayable;
import static it.tidalwave.geo.geocoding.GeoCoder.GeoCoder;
import static it.tidalwave.geo.geocoding.GeoCoderEntity.FactSheet.*;
import static it.tidalwave.geo.geocoding.GeoCoderEntity.FactSheet.FactSheet;

public class Main
public static void main (final @Nonnull String ... args)
throws NotFoundException
final GeoCoder geoCoder = Locator.find(GeoCoder);
final Coordinate coordinate = new Coordinate(43.5, 6);
final Finder<GeoCoderEntity> nearbyPlaces = geoCoder.findNearByEntities(coordinate, 10);

for (final GeoCoderEntity place : nearbyPlaces.results())
final String displayName = place.as(Displayable).getDisplayName();
final String type = place.getTypeAsString();
final Coordinate c = place.getCoordinate();
final FactSheet factSheet = place.as(FactSheet);

System.err.printf("%-30s %-5s: %s\n", displayName, type, c);

if (factSheet.contains(POPULATION))
System.err.printf("%42s %d\n", "population:", factSheet.get(POPULATION));

if (factSheet.contains(ELEVATION))
System.err.printf("%42s %d\n", "elevation: ", factSheet.get(ELEVATION));

Now run:

mvn clean install exec:java -Dexec.mainClass=Main

You should see this application output:

Châteauvert                    PPL  : N 43° 30' 00.000" E 6° 01' 00.000", 0.0
population: 147
elevation: 0
Miraval PPL : N 43° 28' 00.000" E 6° 02' 00.000", 0.0
elevation: 0
Saint-Estève PPL : N 43° 30' 00.000" E 5° 56' 00.000", 0.0
elevation: 0
Brue-Auriac PPL : N 43° 32' 00.000" E 5° 57' 00.000", 0.0
population: 959
elevation: 0
Bras PPL : N 43° 28' 00.000" E 5° 57' 00.000", 0.0
population: 1888
elevation: 0
Barjols PPL : N 43° 33' 00.000" E 6° 00' 00.000", 0.0
population: 2619
elevation: 0
Correns PPL : N 43° 29' 00.000" E 6° 05' 00.000", 0.0
population: 723
elevation: 0
Pontevès PPL : N 43° 34' 00.000" E 6° 03' 00.000", 0.0
population: 624
elevation: 0
Seillons-Source-d'Argens PPL : N 43° 29' 00.000" E 5° 53' 00.000", 0.0
elevation: 0

What are you bringing into your application? You can discover it by generating the dependency tree with:

mvn dependency:tree 

The output is:

[INFO] [dependency:tree {execution: default-cli}]
[INFO] it.tidalwave.geo.examples:example2:jar:1.1-SNAPSHOT
[INFO] +- it.tidalwave.geo:it-tidalwave-geo-geocoding:jar:3.1.0:compile
[INFO] |  +- it.tidalwave.netbeans:it-tidalwave-netbeans-util:jar:1.10.20:compile
[INFO] |  |  \- com.kenai.nbpwr:javax-inject:jar:1.0:compile
[INFO] |  |     \- javax.inject:javax.inject:jar:1:compile
[INFO] |  +- it.tidalwave.geo:it-tidalwave-geo:jar:2.0.32:compile
[INFO] |  +- org.netbeans.api:org-openide-util:jar:RELEASE68:compile
[INFO] |  +- it.tidalwave.netbeans:it-tidalwave-netbeans-capabilitiesprovider:jar:1.1.8:compile
[INFO] |  +- com.kenai.nbpwr:edu-umd-cs-findbugs-annotations:jar:
[INFO] |  |  \- net.sourceforge.findbugs:annotations:jar:1.3.2:compile
[INFO] |  \- com.kenai.nbpwr:javax-annotation:jar:
[INFO] |     \- com.google.code.findbugs:jsr305:jar:1.3.7:compile
[INFO] \- it.tidalwave.geo:it-tidalwave-geo-geocoding-geonamesprovider:jar:1.0.44:compile
[INFO]    +- it.tidalwave.netbeans:it-tidalwave-netbeans-workspacemanager:jar:2.2.16:compile
[INFO]    +- it.tidalwave.thesefoolishthings:it-tidalwave-util-logging:jar:1.0.5:compile
[INFO]    |  \- it.tidalwave.thesefoolishthings:it.tidalwave.util.logging:jar:1.0.5:compile
[INFO]    \- com.kenai.nbpwr:org-apache-commons-io:jar:
[INFO]       \- commons-io:commons-io:jar:1.3.1:compile

so there are just a few libraries used by forceTen and a single module from the NetBeans Platform, org-openide-util which contains Lookup. In this case, no problems, as it will work in a plain application. In other cases, some more complex components of the Platform might be required and it would not be necessarily simple to have them working out of the box.

Also, please note that the service discovery mechanism based on the META-INF/services facility is working fine, since it's a standard feature of Java 6: in fact, you're using the abstract GeoCoding API and in the code there's no reference to the GeoNames provider; still, it's discovered at runtime.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}