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?

1
  • did you register your function?
    – Ian Turton
    Mar 22, 2018 at 15:13

1 Answer 1

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()).

6
  • Thanks a lot Andrea, I've tried SimpleFeature.getID() and it works perfectly.
    – Faz B
    Mar 24, 2018 at 8:09
  • However getImageUrl("id") doesn't work. it gives java.lang.IllegalArgumentException: Invalid cql expression 'getImageUrl(%22id%22)'
    – Faz B
    Mar 24, 2018 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, 2018 at 8:33
  • Try getImageUrl('${"id"}') Mar 26, 2018 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, 2018 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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