DeserConcurrencyTest.java
package tools.jackson.databind.deser;
import org.junit.jupiter.api.Test;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.*;
import tools.jackson.databind.annotation.JsonDeserialize;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Testing for a NPE due to race condition
*/
public class DeserConcurrencyTest
{
@JsonDeserialize(using=TestBeanDeserializer.class)
static class Bean
{
public int value = 42;
}
/*
/**********************************************************************
/* Helper classes
/**********************************************************************
*/
/**
* Dummy deserializer used for verifying that partially handled (i.e. not yet
* resolved) deserializers are not allowed to be used.
*/
static class TestBeanDeserializer
extends ValueDeserializer<Bean>
{
protected volatile boolean resolved = false;
@Override
public Bean deserialize(JsonParser p, DeserializationContext ctxt)
{
if (!resolved) {
ctxt.reportInputMismatch(Bean.class,
"Deserializer not yet completely resolved");
}
p.skipChildren(); // consume the value
Bean b = new Bean();
b.value = 13;
return b;
}
@Override
public void resolve(DeserializationContext ctxt)
{
try {
Thread.sleep(100L);
} catch (Exception e) { }
resolved = true;
}
}
/*
/**********************************************************************
/* Test methods
/**********************************************************************
*/
@Test
public void testDeserializerResolution() throws Exception
{
// Let's repeat couple of times, just to be sure; thread timing is not
// exact science; plus caching plays a role too
final String JSON = "{\"value\":42}";
for (int i = 0; i < 5; ++i) {
final ObjectMapper mapper = new ObjectMapper();
Runnable r = new Runnable() {
@Override
public void run() {
try {
/*Bean b =*/ mapper.readValue(JSON, Bean.class);
} catch (Exception e) { }
}
};
Thread t = new Thread(r);
t.start();
// then let it proceed
Thread.sleep(10L);
// and try the same...
Bean b = mapper.readValue(JSON, Bean.class);
// note: funny deserializer, mangles data.. :)
assertEquals(13, b.value);
t.join();
}
}
}