implementing.rst 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. .. _rest_services_implementing:
  2. Implementing a RESTful Service
  3. ==============================
  4. This section describes how to implement a restful service in GeoServer, using
  5. a "Hello World" example. The service will be extremely simple and will return
  6. the text "Hello World" from a GET request.
  7. Prerequisites
  8. --------------
  9. Before being able to proceed, GeoServer must be built on the local system. See
  10. the :ref:`source` and :ref:`quickstart` sections for details.
  11. Create a new module
  12. -------------------
  13. #. Create a new module named ``hello_rest`` somewhere on the file system.
  14. #. Add the following ``pom.xml`` to the root of the new module:
  15. .. code-block:: xml
  16. <project xmlns="http://maven.apache.org/POM/4.0.0"
  17. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  18. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
  19. <modelVersion>4.0.0</modelVersion>
  20. <groupId>org.geoserver</groupId>
  21. <artifactId>hello_rest</artifactId>
  22. <packaging>jar</packaging>
  23. <version>1.0-SNAPSHOT</version>
  24. <name>hello_rest</name>
  25. <dependencies>
  26. <dependency>
  27. <groupId>org.geoserver</groupId>
  28. <artifactId>gs-rest</artifactId>
  29. <version>2.8-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
  30. </dependency>
  31. <dependency>
  32. <groupId>org.geoserver</groupId>
  33. <artifactId>gs-main</artifactId>
  34. <version>2.8-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
  35. <classifier>tests</classifier>
  36. <scope>test</scope>
  37. </dependency>
  38. <dependency>
  39. <groupId>junit</groupId>
  40. <artifactId>junit</artifactId>
  41. <version>4.11</version>
  42. <scope>test</scope>
  43. </dependency>
  44. <dependency>
  45. <groupId>com.mockrunner</groupId>
  46. <artifactId>mockrunner</artifactId>
  47. <version>0.3.6</version>
  48. <scope>test</scope>
  49. </dependency>
  50. </dependencies>
  51. <build>
  52. <plugins>
  53. <plugin>
  54. <artifactId>maven-compiler-plugin</artifactId>
  55. <configuration>
  56. <source>1.8</source>
  57. <target>1.8</target>
  58. </configuration>
  59. </plugin>
  60. </plugins>
  61. </build>
  62. </project>
  63. #. Create the directory ``src/main/java`` under the root of the new module::
  64. [hello_rest]% mkdir -p src/main/java
  65. Create the resource class
  66. -------------------------
  67. #. The class ``org.geoserver.rest.AbstractResource`` is a convenient base
  68. class available when creating new resources. Create a new class called
  69. ``HelloResource`` in the package ``org.geoserver.hellorest``, which
  70. extends from ``AbstractResource``.
  71. .. code-block:: java
  72. package org.geoserver.hellorest;
  73. import java.util.List;
  74. import org.geoserver.rest.AbstractResource;
  75. import org.geoserver.rest.format.DataFormat;
  76. import org.restlet.data.Request;
  77. import org.restlet.data.Response;
  78. public class HelloResource extends AbstractResource {
  79. @Override
  80. protected List<DataFormat> createSupportedFormats(Request request, Response response) {
  81. return null;
  82. }
  83. }
  84. #. The first method to implement is ``createSupportedFormats()``. The purpose
  85. of this method is to create mapping from an extension, to a particular
  86. format. For now the goal will be to return the text "Hello World" when a
  87. ".txt" extension is requested by the client.
  88. .. code-block:: java
  89. import java.util.ArrayList;
  90. import org.geoserver.rest.format.StringFormat;
  91. ...
  92. @Override
  93. protected List<DataFormat> createSupportedFormats(Request request, Response response) {
  94. List<DataFormat> formats = new ArrayList();
  95. formats.add(new StringFormat( MediaType.TEXT_PLAIN ));
  96. return formats;
  97. }
  98. #. The next step is to override the ``handleGet()`` method. This method is
  99. called when a GET request is made for the resource.
  100. .. code-block:: java
  101. @Override
  102. public void handleGet() {
  103. //get the appropriate format
  104. DataFormat format = getFormatGet();
  105. //transform the string "Hello World" to the appropriate response
  106. getResponse().setEntity(format.toRepresentation("Hello World"));
  107. }
  108. The above makes use of the ``getFormatGet()`` method, whose purpose is
  109. to determine the extension being requested by the client, and look up
  110. the appropriate format for it. In this case when the client requests the
  111. ".txt" extension, the ``StringFormat`` setup in the previous step will be
  112. found.
  113. Create the application context
  114. ------------------------------
  115. #. The next step is to create an application context that tells GeoServer
  116. about the resource created in the previous section. Create the directory
  117. ``src/main/resources`` under the root of the ``hello_rest`` module::
  118. [hello_rest]% mkdir src/main/resources
  119. #. Add the following ``applicationContext.xml`` file to the ``src/main/resources`` directory under the root of the ``hello_rest`` module.
  120. .. code-block:: xml
  121. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
  122. <beans>
  123. <bean id="hello" class="org.geoserver.hellorest.HelloResource"/>
  124. <bean id="helloMapping" class="org.geoserver.rest.RESTMapping">
  125. <property name="routes">
  126. <map>
  127. <entry>
  128. <key><value>/hello.{format}</value></key>
  129. <value>hello</value>
  130. </entry>
  131. </map>
  132. </property>
  133. </bean>
  134. </beans>
  135. There are two things to note above. The first is the ``hello`` bean which
  136. is an instance of the ``HelloResource`` class created in the previous
  137. section. The second is the ``helloMapping`` bean, which defines a template
  138. for the uri in which the resource will be accessed. The above mapping
  139. specifies that the resource will be located at ``/rest/hello.{format}``
  140. where ``format`` is the representation being requested by the client. As
  141. implemented ``hello.txt`` is the only supported representation.
  142. Test
  143. ----
  144. #. Create the directory ``/src/test/java`` under the root of the
  145. ``hello_rest`` module::
  146. [hello_rest]% mkdir -p src/test/java
  147. #. Create a new test class called ``HelloResourceTest`` in the package
  148. ``org.geoserver.hellorest``, which extends from
  149. ``org.geoserver.test.GeoServerTestSupport``:
  150. .. code-block:: java
  151. package org.geoserver.hellorest;
  152. import org.geoserver.test.GeoServerTestSupport;
  153. public class HelloResourceTest extends GeoServerTestSupport {
  154. public void test() throws Exception {
  155. }
  156. }
  157. #. Add a statement which makes a GET request for ``/rest/hello.txt`` and
  158. asserts it is equal to the string "Hello World":
  159. .. code-block:: java
  160. public void test() throws Exception {
  161. assertEquals( "Hello World", getAsString("/rest/hello.txt"));
  162. }
  163. #. Build and test the ``hello_test`` module::
  164. [hello_rest]% mvn install