JAX-RS ja Swagger: Helposti dokumentoity REST API

Hetken aikaa jo on tykyttänyt mietintämyssyn alla miten REST rajapintoja voisi helposti dokumentoida – WSDL kun sieltä uupuu (Ja WADL:ia ei kukaan halua). Kuitenkin pitäisi pystyä kertomaan ja rekisteröimään missä osoitteissa on palvelua, mitä ne tekevät, miten niitä kutsutaan, jne, muutenkin kuin testeillä ja esimerkeillä.

Törmäsin mukavaan jersey-yhteensopivaan laajennukseen nimeltä jersey-swagger. Sovitin tätä Glassfishin versioon, jossa pyörii Jersey 2, ja sainkin jotain aikaan. Tässä muistiinpanoja:

Käyttöönotto vaatii muutaman askelen: Ensiksi täytyy Mavenissä tai Gradlessa ottaa käyttöön swagger jersey versiolle kaksi. Samalla on tuikitärkeää määrittää pari exclusionia, tai serverille päätyy duplikaatteja hieman eri versioista ja tulee mukavia poikkeuksia logista. Tässä toimivaksi testattu dependency Glassfish neloselle:

 <dependency>
   <groupId>com.wordnik</groupId>
   <artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
   <version>1.3.7</version>
   <exclusions>
     <exclusion>
       <groupId>org.glassfish.jersey.media</groupId>
       <artifactId>jersey-media-multipart</artifactId>
     </exclusion>
     <exclusion>
       <groupId>org.glassfish.jersey.containers</groupId>
       <artifactId>jersey-container-servlet-core</artifactId> 
     </exclusion>
   </exclusions>
 </dependency>

Hyvä tarkistaa tässä välissä että vanhat palvelut edelleen toimivat, jos niitä on. Seuraavaksi rekisteröidään Swagger servicet. Tämän voi tehdä xml:ssä – mutta itse käytän ResourceConfig-luokkaa ja annotaatioita:

@ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("my.own.resources","com.wordnik.swagger.jersey.listing");
 }
}

Noin, sieltä aktivoituu tosiaan pari resurssiluokkaa, automaattisesti /rest/api-docs osoitteella. Seuraavaksi rekisteröidään Swagger servlet. Tämänkin voi tehdä annotaatioilla mutta kun sattui olemaan vielä web.xml (se on ainoa paikka jossa voi tehdä distributable-setin ha klusteriin) – tein sen siellä näin:

 <servlet>
 <servlet-name>JerseyJaxrsConfig</servlet-name>
 <servlet-class>com.wordnik.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
 <init-param>
 <param-name>api.version</param-name>
 <param-value>1.0.0</param-value>
 </init-param>
 <init-param>
 <param-name>swagger.api.basepath</param-name>
 <param-value>http://localhost:8080/rest/api-docs</param-value>
 </init-param>
 <load-on-startup>2</load-on-startup>
 </servlet>

Nyt alkaa jo melkein tapahtumaan. Seuraavaksi pitää varustaa ainakin yksi palvelu @Api-annotaatiolla, metodeille voi pistää @ApiOperation, ja parametreille ja paluuarvoille @ApiModel annotaatioita. Jotta saat jotain näkyviin tarvitset ainakin yhden @Api-annotaatiolla varustetun palvelun, jolla on ainakin yksi @ApiOperation annotaatiolla varustettu operaatio.

Tähän tapaan:

@Path("/pet")
@Api(value = "/pet", description = "Operations about pets")
@Produces({"application/json", "application/xml"})
public class PetResource {
  ...
@GET
@Path("/{petId}")
@ApiOperation(value = "Find pet by ID", notes = "More notes about this method", response = Pet.class)
@ApiResponses(value = {
  @ApiResponse(code = 400, message = "Invalid ID supplied"),
  @ApiResponse(code = 404, message = "Pet not found") 
})
public Response getPetById(
    @ApiParam(value = "ID of pet to fetch", required = true) @PathParam("petId") String petId)
    throws WebApplicationException {
@ApiModel(value = "A pet is a person's best friend")
@XmlRootElement(name = "Pet")
public class Pet {
  @XmlElement(name = "status")
  @ApiModelProperty(value = "Order Status", required=true, allowableValues = "placed,approved,delivered")
  public void setStatus(String status) {
    this.status = status;
  }
  public String getStatus() {
    return status;
  }

Sitten voitkin käynnistellä serverin, ja kokeilla mitä löytyy kontekstin alta osoitteella /api-docs, /api-docs/myservicename, jne – tässä tietysti myservicename on joku palvelu johon olet noita Swagger-annotaatioita ripotellut.

Tuolta löytyy myös esimerkkiä live-sisällöstä, niin kauan kuin se tietysti on pystyssä:

http://petstore.swagger.wordnik.com/api/api-docs

Näyttäisi tämmöiseltä:

{"apiVersion":"1.0.0","swaggerVersion":"1.2","apis":[{"path":"/pet","description":"Operations about pets"},{"path":"/user","description":"Operations about user"},{"path":"/store","description":"Operations about store"}],"authorizations":{"oauth2":{"type":"oauth2","scopes":[{"scope":"write:pets","description":"Modify pets in your account"},{"scope":"read:pets","description":"Read your pets"}],"grantTypes":{"implicit":{"loginEndpoint":{"url":"http://petstore.swagger.wordnik.com/oauth/dialog"},"tokenName":"access_token"},"authorization_code":{"tokenRequestEndpoint":{"url":"http://petstore.swagger.wordnik.com/oauth/requestToken","clientIdName":"client_id","clientSecretName":"client_secret"},"tokenEndpoint":{"url":"http://petstore.swagger.wordnik.com/oauth/token","tokenName":"auth_code"}}}}},"info":{"title":"Swagger Sample App","description":"This is a sample server Petstore server.  You can find out more about Swagger \n    at <a href=\"http://swagger.wordnik.com\">http://swagger.wordnik.com</a> or on irc.freenode.net, #swagger.  For this sample,\n    you can use the api key \"special-key\" to test the authorization filters","termsOfServiceUrl":"http://helloreverb.com/terms/","contact":"apiteam@wordnik.com","license":"Apache 2.0","licenseUrl":"http://www.apache.org/licenses/LICENSE-2.0.html"}}

Törmäsin myös toiseen aika metkaan standardiin – ALPS. Sitä näyttäisi osaavan Spring Framework hyvin, mutta ainakan nyky-jerseystä ei löytynyt helppoa ratkaisua siihen. Pidän tätäkin kuitenkin silmällä. Looking good!

http://www.dzone.com/links/r/spring_data_rest_now_comes_with_alps_metadata.html

http://alps.io/

Näistä linkeistä löytyy vähän lisää ideoita. Varovaisuutta vanhemman Swagger-version kanssa!

https://github.com/wordnik/swagger-core/wiki/Java-JAXRS-Quickstart

 

 

Mainokset

Vastaa

Täytä tietosi alle tai klikkaa kuvaketta kirjautuaksesi sisään:

WordPress.com-logo

Olet kommentoimassa WordPress.com -tilin nimissä. Log Out / Muuta )

Twitter-kuva

Olet kommentoimassa Twitter -tilin nimissä. Log Out / Muuta )

Facebook-kuva

Olet kommentoimassa Facebook -tilin nimissä. Log Out / Muuta )

Google+ photo

Olet kommentoimassa Google+ -tilin nimissä. Log Out / Muuta )

Muodostetaan yhteyttä palveluun %s