Close

JAX-RS, Multi values for a request header examples

[Last Updated: Feb 6, 2019]

JAX-RS 

In following examples we will send multiple values for a single request header name to a JAX-RS resource and will observe the behavior.

The resource class

@Path("/")
public class MyResource {

  @GET
  @Path("test")
  public String collectionTest(@HeaderParam("myHeader") List<String> list) {
      if (list == null) {
          return "null";
      }
      String rv = "Collection size: " + list.size() +
              "\nvalues: \n";
      rv += list.stream()
                .map(Object::toString)
                .collect(Collectors.joining("\n"));
      return rv;
  }
    .............
}

We are also going to register a ContainerRequestFilter to print the request header on server console:

@Provider
public class MyFilter implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
      System.out.println("--request headers-----");
      MultivaluedMap<String, String> headers = requestContext.getHeaders();
      headers.entrySet().forEach(System.out::println);
  }
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run

The client

public class MyClient {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target = client.target("http://localhost:8080/test");
      Invocation.Builder builder = target.request();
      String response = builder.header("myHeader", "a")
                               .header("myHeader", "b")
                               .get(String.class);
      System.out.println(response);
      client.close();
  }
}

Output:

Collection size: 1
values:
a,b

Server console:

--request headers-----
myheader=[a,b]
user-agent=[Jersey/2.25.1 (HttpUrlConnection 1.8.0_65)]
host=[localhost:8080]
accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2]
connection=[keep-alive]

As seen in the server console (the filter output), the incoming request are comma separated header values instead of separate header values. Jersey does not attempt to split comma separated multi header values. that is per HTTP standard header format as mentioned in this jira.

In above example, MyClient uses standard JAX-RS client API, to send multiple header values. The method Builder#header() prepare comma separated header values even though we added separate values. A related jira here.

Sending multi header values using HttpURLConnection

Jersey does assign 'separate multi-line header values' (as opposed to comma separated values) to the @HeaderParam collection. In this example we are using HttpURLConnection to send request to the resource:

public class MyClient2 {
  public static void main(String[] args) throws Exception {
      final URL url = new URL("http://localhost:8080/test");
      final HttpURLConnection connection = (HttpURLConnection) url.openConnection();

      connection.setRequestMethod("GET");
      connection.setRequestProperty("myHeader", "a");
      connection.addRequestProperty("myHeader", "b");

      connection.setDoOutput(false);
      connection.connect();

      String s = ReaderWriter.readFromAsString(new InputStreamReader(connection.getInputStream()));

      System.out.println(s);
  }
}

HttpURL Connection# set Request Property()sets the first header. The method HttpURL Connection# add Request Property() adds additional header values.

Resource response

Collection size: 2
values:
a
b

Server console:

--request headers-----
myheader=[a, b]
user-agent=[Java/1.8.0_65]
host=[localhost:8080]
accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2]
connection=[keep-alive]

Sending multi header values from JQuery Ajax

src/main/resources/myPage.html

<html lang="en">
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
</head>
<body>
<div id="responseDiv"></div>
<script>
  $.ajax({
    url: 'http://localhost:8080/test',
    headers: { 'myHeader': 'a', 'myHeader': 'b'  }
 }).done(function(data) {
    $("#responseDiv").html(data);
});;
</script>
</body>
</html>
@Path("/")
public class MyResource {
    .............
  @GET
  @Path("page")
  @Produces({MediaType.TEXT_HTML})
  public InputStream viewPage() {
      return MyResource.class.getClassLoader()
                             .getResourceAsStream("myPage.html");
  }
}

Server console:

--request headers-----
host=[localhost:8080]
connection=[keep-alive]
accept=[*/*]
x-requested-with=[XMLHttpRequest]
myheader=[b]
user-agent=[Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36]
referer=[http://localhost:8080/page]
accept-encoding=[gzip, deflate, sdch, br]
accept-language=[en-US,en;q=0.8]

As seen in above output, JQuery sends the last header value if there are multiple values for the same header key.

Example Project

Dependencies and Technologies Used:

  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

jaxrs-header-multi-values Select All Download
  • jaxrs-header-multi-values
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyResource.java
          • resources

    See Also