Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] [jaxrs-spec] FormParam used instead of FormDataParam for "multipart/form-data" #5957

Open
kdebski85 opened this issue Apr 16, 2020 · 3 comments

Comments

@kdebski85
Copy link

kdebski85 commented Apr 16, 2020

Bug Report Checklist

Description

jaxrs-spec generator adds javax.ws.rs.FormParam annotation to parameters when content type is set to multipart/form-data

It causes the following error with Jersey (jaxrs reference implementation) for primitive types:

java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
        at org.glassfish.jersey.server.internal.inject.FormParamValueParamProvider$FormParamValueProvider.ensureValidRequest(FormParamValueParamProvider.java:107)

When javax.ws.rs.FormParam is applied to a Java bean, Jersey throws a different error:

org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public abstract javax.ws.rs.core.Response com.foo.FooApi.addFoo(com.foo.FooDto) at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[multipart/form-data], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=interface com.foo.FooApi handlerConstructors=[]}, definitionMethod=public abstract javax.ws.rs.core.Response com.foo.FooApi.addFoo(com.foo.FooDto), parameters=[Parameter [type=class com.foo.FooDto, source=metadata, defaultValue=null]], responseType=class javax.ws.rs.core.Response}, nameBindings=[]}']
        at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:371) ~[jersey-server-2.29.1.jar:na]
openapi-generator version

openapi-generator-maven-plugin 4.3.0 with jaxrs-spec generator

OpenAPI declaration file content or url

For simple parameter:

   requestBody:
     content:
         multipart/form-data:
            schema:
              properties:
                foo:
                  type: integer
                  format: int32

For bean parameter:

   requestBody:
     content:
         multipart/form-data:
            schema:
              type: object
              properties:
                metadata:
                   $ref: '#/components/schemas/FooDto'
Command line used for generation

openapi-generator-maven-plugin with jaxrs-spec generator

Steps to reproduce
  1. Generate API with openapi-generator-maven-plugin and jaxrs-spec generator
  2. Implement the API
  3. Add org.springframework.boot:spring-boot-starter-jersey and org.glassfish.jersey.media:jersey-media-multipart to your project
  4. In JerseyConfig add register(MultiPartFeature.class);
  5. Try invoking generated endpoints. It will return the error described above
  6. (optional) Manually change the annotation in generated classes to FormDataParam and check that it works.
Related issues/PRs
Suggest a fix

I checked that when javax.ws.rs.FormParam is replaced with org.glassfish.jersey.media.multipart.FormDataParam, everything works fine.

However, org.glassfish.jersey.media.multipart.FormDataParam is Jersey specific.
Maybe there should be a configuration option to choose which annotation should be used for multi part parameters.

More about Multipart in Jersey:
https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/media.html#multipart

@kdebski85
Copy link
Author

As a workaround, I use replacer plugin:

      <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>1.5.3</version>
        <executions>
          <execution>
            <phase>process-resources</phase>
            <goals>
              <goal>replace</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <file>target/generated-sources/openapi/src/main/java/(path to API java file)</file>
          <replacements>
            <replacement>
              <token>@FormParam</token>
              <value>@org.glassfish.jersey.media.multipart.FormDataParam</value>
            </replacement>
          </replacements>
        </configuration>
      </plugin>

@pvdbosch
Copy link

jakartaee/rest#418 talks about adding support for multipart to JAX-RS. It lists the different implementation-specific mechanisms that currently exist (jakartaee/rest#418 (comment)), but the generated code doesn't seem to match any of them.

Maybe the jaxrs-spec code generator should fall back to generate an InputStream as type, and let other flavors (jaxrs-jersey, jaxrs-resteasy, ...) generate the implementation-specific methods?

@dhutchison
Copy link
Contributor

Looks like this will be possible in the JAX-RS 3.1 spec, with the spec change having been included in this PR.

That is likely tied into Jakarta EE 10, so it is going to be a while until this can be fixed in the jaxrs-spec generator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants