2

I'm using CSS to Style a layer in Geoserver, something like:

{
  mark: url('${getImageUrl(id)}');
   mark-mime: "image/png";
   mark-rotation: [rotationAngle];
}

getImageUrl is a custom Geotools function of mine. The problem is that Geoserver doesn't accept the id as a parameter, it gives the following exception:

ERROR [geoserver.ows] - 
java.lang.IllegalArgumentException: Invalid cql expression 'getImageUrl(id)'
    at org.geotools.renderer.style.ExpressionExtractor.splitCqlExpressions(ExpressionExtractor.java:122)
    at org.geotools.renderer.style.ExpressionExtractor.extractCqlExpressions(ExpressionExtractor.java:162)
    at org.geotools.styling.StyleAttributeExtractor.visitCqlExpression(StyleAttributeExtractor.java:396)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:410)
    at org.geotools.styling.ExternalGraphicImpl.accept(ExternalGraphicImpl.java:142)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:346)
    at org.geotools.styling.GraphicImpl.accept(GraphicImpl.java:349)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:232)
    at org.geotools.styling.PointSymbolizerImpl.accept(PointSymbolizerImpl.java:93)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:96)
    at org.geotools.styling.RuleImpl.accept(RuleImpl.java:312)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:114)
    at org.geotools.styling.FeatureTypeStyleImpl.accept(FeatureTypeStyleImpl.java:260)
    at org.geotools.styling.StyleAttributeExtractor.visit(StyleAttributeExtractor.java:77)
    at org.geoserver.wms.map.GetMapKvpRequestReader.checkStyle(GetMapKvpRequestReader.java:1062)
    at org.geoserver.wms.map.GetMapKvpRequestReader.read(GetMapKvpRequestReader.java:496)
    at org.geoserver.wms.map.GetMapKvpRequestReader.read(GetMapKvpRequestReader.java:87)
    at org.geoserver.ows.Dispatcher.parseRequestKVP(Dispatcher.java:1521)
    at org.geoserver.ows.Dispatcher.dispatch(Dispatcher.java:680)
    at org.geoserver.ows.Dispatcher.handleRequestInternal(Dispatcher.java:258)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:174)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
    at org.geoserver.filters.ThreadLocalsCleanupFilter.doFilter(ThreadLocalsCleanupFilter.java:28)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:75)
    at org.geoserver.wms.animate.AnimatorFilter.doFilter(AnimatorFilter.java:71)
    at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:71)
    at org.geoserver.filters.SpringDelegatingFilter.doFilter(SpringDelegatingFilter.java:46)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.platform.AdvancedDispatchFilter.doFilter(AdvancedDispatchFilter.java:50)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:213)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.geoserver.security.filter.GeoServerBasicAuthenticationFilter.doFilter(GeoServerBasicAuthenticationFilter.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.geoserver.security.filter.GeoServerSecurityContextPersistenceFilter$1.doFilter(GeoServerSecurityContextPersistenceFilter.java:53)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.geoserver.security.GeoServerSecurityFilterChainProxy.doFilter(GeoServerSecurityFilterChainProxy.java:152)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.LoggingFilter.doFilter(LoggingFilter.java:88)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.XFrameOptionsFilter.doFilter(XFrameOptionsFilter.java:89)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.GZIPFilter.doFilter(GZIPFilter.java:42)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.SessionDebugFilter.doFilter(SessionDebugFilter.java:48)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.FlushSafeFilter.doFilter(FlushSafeFilter.java:44)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:256)
    at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:219)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.geotools.filter.text.cql2.CQLException: Encountered "id" at line 1, column 8.
Was expecting one of:
    <STRING_LITERAL> ...
    "true" ...
    "false" ...
    "point" ...
    "linestring" ...
    "polygon" ...
    "multipoint" ...
    "multilinestring" ...
    "multipolygon" ...
    "geometrycollection" ...
    "envelope" ...
    "(" ...
    ")" ...
    "[" ...
    "-" ...
    <INTEGER_LITERAL> ...
    <FLOATING_LITERAL> ...
    <DATE> ...
    <DATE_TIME> ...
    <IDENTIFIER> ...
     Parsing : getImageUrl(id).
    at org.geotools.filter.text.ecql.ECQLCompiler.compileExpression(ECQLCompiler.java:117)
    at org.geotools.filter.text.commons.CompilerUtil.parseExpression(CompilerUtil.java:175)
    at org.geotools.filter.text.ecql.ECQL.toExpression(ECQL.java:157)
    at org.geotools.filter.text.ecql.ECQL.toExpression(ECQL.java:136)
    at org.geotools.renderer.style.ExpressionExtractor.splitCqlExpressions(ExpressionExtractor.java:119)
    ... 105 more

If I use any other int field as a parameter it works perfectly. What is the problem?

  • did you register your function? – Ian Turton Mar 22 '18 at 15:13
2

id is a keyword in CQL, you cannot use it like that. If you have a "id" attribute in your data, and it's visible in GeoServer layer page (e.g., it's not actually the primary key in a database, or you told the store to expose primary keys) then you can try using "id" (notice the double quotes).

As a second note, filter functions do receive the entire feature, so if it's actually the feature identifier you're after, you can also write a function without any parameter and extract the id from the received feature (cast to SimpleFeature, then call getID()).

  • Thanks a lot Andrea, I've tried SimpleFeature.getID() and it works perfectly. – Faz B Mar 24 '18 at 8:09
  • However getImageUrl("id") doesn't work. it gives java.lang.IllegalArgumentException: Invalid cql expression 'getImageUrl(%22id%22)' – Faz B Mar 24 '18 at 8:30
  • And when I use getImageUrl('id') (with a single quote) it gives no exceptions but the function sees a null id – Faz B Mar 24 '18 at 8:33
  • Try getImageUrl('${"id"}') – Andrea Aime Mar 26 '18 at 10:40
  • It does not work. Please help me as I need it now. I tried the following: mark: url('${getImageUrl('${"id"}')}'); but doesn't work. – Faz B Apr 21 '18 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.