geoserver:Migrate from Restlet to Spring-MVC


GeoServer的RESTAPI很流行,但维护的不好,收集了大量未解决的bug。其中许多人抱怨功能和缺乏文档。大量的bug(API调用正确但产生了错误)可能会产生更多的文档请求(开发人员认为他们调用错误,并通过一个有效的示例要求改进文档)。

在内部,RESTAPI是使用早期名为“restlet”的java库编写的(http://restlet.com/)。人们希望迁移到spring rest api,它是注释驱动的,并且支持得更好。执行到SpringMVC迁移的风险在于引入的bug比修复的要多。这在一定程度上被一个熟悉代码库和所用技术的开发人员池所抵消。
有关规划协调和详细信息,请参见:

https://osgeo-org.atlassian.net/browse/GEOS-8275

https://osgeo-org.atlassian.net/browse/GEOS-10330?jql=project%20%3D%20GEOS%20AND%20status%20in%20(Open%2C%20Reopened)%20AND%20component%20%3D%20REST%20ORDER%20BY%20created%20DESC%2C%20issuetype%20ASC

https://github.com/geoserver/geoserver/wiki/REST-Refresh-Notes-and-Tips

https://github.com/Maps4HTML/geoserver/wiki/REST-Refresh-Notes-and-Tips

这些是关于将GeoServer REST API转换为Spring MVC的松散注释。它们源自转换现有样式端点的经验。本文档旨在作为实际代码的配套文件。

Sample Branch

https://github.com/boundlessgeo/geoserver/tree/spring_mvc_example

Spring MVC Documentation

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

Getting Ready for REST

In this week’s GeoServer meeting we had a chance to sit down and plan out the steps needed to get ready.

在本周的GeoServer会议上,我们有机会坐下来计划准备工作所需的步骤。

The majority of prep will go into performing the restlet to spring mvc migration for a sample REST API end point to produce a “code example” for developers to follow. We have selected the rest/styles endpoint as one of the easier examples:

prep的大部分内容将用于执行restlet到spring的mvc迁移,以获得一个示例restapi端点,从而为开发人员提供一个“代码示例”。我们选择了rest/styles端点作为更简单的示例之一:

http://blog.geoserver.org/2017/03/09/rest-api-code-sprint-prep/

  1. Preflight check: Before we start we want to have a good baseline of the current REST API responses. We would like to double check that each endpoint has a JUnit test case that checks the response against a reference file. Most of our tests just count the number of elements, or drill into the content to look for a specific value. The goal is to use these reference files as a quick “regression test” when performing the migration.飞行前检查:在开始之前,我们希望对当前RESTAPI响应有一个良好的基线。我们想再次检查每个端点是否有一个JUnit测试用例,该用例根据引用文件检查响应。我们的大多数测试只是计算元素的数量,或者深入内容以查找特定的值。目标是在执行迁移时将这些参考文件用作快速“回归测试”。
  2. Migrate rest/styles from StyleResource (restlet) to StyleController (spring): This should be a bit of fun, part of why spring model-view-controller was selected. Our goal is to have one Controller per end-point, and configure the controller using annotations directly in the Java file. This ends up being quite readable with variable names being taken directly out of the URL path. It is also easier to follow since you do not have to keep switching between XML and Java files to figure out what is going on.  It is important that the example is “picture perfect” as it will be used as a template by the developers over the course of the sprint, and will be an example of the level of quality we expect during the activity.将rest/样式从StyleResource(restlet)迁移到StyleController(spring):这应该有点有趣,这也是选择spring模型视图控制器的部分原因。我们的目标是每个端点有一个控制器,并直接在Java文件中使用注释配置控制器。由于变量名直接从URL路径中取出来,因此非常可读。这也更容易理解,因为您不必一直在XML和Java文件之间切换以了解发生了什么。重要的是,该示例是“完美的图片”,因为它将在sprint过程中被开发人员用作模板,并且将是我们在活动期间期望的质量水平的示例。

           3.Create StyleInfo bindings (using XStream for xml and json generation): The above method returns a StyleInfo data structure, our current restlet solutions publishes each “resource” using the XStream library. We think we can adapt our XStream work for use in spring model-view-controller by configuring a binding for StyleInfo and implementing in using XStream.  This approach is the key reason we are confident in this migration being a success; existing clients that depend on exactly the same output from GeoServer – should get exactly the same output.创建样式信息绑定(使用XStream生成xml和json):上述方法返回样式信息数据结构,我们当前的restlet解决方案使用XStream库发布每个“资源”。我们认为,通过配置StyleInfo的绑定并在使用XStream中实现,我们可以调整我们的XStream工作,以便在spring模型视图控制器中使用。这种方法是我们对这次迁移成功充满信心的关键原因;依赖于GeoServer完全相同输出的现有客户端应获得完全相同的输出。

          4. StyleController path management: There is some work to configure each controller, while we have the option of doing some custom logic inside each controller we would like to keep this to a minimum.  This step is the small bit of applicationContext.xml configuration work we need to do for each controller, we expect it to be less work then reslet given the use of annotations.StyleController path management:在配置每个控制器时需要做一些工作,而我们可以选择在每个控制器内部执行一些自定义逻辑,我们希望将此限制在最低限度。这一步是applicationContext的一小部分。我们需要为每个控制器进行xml配置工作,考虑到注释的使用,我们希望这项工作比reslet少。

          5. Reference Documentation Generation: We are looking into a tool called swagger for documentation generation. Our current reference documentation only lists each end-point (and does not provide information on the request and response expected – leaving users to read the examples or try out the api in an ad-hoc fashion). See screen snap below, our initial experience is positive, but the amount of work required is intimidating.

          6. Updated examples for cURL and Python: We would like to rewrite our examples in a more orderly fashion to make sure both XML and JSON sample requests and responses are provided. Ideally we will inline the “reference files” from the JUnit regression test in step 1 to ensure that the documentation is both accurate and up to date.

http://blog.geoserver.org/2017/04/11/rest-api-code-sprint-results/

After an epic week of work on the REST-API as a team we are happy to report back with both a pull request and this status update on the work performed.

The base /rest end-point provides an HTML and JSON list of all the other endpoints. Torben was able to implement using by looking up path mapping at runtime, allowing us to list new rest-api end-points that are added by optional modules such as the backup-restore community module.

The/rest/workspaces and/rest/namespaces were ported by Ian Turton who joined us from the United Kingdom. These two end-points work in tandem, and are responsible for partitioning GeoServer’s configuration for ease of management, with each workspace being assigned an XML namespace (so their output will not conflict).

Next we have David Vick working on the /rest/{workspace}/datastores end-point. This end-point is responsible for managing vector data sources, this was especially challenging to document since the connection parameters are different for each kind of connection.

Andrea Aime drove down to the coast from to joint the sprint. Initially working on the the /rest/{workspace}/coveragestores end-points, responsible for managing raster data sources, including file upload. Andrea was the first to finish migration and move on to documentation with Mike Pumphrey. This was an especially comlicated end-point as it also covers index and granules management for structured coverages (such as image mosaic).

From Canada Jody Garnett helped with documentation builds, and porting the /rest/layers end-points. The layers end-point captures the WFS options and WMS styling required when publishing.

Nuno, joining us Portugal, worked on the /rest/{workspace}/coverages end-points. Each coverage represents a resource published as a layer. This makes it a tricky to work as both the coverages and layers end-point needs to be used together to effect change.

Matt Kruszewski, joining from St. Louis, provided technical experience to guide the documentation effort. For migration Matt worked on the /rest/{workspace}/featuretypes end-point. Each featuretype represents vector data that is published as a layer, once again requiring use of both the featuretypes and layers end-points together.

Kevin Smith, over from Canada, worked on the /rest/{workspaces}/wmsstores and /rest/{workspaces}/wmslayers end-points. These endpoints are responsible for managing cascaded WMS services, and shared many of the same challenges as the datastores and coverages endpoints.

Quinn Scriptor flew in from Washington District of Columbia, helping with the documentation publication and porting the /rest/layergroups end-points. This work was made more challenging due to an inital lack of test coverage, requiring Quinn to write tests prior to migration.

Several developers were able to go back for a second helping, porting the remaining end-points:

  • /rest/fonts was ported by Ian
  • /rest/about was ported by Matt
  • /rest (index) was ported by Torben
  • /rest/settings were ported by Quinn and Torben. Quinn had to dig into the settings for each of the OWS Services.
  • /rest/templates were ported by Jody
  • /rest/security was ported, at some cost to personal sanity, by Andrea.
  • /rest/resources was ported by Torben. This proved tricky as the end-point is willing to work with a wide range of mimetypes (as it is used to manage configuration files, icons and fonts).

After the core application was migrated we had a chance to work on the extensions.

  • The /rest/imports extension was a team effort with Ian David, Matt and Torben on task. Torben especially worked on the airplane ride home and far into the next week migrating the tasks section of this api (responsible for monitoring long running import activities).
  • The /rest/monitor extension was the work of Andrea. This proved difficult to migrate unchanged, as the original notification model was tied into the restlet life-cycle. This work was extensive requiring re-implementing all the dispatcher callbacks in core.
  • Finally Nuno migrated the /rest/services/wfs/transforms end-point used to define XSLT transformations on WFS output.

 文档:

One thing everyone we talked to was looking forward to was reference documentation for the rest api. We have mixed success to report.

很多人讨论的是rest api的参考文档。

We were unable to “auto generate” swagger documentation starting from our existing java codebase. The XStream library we use for XML/JSON output cannot be automatically scanned to produce a swagger file.

我们不能自动生成swagger文档,从我们现有的java codebase。XStream库,我们用来处理XML/JSON输出的无法自动扫描生成一个swagger文件。

What we were able to do was form a documentation train,  as each developer completed the migration of a rest-api endpoint they would visit Mike Pumphrey and get started on producing a swagger document by hand. These text files explicitly document each end point, the path, the queries, and most importantly the data that can be edited.、

Once the swagger document had been produced we then had a chance to look into publishing options.

From each rest api in the user documentation we link to the generated reference docs.

 https://github.com/geoserver/geoserver/wiki/REST-API-Refresh

 https://github-wiki-see.page/m/geoserver/geoserver/wiki/REST-Refresh-Notes-and-Tips

GeoSolutions has offered to host the GeoServer team for a Java 2017 code sprint to look at updating, fixing and documenting the the GeoServer REST API. The GeoServer REST API is used to remotely manage a GeoServer instance and has proven highly successful for automation, integration with other applications, with libraries for java and python remote management

http://blog.geoserver.org/2017/01/23/geoserver-code-sprint-2017/

https://osgeo-org.atlassian.net/jira/software/c/projects/GEOS/issues/?filter=allissues