/
Cache_NoCache_CacheControl.xml
185 lines (167 loc) · 8.15 KB
/
Cache_NoCache_CacheControl.xml
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<chapter id="Cache_NoCache_CacheControl">
<title>Resteasy Caching Features</title>
<para>
Resteasy provides numerous annotations and facilities to support HTTP caching semantics. Annotations to make setting Cache-Control
headers easier and both server-side and client-side in-memory caches are available.
</para>
<sect1 id="Cache_Annotation">
<title>@Cache and @NoCache Annotations</title>
<para>
Resteasy provides an extension to JAX-RS that allows you to automatically set Cache-Control headers on a successful
GET request. It can only be used on @GET annotated methods. A successful @GET request is any request
that returns 200 OK response.
</para>
<programlisting>
package org.jboss.resteasy.annotations.cache;
public @interface Cache
{
int maxAge() default -1;
int sMaxAge() default -1;
boolean noStore() default false;
boolean noTransform() default false;
boolean mustRevalidate() default false;
boolean proxyRevalidate() default false;
boolean isPrivate() default false;
}
public @interface NoCache
{
String[] fields() default {};
}
</programlisting>
<para>
While @Cache builds a complex Cache-Control header, @NoCache is a simplified notation to say that you don't
want anything cached i.e. Cache-Control: nocache.
</para>
<para>
These annotations can be put on the resource class or interface and specifies a default cache value for each
@GET resource method. Or they can be put individually on each @GET resource method.
</para>
</sect1>
<sect1 id="client_cache">
<title>Client "Browser" Cache</title>
<para>
Resteasy has the ability to set up a client-side, browser-like, cache. You can use it with the Client Proxy Framework, or with raw
ClientRequests. This cache looks for Cache-Control headers sent back with a server response. If the Cache-Control headers specify
that the client is allowed to cache the response, Resteasy caches it within local memory. The cache obeys max-age requirements
and will also automatically do HTTP 1.1 cache revalidation if either or both the Last-Modified and/or ETag headers are sent back with the
original response. See the HTTP 1.1 specification for details on how Cache-Control or cache revalidation works.
</para>
<para>It is very simple to enable caching. Here's an example of using the client cache with the Client Proxy Framework</para>
<programlisting>
@Path("/orders")
public interface OrderServiceClient {
@Path("{id}")
@GET
@Produces("application/xml")
public Order getOrder(@PathParam("id") String id);
}
</programlisting>
<para>To create a proxy for this interface and enable caching for that proxy requires only a few simple steps:</para>
<programlisting>
import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.client.cache.CacheFactory;
import org.jboss.resteasy.client.cache.LightweightBrowserCache;
public static void main(String[] args) throws Exception
{
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
OrderServiceClient proxy = ProxyFactory.create(OrderServiceClient.class, generateBaseUrl());
// This line enables caching
LightweightBrowserCache cache = CacheFactory.makeCacheable(proxy);
}
</programlisting>
<para>If you are using the ClientRequest class to make invocations rather than the proxy framework, it is just as easy</para>
<programlisting>
import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.client.cache.CacheFactory;
import org.jboss.resteasy.client.cache.LightweightBrowserCache;
public static void main(String[] args) throws Exception
{
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
// This line enables caching
LightweightBrowserCache cache = new LightweightBrowserCache();
ClientRequest request = new ClientRequest("http://example.com/orders/333");
CacheFactory.makeCacheable(request, cache);
}
</programlisting>
<para>The LightweightBrowserCache, by default, has a maximum 2 megabytes of caching space. You can change this programmatically by callings
its setMaxBytes() method. If the cache gets full, the cache completely wipes itself of all cached data. This may seem
a bit draconian, but the cache was written to avoid unnecessary synchronizations in a concurrent environment where the cache is
shared between multiple threads. If you desire a more complex caching solution or if you want to plug in a thirdparty cache
please contact our resteasy-developers list and discuss it with the community.
</para>
</sect1>
<sect1 id="server_cache">
<title>Local Server-Side Response Cache</title>
<para>Resteasy has a server-side, local, in-memory cache that can sit in front of your JAX-RS services.
It automatically caches marshalled responses from HTTP GET JAX-RS invocations if, and only if your
JAX-RS resource method sets a Cache-Control header. When a GET comes in, the Resteasy Server Cache checks
to see if the URI is stored in the cache. If it does, it returns the already marshalled response without
invoking your JAX-RS method. Each cache entry has a max age to whatever is specified in the Cache-Control
header of the initial request. The cache also will automatically generate an ETag using an MD5 hash on the
response body. This allows the client to do HTTP 1.1 cache revalidation with the IF-NONE-MATCH header.
The cache is also smart enough to perform revalidation if there is no initial cache hit, but the jax-rs
method still returns a body that has the same ETag.
</para>
<para>
Starting in Resteasy 2.3, the cache is also automatically invalidated for a particular URI that has
PUT, POST, or DELETE invoked on it. You can also obtain a reference to the cache by injecting a
org.jboss.resteasy.plugins.cache.ServerCache
via the @Context annotation
</para>
<programlisting>
@Context
ServerCache cache;
@GET
public String get(@Context ServerCache cache) {...}
</programlisting>
<para>To set up the server-side cache, there are a few simple steps you have to perform. If you are using Maven you must depend on the resteasy-cache-core artifact:</para>
<programlisting>
<![CDATA[
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-cache-core</artifactId>
<version>2.3-RC1</version>
</dependency>
]]>
</programlisting>
<para>The next thing you have to do is to add a ServletContextListener, org.jboss.resteasy.plugins.cache.server.ServletServerCache.
This must be specified after the ResteasyBootstrap listener in your web.xml file.</para>
<programlisting>
<![CDATA[
<web-app>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<context-param>
<param-name>resteasy.server.cache.maxsize</param-name>
<param-value>1000</param-value>
</context-param>
<context-param>
<param-name>resteasy.server.cache.eviction.wakeup.interval</param-name>
<param-value>5000</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.cache.server.ServletServerCache
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/rest-services/*</url-pattern>
</servlet-mapping>
</web-app>
]]>
</programlisting>
<para>The cache implementation is based on the JBoss Cache project: http://jboss.org/jbosscache. There are two context-param configuration variables
that you can set. resteasy.server.cache.maxsize sets the number of elements that can be cached. The resteasy.server.cache.eviction.wakeup.interval sets the rate at which the background eviction thread runs to purge the cache of stale entries.
</para>
</sect1>
</chapter>