[Geoserver-devel] Need to use ThreadLocal for per-request storage in RenderingTransformation processes?

I’m working on a GSProcess which is being used as a RenderingTransformation, to produce a GridCoverage output. I want to create the output grid with the size of the image requested. To do this I need to keep the GridGeometry provided in the invertQuery() method for later use in the execute() method.

At first I did not realize that the Process object was instantiated by the SLD, and so all instance state is not local to each request. In order to create request-specific state (i.e. to keep the GridGeometry in) I have had to create a ThreadLocal class and use it.

This seems like a bit of a hack, and is slightly obscure. Is there any better way of doing this? Or any plans to provide a simpler alternative?

Martin Davis
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On Thu, Feb 23, 2012 at 12:53 AM, Martin Davis <mdavis@anonymised.com> wrote:

I'm working on a GSProcess which is being used as a RenderingTransformation,
to produce a GridCoverage output. I want to create the output grid with the
size of the image requested. To do this I need to keep the GridGeometry
provided in the invertQuery() method for later use in the execute() method.

That is a way, but not a nice one as you noticed.

If you look at how the raster georeferencing process
is used in geometry transformations (SF metro project) you'll see that
on trunk GeoServer sets a few extra enviroment variables that you
can grab with the "env" function, including the width and height of the
output image.

Here are the params:

        // setup some SLD variable substitution environment used by
rendering transformations
        EnvFunction.setLocalValue("wms_bbox", mapContent.getRenderingArea());
        EnvFunction.setLocalValue("wms_crs",
mapContent.getRenderingArea().getCoordinateReferenceSystem());
        EnvFunction.setLocalValue("wms_srs", mapContent.getRequest().getSRS());
        EnvFunction.setLocalValue("wms_width", mapContent.getMapWidth());
        EnvFunction.setLocalValue("wms_height", mapContent.getMapHeight());

Hope this helps

Cheers
Andrea

--
-------------------------------------------------------
Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313
mob: +39 339 8844549

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf

-------------------------------------------------------

So these need to be defined as parameters to the RenderingTransformation process, and then specified in the SLD with values provided by calls to the “env” function?

Hmm… I think I like the invertQuery way better - more explicit, and fewer lines of code for users to screw up.

I can see that having access to rendering parameters in the SLD could be very useful, however.

On Tue, Feb 28, 2012 at 1:41 PM, Andrea Aime <andrea.aime@anonymised.com> wrote:

On Thu, Feb 23, 2012 at 12:53 AM, Martin Davis <mdavis@anonymised.com1…> wrote:

I’m working on a GSProcess which is being used as a RenderingTransformation,
to produce a GridCoverage output. I want to create the output grid with the
size of the image requested. To do this I need to keep the GridGeometry
provided in the invertQuery() method for later use in the execute() method.

That is a way, but not a nice one as you noticed.

If you look at how the raster georeferencing process
is used in geometry transformations (SF metro project) you’ll see that
on trunk GeoServer sets a few extra enviroment variables that you
can grab with the “env” function, including the width and height of the
output image.

Here are the params:

// setup some SLD variable substitution environment used by
rendering transformations
EnvFunction.setLocalValue(“wms_bbox”, mapContent.getRenderingArea());
EnvFunction.setLocalValue(“wms_crs”,
mapContent.getRenderingArea().getCoordinateReferenceSystem());
EnvFunction.setLocalValue(“wms_srs”, mapContent.getRequest().getSRS());
EnvFunction.setLocalValue(“wms_width”, mapContent.getMapWidth());
EnvFunction.setLocalValue(“wms_height”, mapContent.getMapHeight());

Hope this helps

Cheers
Andrea

Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313
mob: +39 339 8844549

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf


Martin Davis
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On Tue, Feb 28, 2012 at 11:32 PM, Martin Davis <mdavis@anonymised.com> wrote:

So these need to be defined as parameters to the RenderingTransformation
process, and then specified in the SLD with values provided by calls to the
"env" function?

Hmm... I think I like the invertQuery way better - more explicit, and fewer
lines of code for users to screw up.

I can see that having access to rendering parameters in the SLD could be
very useful, however.

In my mind a process is first and foremost a WPS process, its
rendering transformation
ability is something added on top, the process has to work even outside of
that rendering context (when called striaight from WPS the rendering
transformation
methods are _not_ going to get called).

A process that does vector to raster transformation obviously needs to know
how big the output raster will be, thus it needs to have some simple and
WPS bindable way to do that, the grid to world transformation is not a obvious
candidate there, width and height are more natural.

I see you are thinking about the process as something that makes sense
to be used only as a rendering transformation instead, so hopefully it
is not build as
a process (since you'd have around a WPS process that cannot be used)
but as a straight filter function?

I did not cover that use case, but if you want to propose API changes that
would make both approaches work I'm all ears :slight_smile:

Cheers
Andrea

--
-------------------------------------------------------
Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313
mob: +39 339 8844549

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf

-------------------------------------------------------

On Tue, Feb 28, 2012 at 11:09 PM, Andrea Aime <andrea.aime@anonymised.com> wrote:

On Tue, Feb 28, 2012 at 11:32 PM, Martin Davis <mdavis@anonymised.com> wrote:

So these need to be defined as parameters to the RenderingTransformation
process, and then specified in the SLD with values provided by calls to the
“env” function?

Hmm… I think I like the invertQuery way better - more explicit, and fewer
lines of code for users to screw up.

I can see that having access to rendering parameters in the SLD could be
very useful, however.

In my mind a process is first and foremost a WPS process, its
rendering transformation
ability is something added on top, the process has to work even outside of
that rendering context (when called striaight from WPS the rendering
transformation
methods are not going to get called).

A process that does vector to raster transformation obviously needs to know
how big the output raster will be, thus it needs to have some simple and
WPS bindable way to do that, the grid to world transformation is not a obvious
candidate there, width and height are more natural.

I see you are thinking about the process as something that makes sense
to be used only as a rendering transformation instead, so hopefully it
is not build as
a process (since you’d have around a WPS process that cannot be used)
but as a straight filter function?

I did not cover that use case, but if you want to propose API changes that
would make both approaches work I’m all ears :slight_smile:

These are all good points, Andrea, and I agree with your reasoning that it’s nice to have a single implementation which can be used as both a standalone process and as a rendering transformation.

I don’t have any great ideas about another way of doing things at this point. It does seem to me like it would be nice to avoid having all that ugly boilerplate code in the SLD to pass in the rendering context information. I guess there are various ways this might be done:

  • well-known parameters that the Rendering pipeline could fill in automatically
  • a RenderingTransform-specific method on the process class to pass in this information (but this would require ThreadLocal storage again, or creating a new process object for each rendering use)

Anyway, for now I’ll look at switching over to using the explicit parameters.

Martin Davis
OpenGeo - http://opengeo.org
Expert service straight from the developers.