Add Scheduler.testSerialization, some new JsonDeserializer in RedisScheduler, and a bunch of tests to test (de)serialization
This commit is contained in:
parent
f690ef92cc
commit
2e22c95dd0
@ -38,6 +38,10 @@ public class ScheduledItem<T> implements Runnable {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public ScheduledItem(T dto) {
|
||||
this(null, dto);
|
||||
}
|
||||
|
||||
public ScheduledItem(Class<? extends BackgroundJob<T>> bgClass, T dto) {
|
||||
this.bgClass = bgClass;
|
||||
this.dto = dto;
|
||||
@ -72,6 +76,10 @@ public class ScheduledItem<T> implements Runnable {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public T getDto() {
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ScheduledItem{" +
|
||||
|
@ -49,4 +49,13 @@ public interface Scheduler extends Closeable {
|
||||
public <T> boolean schedule(final String queue, final Class<? extends BackgroundJob<T>> bgClass, final T dto);
|
||||
|
||||
public <T> boolean schedule(final String queue, final ScheduledItem<T> scheduledItem);
|
||||
|
||||
/**
|
||||
* This serializes and deserialized T and returns the deserialized version for the calling app to compare is correct
|
||||
* @param t to be serialized
|
||||
* @param <T> Type of DTO
|
||||
* @return t serialized and deserialized
|
||||
* @throws Exception
|
||||
*/
|
||||
public <T> T testSerialization(final T t) throws Exception;
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class AbstractSchedulerTests {
|
||||
public static Scheduler bg;
|
||||
|
||||
@ -61,4 +64,24 @@ public class AbstractSchedulerTests {
|
||||
for (; x < 20; ++x)
|
||||
Assert.assertTrue(bg.schedule(PrintingJob.class, new PrintDTO("fastJob " + x)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationSingleton() throws Throwable {
|
||||
Assert.assertEquals(Collections.singleton(5), bg.testSerialization(Collections.singleton(5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationSingletonMap() throws Throwable {
|
||||
Assert.assertEquals(Collections.singletonMap("5", 5), bg.testSerialization(Collections.singletonMap("5", 5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationSingletonList() throws Throwable {
|
||||
Assert.assertEquals(Collections.singletonList(5), bg.testSerialization(Collections.singletonList(5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationAsList() throws Throwable {
|
||||
Assert.assertEquals(Arrays.asList(2, 3, 4, 5), bg.testSerialization(Arrays.asList(2, 3, 4, 5)));
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,16 @@
|
||||
|
||||
package com.moparisthebest.jbgjob;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This implementation of Scheduler that serializes the DTO into a redis list for processing elsewhere.
|
||||
*/
|
||||
@ -34,6 +39,8 @@ public class RedisScheduler extends AbstractScheduler {
|
||||
|
||||
public static final String defaultQueuePrefix;
|
||||
|
||||
public static final Module redisModule;
|
||||
|
||||
static {
|
||||
String prefix = System.getProperty("redis.queuePrefix");
|
||||
if (isEmpty(prefix))
|
||||
@ -42,11 +49,47 @@ public class RedisScheduler extends AbstractScheduler {
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
defaultQueuePrefix = defaultIfEmpty(prefix, "");
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final Class<Set> singleton = (Class<Set>) Collections.singleton(5L).getClass();
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final Class<Map> singletonMap = (Class<Map>) Collections.singletonMap(5L, 5L).getClass();
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final Class<List> singletonList = (Class<List>) Collections.singletonList(5L).getClass();
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final Class<List> asList = (Class<List>) Arrays.asList(5L).getClass();
|
||||
|
||||
redisModule = new SimpleModule("OrderedMap", new Version(1, 0, 0, null, null, null)).addDeserializer(
|
||||
singleton, new JsonDeserializer<Set>() {
|
||||
@Override
|
||||
public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
return Collections.singleton(jp.getCodec().readValue(jp, Object[].class)[0]);
|
||||
}
|
||||
}).addDeserializer(
|
||||
singletonMap, new JsonDeserializer<Map>() {
|
||||
@Override
|
||||
public Map deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
final Map.Entry entry = (Map.Entry) jp.getCodec().readValue(jp, HashMap.class).entrySet().iterator().next();
|
||||
return Collections.singletonMap(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}).addDeserializer(
|
||||
singletonList, new JsonDeserializer<List>() {
|
||||
@Override
|
||||
public List deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
return Collections.singletonList(jp.getCodec().readValue(jp, Object[].class)[0]);
|
||||
}
|
||||
}).addDeserializer(
|
||||
asList, new JsonDeserializer<List>() {
|
||||
@Override
|
||||
public List deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
return Arrays.asList(jp.getCodec().readValue(jp, Object[].class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected final String queuePrefix;
|
||||
|
||||
protected final ObjectMapper om = new ObjectMapper().enableDefaultTyping();
|
||||
protected final ObjectMapper om = new ObjectMapper().enableDefaultTyping().registerModule(redisModule);
|
||||
protected final JedisPool pool;
|
||||
|
||||
public RedisScheduler() {
|
||||
@ -87,4 +130,21 @@ public class RedisScheduler extends AbstractScheduler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T testSerialization(final T t) throws IOException {
|
||||
final String singleton = om.writeValueAsString(new ScheduledItem<T>(null, t));
|
||||
System.out.printf("singleton: '%s', dto.getClass: '%s'", singleton, t.getClass());
|
||||
final ScheduledItem<T> singletonCol = (ScheduledItem<T>) om.readValue(singleton, ScheduledItem.class);
|
||||
System.out.printf(", singletonCol: '%s', dto.getClass: '%s'", singletonCol, singletonCol.getDto().getClass());
|
||||
if (singletonCol.getDto() instanceof Collection)
|
||||
for (Object ob : ((Collection) singletonCol.getDto()))
|
||||
System.out.printf(", val: '%s', val.getClass: '%s'", ob, ob.getClass());
|
||||
else if (singletonCol.getDto() instanceof Map)
|
||||
for (Map.Entry entry : (Set<Map.Entry>) ((Map) singletonCol.getDto()).entrySet())
|
||||
System.out.printf(", key: '%s', key.getClass: '%s', val: '%s', val.getClass: '%s'", entry.getKey(), entry.getKey().getClass(), entry.getValue(), entry.getValue().getClass());
|
||||
System.out.println();
|
||||
return singletonCol.getDto();
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,11 @@ public class ThreadScheduler extends AbstractScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T testSerialization(final T t) {
|
||||
return t; // do nothing here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
|
Loading…
Reference in New Issue
Block a user