@@ -82,7 +82,8 @@ public class MappingElasticsearchConverter
8282 private final MappingContext <? extends ElasticsearchPersistentEntity <?>, ElasticsearchPersistentProperty > mappingContext ;
8383 private final GenericConversionService conversionService ;
8484
85- private CustomConversions conversions = new ElasticsearchCustomConversions (Collections .emptyList ());
85+ // don't access directly, use getConversions(). to prevent null access
86+ @ Nullable private CustomConversions conversions = null ;
8687 private final EntityInstantiators instantiators = new EntityInstantiators ();
8788
8889 private final ElasticsearchTypeMapper typeMapper ;
@@ -133,14 +134,22 @@ public void setConversions(CustomConversions conversions) {
133134 this .conversions = conversions ;
134135 }
135136
137+ private CustomConversions getConversions () {
138+
139+ if (conversions == null ) {
140+ conversions = new ElasticsearchCustomConversions (Collections .emptyList ());
141+ }
142+ return conversions ;
143+ }
144+
136145 /*
137146 * (non-Javadoc)
138147 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
139148 */
140149 @ Override
141150 public void afterPropertiesSet () {
142151 DateFormatterRegistrar .addDateConverters (conversionService );
143- conversions .registerConvertersIn (conversionService );
152+ getConversions () .registerConvertersIn (conversionService );
144153 }
145154
146155 // region read
@@ -151,7 +160,7 @@ public <R> R read(Class<R> type, Document source) {
151160 TypeInformation <R > typeHint = ClassTypeInformation .from ((Class <R >) ClassUtils .getUserClass (type ));
152161 typeHint = (TypeInformation <R >) typeMapper .readType (source , typeHint );
153162
154- if (conversions .hasCustomReadTarget (Map .class , typeHint .getType ())) {
163+ if (getConversions () .hasCustomReadTarget (Map .class , typeHint .getType ())) {
155164 R converted = conversionService .convert (source , typeHint .getType ());
156165 if (converted == null ) {
157166 // EntityReader.read is defined as non nullable , so we cannot return null
@@ -177,7 +186,7 @@ protected <R> R readEntity(ElasticsearchPersistentEntity<?> entity, Map<String,
177186
178187 EntityInstantiator instantiator = instantiators .getInstantiatorFor (targetEntity );
179188
180- @ SuppressWarnings ("unchecked" )
189+ @ SuppressWarnings ({ "unchecked" , "ConstantConditions" } )
181190 R instance = (R ) instantiator .createInstance (targetEntity ,
182191 new PersistentEntityParameterValueProvider <>(targetEntity , propertyValueProvider , null ));
183192
@@ -223,6 +232,7 @@ protected <R> R readEntity(ElasticsearchPersistentEntity<?> entity, Map<String,
223232 if (source instanceof SearchDocument ) {
224233 SearchDocument searchDocument = (SearchDocument ) source ;
225234 if (targetEntity .hasScoreProperty ()) {
235+ //noinspection ConstantConditions
226236 targetEntity .getPropertyAccessor (result ) //
227237 .setProperty (targetEntity .getScoreProperty (), searchDocument .getScore ());
228238 }
@@ -276,7 +286,7 @@ protected <R> R readValue(@Nullable Object source, ElasticsearchPersistentProper
276286 if (property .hasPropertyConverter ()) {
277287 source = propertyConverterRead (property , source );
278288 } else if (TemporalAccessor .class .isAssignableFrom (property .getType ())
279- && !conversions .hasCustomReadTarget (source .getClass (), rawType )) {
289+ && !getConversions () .hasCustomReadTarget (source .getClass (), rawType )) {
280290
281291 // log at most 5 times
282292 String propertyName = property .getOwner ().getType ().getSimpleName () + '.' + property .getName ();
@@ -291,7 +301,7 @@ protected <R> R readValue(@Nullable Object source, ElasticsearchPersistentProper
291301 }
292302 }
293303
294- if (conversions .hasCustomReadTarget (source .getClass (), rawType )) {
304+ if (getConversions () .hasCustomReadTarget (source .getClass (), rawType )) {
295305 return rawType .cast (conversionService .convert (source , rawType ));
296306 } else if (source instanceof List ) {
297307 return readCollectionValue ((List <?>) source , property , targetType );
@@ -356,8 +366,6 @@ && isSimpleType(componentType.getType())) {
356366 } else if (value instanceof Map ) {
357367 target
358368 .add (readMapValue ((Map <String , Object >) value , property , property .getTypeInformation ().getActualType ()));
359- } else {
360- target .add (readEntity (computeGenericValueTypeForRead (property , value ), (Map <String , Object >) value ));
361369 }
362370 }
363371 }
@@ -423,7 +431,7 @@ private Object readSimpleValue(@Nullable Object value, TypeInformation<?> target
423431 return value ;
424432 }
425433
426- if (conversions .hasCustomReadTarget (value .getClass (), target )) {
434+ if (getConversions () .hasCustomReadTarget (value .getClass (), target )) {
427435 return conversionService .convert (value , target );
428436 }
429437
@@ -477,7 +485,7 @@ public void write(Object source, Document sink) {
477485 typeMapper .writeType (source .getClass (), sink );
478486 }
479487
480- Optional <Class <?>> customTarget = conversions .getCustomWriteTarget (entityType , Map .class );
488+ Optional <Class <?>> customTarget = getConversions () .getCustomWriteTarget (entityType , Map .class );
481489
482490 if (customTarget .isPresent ()) {
483491 sink .putAll (conversionService .convert (source , Map .class ));
@@ -526,7 +534,7 @@ protected void writeProperties(ElasticsearchPersistentEntity<?> entity, Persiste
526534 if (property .hasPropertyConverter ()) {
527535 value = propertyConverterWrite (property , value );
528536 } else if (TemporalAccessor .class .isAssignableFrom (property .getActualType ())
529- && !conversions .hasCustomWriteTarget (value .getClass ())) {
537+ && !getConversions () .hasCustomWriteTarget (value .getClass ())) {
530538
531539 // log at most 5 times
532540 String propertyName = entity .getType ().getSimpleName () + '.' + property .getName ();
@@ -568,7 +576,7 @@ private Object propertyConverterWrite(ElasticsearchPersistentProperty property,
568576
569577 protected void writeProperty (ElasticsearchPersistentProperty property , Object value , MapValueAccessor sink ) {
570578
571- Optional <Class <?>> customWriteTarget = conversions .getCustomWriteTarget (value .getClass ());
579+ Optional <Class <?>> customWriteTarget = getConversions () .getCustomWriteTarget (value .getClass ());
572580
573581 if (customWriteTarget .isPresent ()) {
574582 Class <?> writeTarget = customWriteTarget .get ();
@@ -595,7 +603,7 @@ protected void writeProperty(ElasticsearchPersistentProperty property, Object va
595603
596604 @ Nullable
597605 protected Object getWriteSimpleValue (Object value ) {
598- Optional <Class <?>> customTarget = conversions .getCustomWriteTarget (value .getClass ());
606+ Optional <Class <?>> customTarget = getConversions () .getCustomWriteTarget (value .getClass ());
599607
600608 if (customTarget .isPresent ()) {
601609 return conversionService .convert (value , customTarget .get ());
@@ -759,8 +767,8 @@ private boolean requiresTypeHint(TypeInformation<?> type, Class<?> actualType,
759767 }
760768 }
761769
762- return !conversions .isSimpleType (type .getType ()) && !type .isCollectionLike ()
763- && !conversions .hasCustomWriteTarget (type .getType ());
770+ return !getConversions () .isSimpleType (type .getType ()) && !type .isCollectionLike ()
771+ && !getConversions () .hasCustomWriteTarget (type .getType ());
764772 }
765773
766774 /**
@@ -789,7 +797,7 @@ private boolean isSimpleType(Object value) {
789797 }
790798
791799 private boolean isSimpleType (Class <?> type ) {
792- return conversions .isSimpleType (type );
800+ return getConversions () .isSimpleType (type );
793801 }
794802 // endregion
795803
@@ -819,7 +827,7 @@ private void updateCriteria(Criteria criteria, ElasticsearchPersistentEntity<?>
819827 field .setName (property .getFieldName ());
820828
821829 if (property .hasPropertyConverter ()) {
822- ElasticsearchPersistentPropertyConverter propertyConverter = property .getPropertyConverter ();
830+ ElasticsearchPersistentPropertyConverter propertyConverter = Objects . requireNonNull ( property .getPropertyConverter () );
823831 criteria .getQueryCriteriaEntries ().forEach (criteriaEntry -> {
824832 Object value = criteriaEntry .getValue ();
825833 if (value .getClass ().isArray ()) {
0 commit comments