JAX-RS @PathParam Example

0

We define named URI path parameters in @Path expression. Its value is injected using @javax.ws.rs.PathParam annotation.

Dependencies

See http://www.javarticles.com/2016/01/jax-rs-path-annotation-example.html#dep for details.

PathParam Example

We define a path parameter in @Path and its value is injected using @PathParam.
In the below example, class level @Path("/product/{productName}") annotation hold parameter productName. We inject the product name using @PathParam("productName"). See method findProductByName().

Its possible to refer to multiple path parameters. In findProductByid(), we refer to more than one URI path parameter, product name and its ID.

PathParamExamples:

package com.javarticles.rest;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;

@Path("/product/{productName}")
@Produces(MediaType.TEXT_PLAIN)
public class PathParamExamples {

    @GET
    public String findProductByName(@PathParam("productName") String name) {
        return "Find products by name <" + name + ">";
    }

    @Path("{id}")
    @GET
    public String findProductByid(@PathParam("productName") String name,
            @PathParam("id") String id) {
        return "Find products by name <" + name + ">, id <" + id + ">";
    }
}

Enter http://localhost:8280/myapp/product/bed in browser.

Output:

Find products by name <bed>

Enter <codehttp://localhost:8280/myapp/product/bed/7188 in browser.

Output:

Find products by name <bed>, sku <7188>

PathSegment Example

We now know that @PathParam injects value of the parameter defined in @Param annotation. The parameter value being a string naturally maps to a method argument whose type is a string. If the URI contains a matrix of parameters, for example, http://localhost:8280/myapp/product/bed/details;size=king;color=teak/9199. If you want to access the path and matrix parameters (text in blue), then the type of the value that PathParam injects can’t be string any more. We need some abstraction using which we can access the path as well as the matrix parameters and this where class PathSegment comes in.

package javax.ws.rs.core;
public interface PathSegment {
    String getPath();
    MultivaluedMap<String, String> getMatrixParameters();
}

The value that @PathParam injects can be of type javax.ws.rs.core.PathSegment, this way we have access to both path and matrix parameters.

PathParamExamples:

package com.javarticles.rest;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;

@Path("/product/{productName}")
@Produces(MediaType.TEXT_PLAIN)
public class PathParamExamples {

    @GET
    public String findProductByName(@PathParam("productName") String name) {
        return "Find products by name <" + name + ">";
    }

    @Path("{id}")
    @GET
    public String findProductByid(@PathParam("productName") String name,
            @PathParam("id") String id) {
        return "Find products by name <" + name + ">, id <" + id + ">";
    }

    @Path("{details}/{id}")
    @GET
    public String findProductByDetails(@PathParam("productName") String name,
            @PathParam("details") PathSegment pathSegment,
            @PathParam("id") String id) {
        MultivaluedMap<String, String> map = pathSegment.getMatrixParameters();
        StringBuilder sb = new StringBuilder();
        sb.append(pathSegment.getPath());
        for (String key : map.keySet()) {
            sb.append("key=").append(key).append(",").append("value=")
                    .append(map.get(key)).append("|");
        }
        return "Find products by name <" + name + ", details <" + sb + ">";
    }
}

Enter http://localhost:8280/myapp/product/bed/details;size=king;color=teak/9199 in browser.

Output:

Find products by name <bed, details <detailskey=size,value=[king]|key=color,value=[teak]|>

Matching Multiple PathSegments

Sometimes the expression in @Path annotation can result in more than one path segments.
For example, if the path expression is:
code>”product/{productName}/{details: .+}/group/{group}” and
the URI is http://localhost:8280/myapp/product/bed/storage/details;make=teak;size=king/group/bestsellers,
then path parameter details holds two path segments.

  1. storage
  2. details;make=teak;size=king

Since there are more than one path segments and we need to make sure that the type of the parameter is a list of PathSegments so that both the segments can be injected. See findProductByMultipleDetails(), the details parameter is of type List<PathSegment>.

PathParamExamples:

package com.javarticles.rest;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;

@Path("/product/{productName}")
@Produces(MediaType.TEXT_PLAIN)
public class PathParamExamples {

    @GET
    public String findProductByName(@PathParam("productName") String name) {
        return "Find products by name <" + name + ">";
    }

    @Path("{id}")
    @GET
    public String findProductByid(@PathParam("productName") String name,
            @PathParam("id") String id) {
        return "Find products by name <" + name + ">, id <" + id + ">";
    }

    @Path("{details}/{id}")
    @GET
    public String findProductByDetails(@PathParam("productName") String name,
            @PathParam("details") PathSegment pathSegment,
            @PathParam("id") String id) {
        MultivaluedMap<String, String> map = pathSegment.getMatrixParameters();
        StringBuilder sb = new StringBuilder();
        sb.append(pathSegment.getPath());
        for (String key : map.keySet()) {
            sb.append("key=").append(key).append(",").append("value=")
                    .append(map.get(key)).append("|");
        }
        return "Find products by name <" + name + ", details <" + sb + ">";
    }

    @Path("{details: .+}/group/{group}")
    @GET
    public String findProductByMultipleDetails(
            @PathParam("productName") String name,
            @PathParam("details") List<PathSegment> pathSegmentList,
            @PathParam("group") String group) {
        StringBuilder sb = new StringBuilder();        
        for (PathSegment ps : pathSegmentList) {
            sb.append("Path=");
            sb.append(ps.getPath());
            
            sb.append(", key/value={");
            MultivaluedMap<String, String> map = ps.getMatrixParameters();
            for (String key : map.keySet()) {
                sb.append("key=").append(key).append(",").append("value=")
                        .append(map.get(key)).append("|");
            }
            sb.append("}|");                        
        }
        return "Find products by name <" + name + ">, details <" + sb + ">" + ", group <" + group + ">" ;
    }
}

Enter http://localhost:8280/myapp/product/bed/storage/details;make=teak;size=king/group/bestsellers in browser.

Output:

Find products by name <bed>, details <Path=storage, key/value={}|Path=details, key/value={key=size,value=[king]|key=make,value=[teak]|}|>, group <bestsellers>

Download the source code

This was an example about JAX-RS @PathParam Annotation.

You can download the source code here: JaxRsPathParamExample.zip
Share.

Comments are closed.