Store @PathParam values ​​from REST call in a list or array

My function looks like this:

    @PUT
    @Path("property/{uuid}/{key}/{value}")
    @Produces("application/xml")    
    public Map<String,ValueEntity> updateProperty(@Context HttpServletRequest request,
            @PathParam("key") String key,
            @PathParam("value") String value,
            @PathParam("uuid") String uuid) throws Exception {
                                       ...
                             }

      

I need to change it so it accepts an undefined (or many) list of key-value pairs from a REST call, something like

@Path("property/{uuid}/{key1}/{value1}/{key2}/{value2}/{key3}/{value3}/...")

      

Is it possible to store them in an array or a list, so I don't list dozens of @PathParams and parameters to avoid this:

@PathParam("key1") String key1,
@PathParam("key2") String key2,
@PathParam("key3") String key3,

      

+3


source to share


2 answers


It might be a good opportunity to rethink this design. By using /

s, we denote, with each one /

, that we are trying to find another resource. Key / value pair (in the context of a URL) mainly refers to query parameters or matrix parameters.

If /property/{uuid}

is the path to the main resource and we just want to offer some parameters to the client to access that resource, then we can allow matrix parameters or query parameters

The matrix parameters (in the request url) will look something like this:

/12345;key1=value1;key2=value2;key3=value3

      

A resource method for getting values ​​might look something like this:



@GET
@Path("/property/{uuid}")
public Response getMatrix(@PathParam("uuid") PathSegment pathSegment) {
    StringBuilder builder = new StringBuilder();

    // Get the {uuid} value
    System.out.println("Path: " + pathSegment.getPath());

    MultivaluedMap matrix = pathSegment.getMatrixParameters();
    for (Object key : matrix.keySet()) {
        builder.append(key).append(":")
               .append(matrix.getFirst(key)).append("\n");
    }
    return Response.ok(builder.toString()).build();
}

      

The request parameters (in the request url) might look something like this:

/12345?key1=value1&key2=value2&key3=value3

      

A resource method for getting values ​​might look something like this:



@GET
@Path("/property/{uuid}")
public Response getQuery(@PathParam("uuid") String uuid, 
                         @Context UriInfo uriInfo) {

    MultivaluedMap params = uriInfo.getQueryParameters();
    StringBuilder builder = new StringBuilder();
    for (Object key : params.keySet()) {
        builder.append(key).append(":")
               .append(params.getFirst(key)).append("\n");
    }
    return Response.ok(builder.toString()).build();
}

      

The difference is that Matrix parameters can be embedded in route segments, and query parameters must be placed at the end of the URL. You may also notice a slight difference in syntax.


Some resources


UPDATE

Also looking at PUT

in your method signature it seems you are trying to update the resource using that path as the values ​​you are trying to update, since I don't see any parameters in your method for the subject. When PUTting, you should send the view to the entity body, not as segments or path parameters.

+5


source


Workaround:

@Path("/foo/bar/{other: .*}
public Response foo(@PathParam("other") VariableStrings vstrings) {

   String[] splitPath = vstrings.getSplitPath();


}

      

VariableStrings class:

public class VariableStrings {

   private String[] splitPath;

   public VariableStrings(String unparsedPath) {
     splitPath = unparsedPath.split("/");
   }
}

      



Sequence segment path to vararg array in JAX-RS / Jersey?

Another example where you map an optional parameter to Map:

@GET
@ Produces({"application/xml", "application/json", "plain/text"})
@ Path("/location/{locationId}{path:.*}")
public Response getLocation(@PathParam("locationId") int locationId, @PathParam("path") String path) {
    Map < String, String > params = parsePath(path);
    String format = params.get("format");
    if ("xml".equals(format)) {
        String xml = "<location<</location<<id<</id<" + locationId + "";
        return Response.status(200).type("application/xml").entity(xml).build();
    } else if ("json".equals(format)) {
        String json = "{ 'location' : { 'id' : '" + locationId + "' } }";
        return Response.status(200).type("application/json").entity(json).build();
    } else {
        String text = "Location: id=" + locationId;
        return Response.status(200).type("text/plain").entity(text).build();
    }
}

private Map < String, String > parsePath(String path) {
    if (path.startsWith("/")) {
        path = path.substring(1);
    }
    String[] pathParts = path.split("/");
    Map < String, String > pathMap = new HashMap < String, String > ();
    for (int i = 0; i < pathParts.length / 2; i++) {
        String key = pathParts[2 * i];
        String value = pathParts[2 * i + 1];
        pathMap.put(key, value);
    }
    return pathMap;
}

      

+3


source







All Articles