REST Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Introduction

Jersey is a popular Java framework for creating RESTful web services.

In this tutorial, we'll explore how to read different request parameter types via a simple Jersey project.

2. Project Setup

Using Maven archetypes, we'll be able to generate a working project for our article:

mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2
  -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false
  -DgroupId=com.example -DartifactId=simple-service -Dpackage=com.example
  -DarchetypeVersion=2.28

The generated Jersey project will run on top of a Grizzly container.

Now, by default, the endpoint for our app will be http://localhost:8080/myapp.

Let's add an items resource, which we'll use for our experiments:

@Path("items")
public class ItemsController {
    // our endpoints are defined here
}

Note, by the way, that Jersey also works great with Spring controllers.

3. Annotated Parameters Types

So, before we actually read any request parameters, let's clarify a few rules. The allowed types of parameters are:

  • Primitive types, like float and char
  • Types that have a constructor with a single String argument
  • Types that have either a fromString or valueOf static method; for those, a single String argument is mandatory
  • Collections – like List, Set, and SortedSet – of the types described above

Also, we can register an implementation of the ParamConverterProvider JAX-RS extension SPI. The return type must be a ParamConverter instance capable of a conversion from a String to a type.

4. Cookies

We can resolve cookie values in our Jersey methods using the @CookieParam annotation:

@GET
public String jsessionid(@CookieParam("JSESSIONId") String jsessionId) {
    return "Cookie parameter value is [" + jsessionId+ "]";
}
If we start up our container, we can cURL this endpoint to see the response:
> curl --cookie "JSESSIONID=5BDA743FEBD1BAEFED12ECE124330923" http://localhost:8080/myapp/items
Cookie parameter value is [5BDA743FEBD1BAEFED12ECE124330923]

5. Headers

Or, we can resolve HTTP headers with the @HeaderParam annotation:

@GET
public String contentType(@HeaderParam("Content-Type") String contentType) {
    return "Header parameter value is [" + contentType+ "]";
}

Let's test again:

> curl --header "Content-Type: text/html" http://localhost:8080/myapp/items
Header parameter value is [text/html]

6. Path Parameters

Especially with RESTful APIs, it's common to include information in the path.

We can extract path elements with @PathParam:

@GET
@Path("/{id}")
public String itemId(@PathParam("id") Integer id) {
    return "Path parameter value is [" + id + "]";
}

Let's send another curl command with the value 3:

> curl http://localhost:8080/myapp/items/3
Path parameter value is [3]

7. Query Parameters

We commonly use query parameters in RESTful APIs for optional information.

To read such values we can use the @QueryParam annotation:

@GET
public String itemName(@QueryParam("name") String name) {
    return "Query parameter value is [" + name + "]";
}

So, now we can test with curl, like before:

> curl http://localhost:8080/myapp/items?name=Toaster
Query parameter value if [Toaster]

8. Form Parameters

For reading parameters from a form submission, we’ll use the @FormParam annotation:
@POST
public String itemShipment(@FormParam("deliveryAddress") String deliveryAddress, 
  @FormParam("quantity") Long quantity) {
    return "Form parameters are [deliveryAddress=" + deliveryAddress+ ", quantity=" + quantity + "]";
}

We also need to set the proper Content-Type to mimic the form submission action. Let's set the form parameters using the -d flag:

> curl -X POST -H 'Content-Type:application/x-www-form-urlencoded' \
  -d 'deliveryAddress=Washington nr 4&quantity=5' \
  http://localhost:8080/myapp/items
Form parameters are [deliveryAddress=Washington nr 4, quantity=5]

9. Matrix Parameters

A matrix parameter is a more flexible query parameter as they can be added anywhere in the URL.

For example, in http://localhost:8080/myapp;name=value/items, the matrix parameter is name.

To read such values, we can use the available @MatrixParam annotation:

@GET
public String itemColors(@MatrixParam("colors") List<String> colors) {
    return "Matrix parameter values are " + Arrays.toString(colors.toArray());
}

And now we'll test again our the endpoint:

> curl http://localhost:8080/myapp/items;colors=blue,red
Matrix parameter values are [blue,red]

10. Bean Parameters

Finally, we'll check how to combine request parameters using bean parameters. To clarify, a bean parameter is actually an object that combines different types of request parameters.

We'll use a header parameter, a path and a form one in here:

public class ItemOrder {
    @HeaderParam("coupon")
    private String coupon;

    @PathParam("itemId")
    private Long itemId;

    @FormParam("total")
    private Double total;

    //getter and setter

    @Override
    public String toString() {
        return "ItemOrder {coupon=" + coupon + ", itemId=" + itemId + ", total=" + total + '}';
    }
}

Also, to get such a combination of parameters, we'll use the @BeanParam annotation:

@POST
@Path("/{itemId}")
public String itemOrder(@BeanParam ItemOrder itemOrder) {
    return itemOrder.toString();
}

In the curl command, we've added those three types of parameters and we'll end up with a single ItemOrder object:

> curl -X POST -H 'Content-Type:application/x-www-form-urlencoded' \
  --header 'coupon:FREE10p' \
  -d total=70 \
  http://localhost:8080/myapp/items/28711
ItemOrder {coupon=FREE10p, itemId=28711, total=70}

11. Conclusion

To sum it up, we've created a simple setup for a Jersey project to help us explore how to read different parameters from a request using Jersey.

The implementation of all these snippets is available over on Github.

REST bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!