package org.infinispan.it.compatibility;
import static org.testng.AssertJUnit.assertArrayEquals;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.infinispan.client.hotrod.Flag;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.test.AbstractInfinispanTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Test compatibility between embedded caches, Hot Rod, and REST endpoints.
*
* @author Galder ZamarreƱo
* @since 5.3
*/
@Test(groups = "functional", testName = "it.compatibility.EmbeddedRestHotRodTest")
public class EmbeddedRestHotRodTest extends AbstractInfinispanTest {
private static final DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
CompatibilityCacheFactory<String, Object> cacheFactory;
@BeforeClass
protected void setup() throws Exception {
cacheFactory = new CompatibilityCacheFactory<String, Object>(CacheMode.LOCAL).setup();
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
}
@AfterClass
protected void teardown() {
CompatibilityCacheFactory.killCacheFactories(cacheFactory);
}
public void testRestPutEmbeddedHotRodGet() throws Exception {
final String key = "1";
// 1. Put with REST
EntityEnclosingMethod put = new PutMethod(cacheFactory.getRestUrl() + "/" + key);
put.setRequestEntity(new ByteArrayRequestEntity(
"<hey>ho</hey>".getBytes(), "application/octet-stream"));
HttpClient restClient = cacheFactory.getRestClient();
restClient.executeMethod(put);
assertEquals(HttpStatus.SC_OK, put.getStatusCode());
assertEquals("", put.getResponseBodyAsString().trim());
// 2. Get with Embedded
assertArrayEquals("<hey>ho</hey>".getBytes(), (byte[])
cacheFactory.getEmbeddedCache().get(key));
// 3. Get with Hot Rod
assertArrayEquals("<hey>ho</hey>".getBytes(), (byte[])
cacheFactory.getHotRodCache().get(key));
}
public void testEmbeddedPutRestHotRodGet() throws Exception {
final String key = "2";
// 1. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key, "v1"));
// 2. Get with Hot Rod
assertEquals("v1", cacheFactory.getHotRodCache().get(key));
// 3. Get with REST
HttpMethod get = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
cacheFactory.getRestClient().executeMethod(get);
assertEquals(HttpStatus.SC_OK, get.getStatusCode());
assertEquals("v1", get.getResponseBodyAsString());
}
public void testHotRodPutEmbeddedRestGet() throws Exception {
final String key = "3";
// 1. Put with Hot Rod
RemoteCache<String, Object> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
// 2. Get with Embedded
assertEquals("v1", cacheFactory.getEmbeddedCache().get(key));
// 3. Get with REST
HttpMethod get = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
cacheFactory.getRestClient().executeMethod(get);
assertEquals(HttpStatus.SC_OK, get.getStatusCode());
assertEquals("v1", get.getResponseBodyAsString());
}
public void testCustomObjectHotRodPutEmbeddedRestGet() throws Exception{
final String key = "4";
Person p = new Person("Martin");
// 1. Put with Hot Rod
RemoteCache<String, Object> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, p));
// 2. Get with Embedded
assertEquals(p, cacheFactory.getEmbeddedCache().get(key));
// 3. Get with REST
HttpMethod get = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
get.setRequestHeader("Accept", "application/x-java-serialized-object");
cacheFactory.getRestClient().executeMethod(get);
assertEquals(get.getStatusText(), HttpStatus.SC_OK, get.getStatusCode());
// REST finds the Java POJO in-memory and returns the Java serialized version
assertEquals(p, new ObjectInputStream(get.getResponseBodyAsStream()).readObject());
}
public void testCustomObjectEmbeddedPutHotRodRestGet() throws Exception{
final String key = "5";
Person p = new Person("Galder");
// 1. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key, p));
// 2. Get with Hot Rod
assertEquals(p, cacheFactory.getHotRodCache().get(key));
// 3. Get with REST
HttpMethod get = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
get.setRequestHeader("Accept", "application/x-java-serialized-object, application/json;q=0.3");
cacheFactory.getRestClient().executeMethod(get);
assertEquals("application/x-java-serialized-object", get.getResponseHeader("Content-Type").getValue());
assertEquals(get.getStatusText(), HttpStatus.SC_OK, get.getStatusCode());
// REST finds the Java POJO in-memory and returns the Java serialized version
assertEquals(p, new ObjectInputStream(get.getResponseBodyAsStream()).readObject());
}
public void testCustomObjectEmbeddedPutRestGetAcceptJSONAndXML() throws Exception{
final String key = "6";
final Person p = new Person("Anna");
// 1. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key, p));
// 2. Get with REST (accept application/json)
HttpMethod getJson = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
getJson.setRequestHeader("Accept", "application/json");
cacheFactory.getRestClient().executeMethod(getJson);
assertEquals(getJson.getStatusText(), HttpStatus.SC_OK, getJson.getStatusCode());
assertEquals("{\"name\":\"Anna\"}", getJson.getResponseBodyAsString());
// 3. Get with REST (accept application/xml)
HttpMethod getXml = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
getXml.setRequestHeader("Accept", "application/xml");
cacheFactory.getRestClient().executeMethod(getXml);
assertEquals(getXml.getStatusText(), HttpStatus.SC_OK, getXml.getStatusCode());
assertTrue(getXml.getResponseBodyAsString().contains("<name>Anna</name>"));
}
public void testCustomObjectHotRodPutRestGetAcceptJSONAndXML() throws Exception{
final String key = "7";
final Person p = new Person("Jakub");
// 1. Put with HotRod
RemoteCache<String, Object> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, p));
// 2. Get with REST (accept application/json)
HttpMethod getJson = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
getJson.setRequestHeader("Accept", "application/json");
cacheFactory.getRestClient().executeMethod(getJson);
assertEquals(getJson.getStatusText(), HttpStatus.SC_OK, getJson.getStatusCode());
assertEquals("{\"name\":\"Jakub\"}", getJson.getResponseBodyAsString());
// 3. Get with REST (accept application/xml)
HttpMethod getXml = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
getXml.setRequestHeader("Accept", "application/xml");
cacheFactory.getRestClient().executeMethod(getXml);
assertEquals(getXml.getStatusText(), HttpStatus.SC_OK, getXml.getStatusCode());
assertTrue(getXml.getResponseBodyAsString().contains("<name>Jakub</name>"));
}
public void testCustomObjectRestPutHotRodEmbeddedGet() throws Exception{
final String key = "77";
Person p = new Person("Iker");
// 1. Put with Rest
EntityEnclosingMethod put = new PutMethod(cacheFactory.getRestUrl() + "/" + key);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bout)) {
oos.writeObject(p);
}
put.setRequestHeader("Content-Type", "application/x-java-serialized-object");
put.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(bout.toByteArray())));
cacheFactory.getRestClient().executeMethod(put);
// 2. Get with Hot Rod
RemoteCache<String, Object> remote = cacheFactory.getHotRodCache();
assertEquals(p, remote.get(key));
// 3. Get with Embedded
assertEquals(p, cacheFactory.getEmbeddedCache().get(key));
}
public void testHotRodEmbeddedPutRestHeadExpiry() throws Exception {
final String key1 = "8";
final String key2 = "9";
// 1. Put with HotRod
assertEquals(null, cacheFactory.getHotRodCache().put(key1, "v1", 5, TimeUnit.SECONDS));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2", 5, TimeUnit.SECONDS));
// 3. HEAD with REST key1
HttpMethod headKey1 = new HeadMethod(cacheFactory.getRestUrl() + "/" + key1);
cacheFactory.getRestClient().executeMethod(headKey1);
assertEquals(HttpStatus.SC_OK, headKey1.getStatusCode());
Header expires = headKey1.getResponseHeader("Expires");
assertNotNull(expires);
assertTrue(dateFormat.parse(expires.getValue()).after(new GregorianCalendar(2013, 1, 1).getTime()));
// 4. HEAD with REST key2
HttpMethod headKey2 = new HeadMethod(cacheFactory.getRestUrl() + "/" + key2);
cacheFactory.getRestClient().executeMethod(headKey2);
assertEquals(HttpStatus.SC_OK, headKey2.getStatusCode());
assertNotNull(headKey2.getResponseHeader("Expires"));
}
public void testHotRodEmbeddedPutRestGetExpiry() throws Exception {
final String key = "10";
final String key2 = "11";
// 1. Put with HotRod
assertEquals(null, cacheFactory.getHotRodCache().put(key, "v1", 5, TimeUnit.SECONDS));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2", 5, TimeUnit.SECONDS));
// 3. Get with REST key
HttpMethod get1 = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
cacheFactory.getRestClient().executeMethod(get1);
assertEquals(HttpStatus.SC_OK, get1.getStatusCode());
assertDate(get1, "Expires");
// 4. Get with REST key2
HttpMethod get2 = new GetMethod(cacheFactory.getRestUrl() + "/" + key2);
cacheFactory.getRestClient().executeMethod(get2);
assertEquals(HttpStatus.SC_OK, get2.getStatusCode());
assertDate(get2, "Expires");
}
public void testHotRodEmbeddedPutRestGetLastModified() throws Exception {
final String key = "12";
final String key2 = "13";
// 1. Put with HotRod
assertEquals(null, cacheFactory.getHotRodCache().put(key, "v1", 5, TimeUnit.SECONDS));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2", 5, TimeUnit.SECONDS));
// 3. Get with REST key
HttpMethod get1 = new GetMethod(cacheFactory.getRestUrl() + "/" + key);
cacheFactory.getRestClient().executeMethod(get1);
assertEquals(HttpStatus.SC_OK, get1.getStatusCode());
assertDate(get1, "Last-Modified");
// 4. Get with REST key2
HttpMethod get2 = new GetMethod(cacheFactory.getRestUrl() + "/" + key2);
cacheFactory.getRestClient().executeMethod(get2);
assertEquals(HttpStatus.SC_OK, get2.getStatusCode());
assertDate(get2, "Last-Modified");
}
private static void assertDate(HttpMethod method, String header) throws Exception {
Header dateHeader = method.getResponseHeader(header);
assertNotNull(dateHeader);
Date parsedDate = dateFormat.parse(dateHeader.getValue());
assertTrue("Parsed date is before this code was written: " + parsedDate,
parsedDate.after(new GregorianCalendar(2013, 1, 1).getTime()));
}
public void testByteArrayHotRodEmbeddedPutRestGet() throws Exception{
final String key1 = "14";
final String key2 = "15";
// 1. Put with Hot Rod
RemoteCache<String, Object> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key1, "v1".getBytes()));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2".getBytes()));
// 3. Get with REST key1
HttpMethod getHotRodValue = new GetMethod(cacheFactory.getRestUrl() + "/" + key1);
cacheFactory.getRestClient().executeMethod(getHotRodValue);
assertEquals(getHotRodValue.getStatusText(), HttpStatus.SC_OK, getHotRodValue.getStatusCode());
assertEquals("application/octet-stream", getHotRodValue.getResponseHeader("Content-Type").getValue());
assertArrayEquals("v1".getBytes(), getHotRodValue.getResponseBody());
// 4. Get with REST key2
HttpMethod getEmbeddedValue = new GetMethod(cacheFactory.getRestUrl() + "/" + key2);
cacheFactory.getRestClient().executeMethod(getEmbeddedValue);
assertEquals(getEmbeddedValue.getStatusText(), HttpStatus.SC_OK, getEmbeddedValue.getStatusCode());
assertEquals("application/octet-stream", getEmbeddedValue.getResponseHeader("Content-Type").getValue());
assertArrayEquals("v2".getBytes(), getEmbeddedValue.getResponseBody());
}
public void testHotRodEmbeddedPutRestGetWrongAccept() throws Exception {
final String key1 = "16";
final String key2 = "17";
// 1. Put with HotRod
assertEquals(null, cacheFactory.getHotRodCache().put(key1, "v1"));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2"));
// 3. GET with REST key1
HttpMethod getKey1 = new HeadMethod(cacheFactory.getRestUrl() + "/" + key1);
getKey1.setRequestHeader("Accept", "unknown-media-type");
cacheFactory.getRestClient().executeMethod(getKey1);
assertEquals(getKey1.getStatusText(), HttpStatus.SC_BAD_REQUEST, getKey1.getStatusCode());
// 4. GET with REST key2
HttpMethod getKey2 = new HeadMethod(cacheFactory.getRestUrl() + "/" + key2);
getKey2.setRequestHeader("Accept", "unknown-media-type");
cacheFactory.getRestClient().executeMethod(getKey2);
assertEquals(getKey2.getStatusText(), HttpStatus.SC_BAD_REQUEST, getKey2.getStatusCode());
}
public void testHotRodEmbeddedPutRestGetCacheControlHeader() throws Exception {
final String key1 = "18";
final String key2 = "19";
// 1. Put with HotRod
assertEquals(null, cacheFactory.getHotRodCache().put(key1, "v1", 7, TimeUnit.SECONDS));
// 2. Put with Embedded
assertEquals(null, cacheFactory.getEmbeddedCache().put(key2, "v2", 7, TimeUnit.SECONDS));
// 3. GET with REST key1, long min-fresh
HttpMethod getKey1 = new GetMethod(cacheFactory.getRestUrl() + "/" + key1);
getKey1.setRequestHeader("Cache-Control", "min-fresh=20");
cacheFactory.getRestClient().executeMethod(getKey1);
assertEquals(getKey1.getStatusText(), HttpStatus.SC_NOT_FOUND, getKey1.getStatusCode());
// 4. GET with REST key2, long min-fresh
HttpMethod getKey2 = new GetMethod(cacheFactory.getRestUrl() + "/" + key2);
getKey2.setRequestHeader("Cache-Control", "min-fresh=20");
cacheFactory.getRestClient().executeMethod(getKey2);
assertEquals(getKey2.getStatusText(), HttpStatus.SC_NOT_FOUND, getKey2.getStatusCode());
// 5. GET with REST key1, short min-fresh
getKey1 = new GetMethod(cacheFactory.getRestUrl() + "/" + key1);
getKey1.setRequestHeader("Cache-Control", "min-fresh=3");
cacheFactory.getRestClient().executeMethod(getKey1);
assertNotNull(getKey1.getResponseHeader("Cache-Control"));
assertTrue(getKey1.getResponseHeader("Cache-Control").getValue().contains("max-age"));
assertEquals(getKey1.getStatusText(), HttpStatus.SC_OK, getKey1.getStatusCode());
assertEquals("v1", getKey1.getResponseBodyAsString());
// 6. GET with REST key2, short min-fresh
getKey2 = new GetMethod(cacheFactory.getRestUrl() + "/" + key2);
getKey2.setRequestHeader("Cache-Control", "min-fresh=3");
cacheFactory.getRestClient().executeMethod(getKey2);
assertTrue(getKey2.getResponseHeader("Cache-Control").getValue().contains("max-age"));
assertEquals(getKey2.getStatusText(), HttpStatus.SC_OK, getKey2.getStatusCode());
assertEquals("v2", getKey2.getResponseBodyAsString());
}
/**
* The class needs a getter for the attribute "name" so that it can be converted to JSON format
* internally by the REST server.
*/
static class Person implements Serializable {
final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (!name.equals(person.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
}
}