| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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. |
| */ |
| package org.apache.cxf.jaxrs.client.cache; |
| |
| |
| import java.io.InputStream; |
| import java.io.Serializable; |
| import java.util.Collections; |
| |
| import javax.ws.rs.GET; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.client.ClientBuilder; |
| import javax.ws.rs.client.Invocation; |
| import javax.ws.rs.client.WebTarget; |
| import javax.ws.rs.core.CacheControl; |
| import javax.ws.rs.core.HttpHeaders; |
| import javax.ws.rs.core.Response; |
| import javax.xml.bind.annotation.XmlRootElement; |
| |
| import org.apache.cxf.Bus; |
| import org.apache.cxf.BusFactory; |
| import org.apache.cxf.endpoint.Server; |
| import org.apache.cxf.helpers.IOUtils; |
| import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; |
| import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; |
| import org.apache.cxf.jaxrs.client.WebClient; |
| import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; |
| import org.apache.cxf.transport.local.LocalConduit; |
| import org.apache.cxf.transport.local.LocalTransportFactory; |
| |
| import org.junit.AfterClass; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| |
| public class ClientCacheTest { |
| public static final String ADDRESS = "local://transport"; |
| private static Server server; |
| |
| @BeforeClass |
| public static void bind() throws Exception { |
| final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); |
| sf.setResourceClasses(TheServer.class); |
| sf.setResourceProvider(TheServer.class, new SingletonResourceProvider(new TheServer(), false)); |
| sf.setTransportId(LocalTransportFactory.TRANSPORT_ID); |
| sf.setAddress(ADDRESS); |
| server = sf.create(); |
| } |
| |
| @AfterClass |
| public static void unbind() throws Exception { |
| server.stop(); |
| server.destroy(); |
| } |
| |
| @Test |
| public void testGetTimeString() { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| final WebTarget base = ClientBuilder.newBuilder().register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = base.request("text/plain").header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final String r1 = r.readEntity(String.class); |
| waitABit(); |
| assertEquals(r1, cached.get().readEntity(String.class)); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| @Test |
| public void testGetTimeStringUsingClientFactory() { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); |
| bean.setAddress(ADDRESS); |
| bean.setProviders(Collections.singletonList(feature)); |
| bean.setTransportId(LocalTransportFactory.TRANSPORT_ID); |
| |
| final WebClient cached = bean.createWebClient() |
| .accept("text/plain") |
| .header(HttpHeaders.CACHE_CONTROL, "public"); |
| |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final String r1 = r.readEntity(String.class); |
| waitABit(); |
| assertEquals(r1, cached.get().readEntity(String.class)); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| @Test |
| public void testGetTimeStringAsInputStream() throws Exception { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| final WebTarget base = ClientBuilder.newBuilder().register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = base.request("text/plain").header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| InputStream is = r.readEntity(InputStream.class); |
| final String r1 = IOUtils.readStringFromStream(is); |
| waitABit(); |
| is = cached.get().readEntity(InputStream.class); |
| final String r2 = IOUtils.readStringFromStream(is); |
| assertEquals(r1, r2); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| @Test |
| public void testGetTimeStringAsInputStreamAndString() throws Exception { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| feature.setCacheResponseInputStream(true); |
| final WebTarget base = ClientBuilder.newBuilder().register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = base.request("text/plain").header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| InputStream is = r.readEntity(InputStream.class); |
| final String r1 = IOUtils.readStringFromStream(is); |
| waitABit(); |
| // CassCastException would occur without a cached stream support |
| final String r2 = cached.get().readEntity(String.class); |
| assertEquals(r1, r2); |
| } finally { |
| feature.close(); |
| } |
| } |
| @Test |
| public void testGetTimeStringAsStringAndInputStream() throws Exception { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| feature.setCacheResponseInputStream(true); |
| final WebTarget base = ClientBuilder.newBuilder().register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = base.request("text/plain").header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final String r1 = r.readEntity(String.class); |
| waitABit(); |
| // CassCastException would occur without a cached stream support |
| InputStream is = cached.get().readEntity(InputStream.class); |
| final String r2 = IOUtils.readStringFromStream(is); |
| assertEquals(r1, r2); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| @Test |
| public void testGetTimeStringAsStringAndInputStreamWithJAXRSClientFactoryBean() throws Exception { |
| CXFCacheControlFeature feature = new CXFCacheControlFeature(true); |
| try { |
| WebClient client = createClient(feature); |
| final Response r = client.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final String r1 = r.readEntity(String.class); |
| waitABit(); |
| InputStream is = client.get(InputStream.class); |
| final String r2 = IOUtils.readStringFromStream(is); |
| assertEquals(r1, r2); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| @Test |
| public void testGetJaxbBookCache() { |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| final WebTarget base = ClientBuilder.newBuilder().register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = |
| setAsLocal(base.request("application/xml")).header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final Book b1 = r.readEntity(Book.class); |
| assertEquals("JCache", b1.getName()); |
| assertNotNull(b1.getId()); |
| waitABit(); |
| assertEquals(b1, cached.get().readEntity(Book.class)); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| |
| @Test |
| public void testGetJaxbBookCacheByValue() { |
| // org.apache.cxf.jaxrs.client.cache.CacheControlFeature.storeByValue |
| CacheControlFeature feature = new CacheControlFeature(); |
| try { |
| final WebTarget base = ClientBuilder.newBuilder() |
| .property("org.apache.cxf.jaxrs.client.cache.CacheControlFeature.storeByValue", "true") |
| .register(feature).build().target(ADDRESS); |
| final Invocation.Builder cached = |
| setAsLocal(base.request("application/xml")).header(HttpHeaders.CACHE_CONTROL, "public"); |
| final Response r = cached.get(); |
| assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); |
| final Book b1 = r.readEntity(Book.class); |
| assertEquals("JCache", b1.getName()); |
| assertNotNull(b1.getId()); |
| waitABit(); |
| assertEquals(b1, cached.get().readEntity(Book.class)); |
| } finally { |
| feature.close(); |
| } |
| } |
| |
| private static Invocation.Builder setAsLocal(final Invocation.Builder client) { |
| WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE); |
| return client; |
| } |
| |
| private static void waitABit() { |
| try { // just to be sure |
| Thread.sleep(150); |
| } catch (final InterruptedException e) { |
| Thread.interrupted(); |
| } |
| } |
| |
| @Path("/") |
| public static class TheServer { |
| @GET |
| @Produces("text/plain") |
| public Response getString() { |
| return Response.ok(Long.toString(System.currentTimeMillis())) |
| .tag("123").cacheControl(CacheControl.valueOf("max-age=50000")).build(); |
| } |
| @GET |
| @Produces("application/xml") |
| public Response getJaxbBook() { |
| Book b = new Book(); |
| b.setId(System.currentTimeMillis()); |
| b.setName("JCache"); |
| return Response.ok(b).tag("123").cacheControl(CacheControl.valueOf("max-age=50000")).build(); |
| } |
| } |
| @XmlRootElement |
| public static class Book implements Serializable { |
| private static final long serialVersionUID = 4924824780883333782L; |
| private String name; |
| private Long id; |
| public Book() { |
| |
| } |
| public Book(String name, long id) { |
| this.name = name; |
| this.id = id; |
| } |
| public String getName() { |
| return name; |
| } |
| public void setName(String name) { |
| this.name = name; |
| } |
| public Long getId() { |
| return id; |
| } |
| public void setId(Long id) { |
| this.id = id; |
| } |
| public int hashCode() { |
| return id.hashCode() + 37 * name.hashCode(); |
| } |
| public boolean equals(Object o) { |
| if (o instanceof Book) { |
| Book other = (Book)o; |
| return other.id.equals(id) && other.name.equals(name); |
| } |
| return false; |
| } |
| } |
| |
| private WebClient createClient(CXFCacheControlFeature feature) { |
| Bus bus = BusFactory.newInstance().createBus(); |
| JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); |
| sf.setBus(bus); |
| sf.setResourceClasses(TheServer.class); |
| sf.setResourceProvider(TheServer.class, new SingletonResourceProvider(new TheServer(), false)); |
| sf.setTransportId(LocalTransportFactory.TRANSPORT_ID); |
| sf.setAddress(ADDRESS); |
| sf.create(); |
| JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); |
| bean.setBus(bus); |
| bean.setAddress(ADDRESS); |
| bean.setFeatures(Collections.singletonList(feature)); |
| bean.setTransportId(LocalTransportFactory.TRANSPORT_ID); |
| return bean.createWebClient().accept("text/plain").header(HttpHeaders.CACHE_CONTROL, "public"); |
| } |
| |
| } |