Question

I am new to swagger and I find the documentation to be fragmented and lacking to say the least. I am trying to use the Swagger annotation to annotate my JAX-RS compliant classes to statically generate client libraries in several languages and documentation (which is a plus). However, I can't seem to find a simple example that works out of the box.

Here's my very simple REST service:

package com.mypack.rest;

import com.mypack.entity.Person;
import com.mypack.service.PeopleService;
import com.wordnik.swagger.annotations.*;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Collection;

@Path("/people")
@Api(value = "/people", description = "Manage people")
public class PeopleRestService {
  private final PeopleService peopleService;

  public PeopleRestService(PeopleService peopleService) {
    this.peopleService = peopleService;
  }

  @Produces({MediaType.APPLICATION_JSON})
  @GET
  @ApiOperation(value = "List all people", notes = "List all people using paging", response = Person.class, responseContainer = "List")
  public Collection<Person> getPeople(@ApiParam(value = "Page to fetch", required = true) @QueryParam("page") @DefaultValue("1") final int page) {
    return peopleService.getPeople(page, 5);
  }

  @Produces({MediaType.APPLICATION_JSON})
  @Path("/{email}")
  @GET
  @ApiOperation(value = "Find person by e-mail", notes = "Find person by e-mail", response = Person.class)
  @ApiResponses({
        @ApiResponse(code = 404, message = "Person with such e-mail doesn't exists")
  })
  public Person getPeople(@ApiParam(value = "E-Mail address to lookup for", required = true) @PathParam("email") final String email) {
    return peopleService.getByEmail(email);
  }

// and more methods ...
}

and then I have a scala class to generate the client library (as per examples on github):

import com.wordnik.swagger.codegen.BasicJavaGenerator

object JavaPeopleServiceCodegen extends BasicJavaGenerator {
  def main(args: Array[String]) = generateClient(args)

  override def templateDir = "Java"
  override def destinationDir = "src/main/java"
  override def invokerPackage = Some("com.mypack.client")
  override def modelPackage = Some("com.mypack.entity")
  override def apiPackage = Some("com.mypack.api")

  additionalParams ++= Map(
    "artifactId" -> "people-rest",
    "artifactVersion" -> "1.0.0",
    "groupId" -> "com.mypack")

  override def supportingFiles =
    List(
      ("apiInvoker.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "ApiInvoker.java"),
      ("JsonUtil.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "JsonUtil.java"),
      ("apiException.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "ApiException.java"),
      ("pom.mustache", "", "pom.xml"))
}

Now when I try to run this file I always get the following error:

Exception in thread "main" java.lang.NoSuchMethodError: com.wordnik.swagger.model.SwaggerSerializers$.formats(Ljava/lang/String;)Lorg/json4s/Formats;
  at com.wordnik.swagger.codegen.Codegen.<init>(Codegen.scala:45)
  at com.wordnik.swagger.codegen.BasicGenerator.<init>(BasicGenerator.scala:44)
  at com.wordnik.swagger.codegen.BasicJavaGenerator.<init>(BasicJavaGenerator.scala:25)
  at JavaPeopleServiceCodegen$.<init>(JavaPeopleServiceCodegen.scala:3)

Finally, in my pom file I have dependencies for javax.ws.rs, swagger and swagger-codegen. I don't understand if I am missing some runtime dependencies (it doesn't look like it), my scala library is wrong (I have scala 2.10.3 installed and the swagger dependencies are compiled against 2.10, which should be binary compatible) or I haven't understood some basic "gotcha".

Any help?

Was it helpful?

Solution

The problem is class name collision. There is one SwaggerSerializers class in codegen project and one in swagger core. So what happened is compiler used one of these and another was tried to be used in runtime, hence a method missing.

I've just sent a pull request with one of possible refactorizations to address this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top