mulesoft-labs / raml-for-jax-rs

This project is all about two way transformation of JAX-RS-annotated Java code to RAML API description and back.
Other
296 stars 181 forks source link

Exception if query parameters are defined as object type #229

Closed leflamm closed 7 years ago

leflamm commented 7 years ago

Being on commit 4d6de5d (HEAD -> release/2.0.0, origin/release/2.0.0)

raml-to-jaxrs-cli will fail if query parameters are defined as object type.

Exception in thread "main" org.raml.jaxrs.generator.GenerationException: query parameter is composite: org.raml.jaxrs.generator.v10.V10PGParameter@bdd2027
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder.createMethodBuilder(ResourceBuilder.java:392)
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder.createMethodWithoutBody(ResourceBuilder.java:155)
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder.buildResource(ResourceBuilder.java:127)
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder.access$400(ResourceBuilder.java:74)
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder$DefaultResourceClassCreator.onResource(ResourceBuilder.java:498)
    at org.raml.jaxrs.generator.extension.resources.ResourceClassExtension$Composite$1.doElement(ResourceClassExtension.java:48)
    at org.raml.jaxrs.generator.extension.resources.ResourceClassExtension$Composite$1.doElement(ResourceClassExtension.java:44)
    at org.raml.jaxrs.generator.extension.AbstractCompositeExtension.runList(AbstractCompositeExtension.java:42)
    at org.raml.jaxrs.generator.extension.resources.ResourceClassExtension$Composite.onResource(ResourceClassExtension.java:44)
    at org.raml.jaxrs.generator.builders.resources.ResourceBuilder.output(ResourceBuilder.java:96)
    at org.raml.jaxrs.generator.CurrentBuild.generate(CurrentBuild.java:139)
    at org.raml.jaxrs.generator.RamlScanner.handle(RamlScanner.java:94)
    at org.raml.jaxrs.generator.RamlScanner.handle(RamlScanner.java:74)
    at org.raml.jaxrs.generator.RamlScanner.handle(RamlScanner.java:55)
    at org.raml.jaxrs.ramltojaxrs.Main.main(Main.java:75)

https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#query-parameters-in-a-query-string

jpbelang commented 7 years ago

I maybe misunderstanding your request, but the raml spec doesn't square very well with jaxrs here:

public @interface QueryParam

Binds the value(s) of a HTTP query parameter to a resource method parameter, resource class field, or resource class bean property. Values are URL decoded unless this is disabled using the Encoded annotation. A default value can be specified using the DefaultValue annotation. The type T of the annotated parameter, field or property must either: Be a primitive type Have a constructor that accepts a single String argument Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String)) Have a registered implementation of ParamConverterProvider JAX-RS extension SPI that returns a ParamConverter instance capable of a "from string" conversion for the type. Be List, Set or SortedSet, where T satisfies 2, 3 or 4 above. The resulting collection is read-only. If the type is not one of the collection types listed in 5 above and the query parameter is represented by multiple values then the first value (lexically) of the parameter is used.

We could generate the object, but the user would have to provide a plugin to generate one of either static methods, or implement an interface.

Stuff like this If a query parameter declaration specifies a non-array type for the value of the query parameter, or doesn't specify a type (equivalent to specifying a string type), processors MUST disallow multiple instances of that query parameter in the request.

is against the jaxrs spec.

jstoiko commented 7 years ago

I have seen at least two different ways of implementing objects in query parameters.

1) using JSON, e.g. /foo?param={'object':'json'} 2) using dot-notation, e.g. /foo?param.object=json

I personally prefer option 2) but I don't have strong arguments against option 1) plus I think one should have the ability to implement it the way one wants. That being said, @leflamm: would you be ok with what @jpbelang suggested?

We could generate the object, but the user would have to provide a plugin to generate one of either static methods, or implement an interface.

leflamm commented 7 years ago

Yes, I currently fail to see another option.

jpbelang commented 7 years ago

Iv'e fixed this, but it currently requires the user to register a ParameterConverterProvider in jaxrs, as types are currently interfaces right now (so we can't add a static method to it.