Thursday, January 05, 2012

JAX-RS Tip of the Day: Using @CookieParam

I am not a fan of using cookies in REST based services. I think that it makes the service less usable since the client must be able to store and retrieve cookies. This limits usage of the service, and introduces state outside of the service. Even the RFC for cookies is called HTTP State Management Mechanismcurl can be used to send cookies to test so not all is lost.

Alright, if I have not talked you out of using them yet, you must have a need for them.  (Please rethink the idea though).

Use of cookies is accomplished by using the @CookieParam annotation. Also you can return responses as shown in the code below which include cookies.

Cookies have a limitations on the use of some characters, and names so please look at the RFC noted above for additional limitations. I demonstrate a couple of limitations which include the use of semi-colons (;), and commas(,). The nice thing about this example is you can see the output in a real browser (Internet Explorer not included) since most can handle application/json objects which are returned.

Here is the example code developed using NetBeans 7.1 RC2 and GlassFish 3.1.1cookie-parameters.zip

CookieParameterResource.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
 * Copyright 2012 Blue Lotus Software, LLC.
 * Copyright 2012 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: CookieParameterResource.java,v 8aa9e8cbb19a 2012/01/05 12:47:08 jyeary $
 */
package com.bluelotussoftware.jaxrs.resources;
 
import java.text.DateFormat;
import java.util.Date;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
 
/**
 * An example application which demonstrates the use of {@link javax.ws.rs.CookieParam}.
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
@Path("example")
@RequestScoped
public class CookieParameterResource {
 
    @Context
    private HttpHeaders headers;
 
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response get(
            @CookieParam(value = "User-Agent") String userAgent,
            @CookieParam(value = "Last-Accessed") String lastAccessed,
            @HeaderParam(value = "User-Agent") String userAgentHeader) {
        try {
 
            // Cookies have restrictions on the use of semi-colons, and commas so we replace them with directives.
            NewCookie agentCookie = new NewCookie("User-Agent",
                    userAgentHeader.replace(";", "##semicolon##").replace(",", "##comma##"));
            String accessed = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG).format(new Date());
            NewCookie lastAccessedCookie = new NewCookie("Last-Accessed", accessed);
 
            JSONObject jsono = new JSONObject();
            jsono.append("user-agent", userAgentHeader);
            jsono.append("accessed", accessed);
 
            if (userAgent != null) {
                jsono.append("previous-agent", userAgent.replace("##semicolon##", ";").replace("##comma##", ","));
            } else {
                jsono.append("previous-agent", null);
            }
 
            jsono.append("last-accessed", lastAccessed);
 
            return Response.ok(jsono, MediaType.APPLICATION_JSON).cookie(agentCookie, lastAccessedCookie).build();
        } catch (JSONException ex) {
            throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR);
        }
    }
}

0 comments :

Popular Posts