Description
Java API client version
8.4.1
Java version
Azul Zulu 17.0.1
Elasticsearch Version
8.4.1
Problem description
The JsonbDeserializerBase.ArrayDeserializer.acceptedEvents()
Method returns a lazily initialized Set of accepted Events which can be initialized only partially when called concurrently:
public EnumSet<Event> acceptedEvents() {
// Accepted events is computed lazily
// no need for double-checked lock, we don't care about computing it several times
if (acceptedEvents == null) {
acceptedEvents = EnumSet.of(Event.START_ARRAY);
acceptedEvents.addAll(itemDeserializer.acceptedEvents());
}
return acceptedEvents;
}
In our case, a concurrent caller called the methode between the execution of the statements acceptedEvents = EnumSet.of(Event.START_ARRAY);
and acceptedEvents.addAll(itemDeserializer.acceptedEvents());
, which led to a Set containing only the START_ARRAY
event and a very confusing Parsing error:
Error deserializing co.elastic.clients.elasticsearch._types.analysis.StandardAnalyzer: co.elastic.clients.json.UnexpectedJsonEventException: Unexpected JSON event 'VALUE_STRING' instead of '[START_ARRAY, KEY_NAME, VALUE_STRING, VALUE_NUMBER, VALUE_TRUE, VALUE_FALSE]'
Solution: the acceptedEvents
Set should be initialized completely before assigned to the acceptedEvents
field, to avoid the returning of partially initialized sets in concurrent method calls:
if (acceptedEvents == null) {
EnumSet<Event> events = EnumSet.of(Event.START_ARRAY);
events.addAll(itemDeserializer.acceptedEvents());
acceptedEvents = events;
}