Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

jax rs - Is there a way to specify query parameters in the @Path annotation?

I have a Quarkus service where I'm trying (to some extent) to mimic the S3 API.

I noticed that the multipart upload in S3 goes something like this:

POST bucket.host.com /KEY?uploads // signifies that a multipart upload on KEY is starting
                                  // and returns an uploadId for it
PUT bucket.host.com /KEY?uploadId=UPLOADID&partNumber=2 // uploads part 2 of the file,
                                                        // content is in request body
PUT bucket.host.com /KEY?uploadId=UPLOADID&partNumber=1 // upload part 1
POST bucket.host.com /KEY?uploadId=UPLOADID // signifies that the multipart upload is completed

An "atomic" file upload (that is, no multipart, file is just uploaded in one go) "reuses" the PUT path, so to upload a file in that way you just do a PUT on the URL and skip both the query parameters.

I'm not going to use the "bucket is embedded in the host name" approach and instead it will be part of the request URL.

So what I currently have is a resource class that looks like this (simplified and bucket is called "project" in my case and KEY is called "path"):

@Path("/fts")
class FileTransferService(
    @ConfigProperty(name = "fts.project.root")
    private val projectRoot: String
) {

    @POST
    @Path("{project}/{path:.*}")
    @Produces(MediaType.APPLICATION_JSON)
    fun multipartFileUpload(
        @PathParam project: String,
        @PathParam path: String,
        @QueryParam("uploads") uploads: String?,
        @QueryParam("uploadId") uploadId: String?
    ): String {
        // Here I'll have to check whether uploads or uploadId is set
        // and determine the path to take with some if/else statements.
    }

    @PUT
    @Path("{project}/{path:.*}")
    @Produces(MediaType.APPLICATION_JSON)
    fun upload(
        @PathParam project: String,
        @PathParam path: String,
        @QueryParam("uploadId") uploadId: String?,
        @QueryParam("partNumber") partNumber: String?,
        body: InputStream
    ): String {
        // Here I'll need to check uploadId and/or partNumber to determine
        // whether this is an "atomic file upload" or a single part of a 
        // multi part upload and determine the path to take with if/else again.
    }
}

As you see in the comments in the above code I have to do some if/else checking and go different routes depending on whether or not the query parameters are set.

This bugs me. I would rather have different @POST methods, one catching the case where the uploads parameter is set, and another one if the uploadId parameter is set.

I tried having multiple methods where one specifies the QueryParameter and another one doesn't but that doesn't seem to work. I get an information message in the quarkus log saying that multiple matches were found for the path and one is picked randomly (probably just the first one).

So I'm guessing that if this is at all possible, it would be by somehow putting the query parameters into the @Path annotation but I have not been able to find how I would do that. A probable reason for that is that it just isn't possible but I wanted to ask here and get confirmation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your current version is correct if you want to use query parameters.

You won't be able to do what you want to do with JAX-RS. The path is what determines the method called, query parameters are just optional additional information.

If you absolutely wanted to have different methods depending on parameter presence, you would need to use path parameters.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...