Skip to main content
2 of 2
deleted 29 characters in body
PolyGeo
  • 65.4k
  • 29
  • 114
  • 345

Error in Geotools renderer

Here is my Java code that generates an error from Geotools renderer:

public class LandmarkLayer {
protected static final String LANDMARK_FEATURE_NAME = "landmark";
protected static final StyleFactory SF = CommonFactoryFinder.getStyleFactory();
protected static final FilterFactory2 FF = CommonFactoryFinder.getFilterFactory2();
protected static final Color LANDMARK_COLOR = new Color(0, 0, 160);
// Tower icon
protected static final String TOWER_ICON_PATH = "landmarks/water_tower.svg";
protected static final float POINT_SIZE = 10.0f;

public static Layer createLayer(DataStore dataStore) {
 // category == 17 <==> tower
    PropertyIsEqualTo piet = FF.equals(FF.property("category"),
                                       FF.literal(17)         );
    Rule towerRule = SF.createRule();
    towerRule.setName("rule for tower landmarks");
    towerRule.setFilter(piet);

    OnLineResourceImpl svgTower = null;
    try {
        svgTower = new OnLineResourceImpl(new URI(TOWER_ICON_PATH));
    } catch (URISyntaxException ex) {
        System.out.flush();
        System.err.println("Syntax error in next tower icon path : " +
                           TOWER_ICON_PATH);
        System.exit(1);
    }
    svgTower.freeze(); // freeze to prevent modification at runtime
 // List of symbols is considered in order with the rendering engine
 // choosing the first one it can handle. Here only two choices are
 // possible: svg or small circle
    List<GraphicalSymbol> symbols = new ArrayList<>();
    
    symbols.add(SF.externalGraphic(svgTower, "svg", null));

 // simple circle backup plan
    Stroke stroke = SF.stroke(FF.literal("#000000"),
                              null                 ,
                              null                 ,
                              null                 ,
                              null                 ,
                              null                 ,
                              null                 );
    Fill fill = SF.fill(null                  ,
                        FF.literal(Color.BLUE),
                        FF.literal(1.0f)      );
 // create the graphical mark used to represent a tower
    symbols.add(SF.mark(FF.literal("tower"), fill, stroke)); 

    Expression opacity = null; // use default
    Expression size = FF.literal(POINT_SIZE);
    Expression rotation = null; // use default
    AnchorPoint anchor = null; // use default
    Displacement displacement = null; // use default

 // define a point symbolizer for towers
    Graphic towerSymbols = SF.graphic
                   (symbols, opacity, size, rotation, anchor, displacement);
    PointSymbolizer pointSymbolizer = SF.pointSymbolizer
                                           ("tower"            ,
                                            FF.property("geom"),
                                            null               ,
                                            null               ,
                                            towerSymbols       );
    towerRule.symbolizers().add(pointSymbolizer);

    FeatureTypeStyle featureTypeStyle = SF.createFeatureTypeStyle();
    featureTypeStyle.rules().add(towerRule);
    Style style = SF.createStyle();
    style.featureTypeStyles().add(featureTypeStyle);

    SimpleFeatureSource featureSource = null;
    try {
        featureSource = dataStore.getFeatureSource(LANDMARK_FEATURE_NAME);
    } catch (IOException ex) {
        System.out.flush();
        System.err.println("Unable to find the feature called " + 
                           LANDMARK_FEATURE_NAME + " in database");
        System.exit(1);
    }

    Layer layer = new FeatureLayer(featureSource, style);

    return layer;
}

And here is the error message at runtime:

GRAVE: ExternalGraphic location URL cannot be null
java.lang.IllegalArgumentException: ExternalGraphic location URL cannot be null
at org.geotools.styling.ExternalGraphicImpl.setLocation(ExternalGraphicImpl.java:131)
at org.geotools.styling.StyleFactoryImpl.createExternalGraphic(StyleFactoryImpl.java:482)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.visit(DuplicatingStyleVisitor.java:887)
at org.geotools.styling.ExternalGraphicImpl.accept(ExternalGraphicImpl.java:142)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.copy(DuplicatingStyleVisitor.java:480)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.copy(DuplicatingStyleVisitor.java:853)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.visit(DuplicatingStyleVisitor.java:802)
at org.geotools.styling.GraphicImpl.accept(GraphicImpl.java:349)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.copy(DuplicatingStyleVisitor.java:402)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.visit(DuplicatingStyleVisitor.java:703)
at org.geotools.styling.visitor.UomRescaleStyleVisitor.visit(UomRescaleStyleVisitor.java:156)
at org.geotools.styling.PointSymbolizerImpl.accept(PointSymbolizerImpl.java:93)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.copy(DuplicatingStyleVisitor.java:511)
at org.geotools.styling.visitor.DuplicatingStyleVisitor.visit(DuplicatingStyleVisitor.java:281)
at org.geotools.renderer.lite.StreamingRenderer.rescaleFeatureTypeStyle(StreamingRenderer.java:2289)
at org.geotools.renderer.lite.StreamingRenderer.applyUnitRescale(StreamingRenderer.java:2150)
at org.geotools.renderer.lite.StreamingRenderer.createLiteFeatureTypeStyles(StreamingRenderer.java:1788)
at org.geotools.renderer.lite.StreamingRenderer.processStylers(StreamingRenderer.java:1920)
at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:835)
at org.geotools.swing.RenderingTask.call(RenderingTask.java:106)
at org.geotools.swing.RenderingTask.call(RenderingTask.java:41)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)

The only URI / URL that I handle is not null since there is no URI syntax error message. So I've got some difficulties to interpret the error message and therefore to correct the mistake in my source code.