bennnnnnjamin
bennnnnnjamin

Reputation: 53

Restlet Studio Error 422 when generating sample client and server

Hi I'm using the restlet studio to generate a client and server from your sample pet store API . Here are my steps:

  1. Generate Java Server (JAX-RS)
  2. Edit pom.xml to make a war file
  3. mvn package
  4. Deploy to jetty server as webapp
  5. Verify it works by going to hitting the URL with a browser: http://54.149.215.125:8080/v2/pet/findByTags

Response:

{"code":4,"type":"ok","message":"magic!"}
  1. At this point I think it works, until I generate the client in Java
  2. I change the endpoint from the webnik one to my webserver
  3. Make a simple main method

    public static void main(String[] args) {
        try {
            FindPetByTagsClientResource a = new FindPetByTagsClientResource();
            Pet represent = a.represent();
    
        } catch (Exception ex) {
            Logger.getLogger(APIPetStore.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
  4. When I run it I get this:

run: Starting the internal HTTP client null

Unprocessable Entity (422) - The server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the contained instructions at org.restlet.resource.Resource.toObject(Resource.java:893) at org.restlet.engine.resource.ClientInvocationHandler.invoke(ClientInvocationHandler.java:326) at com.sun.proxy.$Proxy5.represent(Unknown Source) at net.apispark.webapi.client.FindPetByTagsClientResource.represent(FindPetByTagsClientResource.java:22) at apipetstore.APIPetStore.main(APIPetStore.java:28) Caused by: java.io.IOException: Unable to create the Object representation at org.restlet.engine.converter.DefaultConverter.toObject(DefaultConverter.java:282) at org.restlet.service.ConverterService.toObject(ConverterService.java:229) at org.restlet.resource.Resource.toObject(Resource.java:889) ... 4 more Caused by: java.lang.IllegalArgumentException: The serialized representation must have this media type: application/x-java-serialized-object or this one: application/x-java-serialized-object+xml at org.restlet.representation.ObjectRepresentation.(ObjectRepresentation.java:221) at org.restlet.representation.ObjectRepresentation.(ObjectRepresentation.java:123) at org.restlet.representation.ObjectRepresentation.(ObjectRepresentation.java:104) at org.restlet.engine.converter.DefaultConverter.toObject(DefaultConverter.java:279) ... 6 more BUILD SUCCESSFUL (total time: 0 seconds)

  1. Change the main method to this and it works:

    public static void main(String[] args) {
        try {
            FindPetByTagsClientResource a = new FindPetByTagsClientResource();
    
            a.getClientResource().get().write(System.out);
        } catch (Exception ex) {
            Logger.getLogger(APIPetStore.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
  2. Output:

Starting the internal HTTP client

{"code":4,"type":"ok","message":"magic!"}

Any ideas on how I can fix this?

Upvotes: 0

Views: 624

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202346

In fact, the JAXRS server skeleton is really a server skeleton ;-) This means that it doesn't actually send back the right content according to the client. If you look at the server code, you always see this:

public Response findPetsByTags(@ApiParam(value = "Tags to filter by") @QueryParam("tags") List<String> tags)
                throws NotFoundException {
    // do some magic!
    return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
}

It doesn't correspond to a list of pet objects...

On the client side, you got the error since you try to use annotated interfaces. They automatically try to use the internal converter of Restlet. It fails since it expects an object of type Pet and you received something with this structure: {"code":4,"type":"ok","message":"magic!"}.

In conclusion, you need to do some work to adapt the server skeleton to return the correct objects. Here is an hardcoded solution to make work your client SDK:

@GET
@Path("/findByTags")
@ApiOperation(value = "Finds Pets by tags", notes = "Finds Pets by tags", response = Pet.class, responseContainer = "List")
@ApiResponses(value = { 
  @ApiResponse(code = 400, message = "") })

public Response findPetsByTags(@ApiParam(value = "Tags to filter by") @QueryParam("tags") List<String> tags)
      throws NotFoundException {
    // do some magic!
    Pet pet = new Pet();
    pet.setId(10);
    pet.setName("My pet");
    pet.setStatus("status");
    List<Tag> actualTags = new ArrayList<Tag>();
    Tag tag1 = new Tag();
    tag1.setId(1);
    tag1.setName("tag1");
    actualTags.add(tag1);
    Tag tag2 = new Tag();
    tag2.setId(2);
    tag2.setName("tag2");
    actualTags.add(tag2);
    pet.setTags(actualTags);
    return Response.ok().entity(pet).build();
}

I'll have a look if we can improve this for the server side. In fact, the Restlet Studio internally uses the swagger2 codegen tool chain to generate this server skeleton.

Hope it helps, Thierry

Upvotes: 2

Related Questions