Skip to content

Commit 210ab24

Browse files
odrotbohmmp911de
authored andcommitted
DATACMNS-1734 - Defer initialization of Repositories in DomainClassConverter.
DomainClassConverter now delays the initialization of the Repositories instances used to avoid the premature initialization of repository instances as that can cause deadlocks if the infrastructure backing the repositories is initialized on a separate thread. Refactored nested converter classes to allow them to be static ones. Related issues: spring-projects/spring-boot#16230, spring-projects/spring-framework#25131. Original pull request: #445.
1 parent 644b65e commit 210ab24

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

src/main/java/org/springframework/data/repository/support/DomainClassConverter.java

+29-9
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.data.repository.CrudRepository;
3131
import org.springframework.data.repository.core.EntityInformation;
3232
import org.springframework.data.repository.core.RepositoryInformation;
33+
import org.springframework.data.util.Lazy;
3334
import org.springframework.lang.Nullable;
3435
import org.springframework.util.Assert;
3536
import org.springframework.util.StringUtils;
@@ -47,7 +48,7 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
4748
implements ConditionalGenericConverter, ApplicationContextAware {
4849

4950
private final T conversionService;
50-
private Repositories repositories = Repositories.NONE;
51+
private Lazy<Repositories> repositories = Lazy.of(Repositories.NONE);
5152
private Optional<ToEntityConverter> toEntityConverter = Optional.empty();
5253
private Optional<ToIdConverter> toIdConverter = Optional.empty();
5354

@@ -97,7 +98,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
9798
* @return
9899
*/
99100
private Optional<? extends ConditionalGenericConverter> getConverter(TypeDescriptor targetType) {
100-
return repositories.hasRepositoryFor(targetType.getType()) ? toEntityConverter : toIdConverter;
101+
return repositories.get().hasRepositoryFor(targetType.getType()) ? toEntityConverter : toIdConverter;
101102
}
102103

103104
/*
@@ -106,13 +107,18 @@ private Optional<? extends ConditionalGenericConverter> getConverter(TypeDescrip
106107
*/
107108
public void setApplicationContext(ApplicationContext context) {
108109

109-
this.repositories = new Repositories(context);
110+
this.repositories = Lazy.of(() -> {
110111

111-
this.toEntityConverter = Optional.of(new ToEntityConverter(this.repositories, this.conversionService));
112-
this.toEntityConverter.ifPresent(it -> this.conversionService.addConverter(it));
112+
Repositories repositories = new Repositories(context);
113113

114-
this.toIdConverter = Optional.of(new ToIdConverter());
115-
this.toIdConverter.ifPresent(it -> this.conversionService.addConverter(it));
114+
this.toEntityConverter = Optional.of(new ToEntityConverter(repositories, conversionService));
115+
this.toEntityConverter.ifPresent(it -> conversionService.addConverter(it));
116+
117+
this.toIdConverter = Optional.of(new ToIdConverter(repositories, conversionService));
118+
this.toIdConverter.ifPresent(it -> conversionService.addConverter(it));
119+
120+
return repositories;
121+
});
116122
}
117123

118124
/**
@@ -121,9 +127,11 @@ public void setApplicationContext(ApplicationContext context) {
121127
* @author Oliver Gierke
122128
* @since 1.10
123129
*/
124-
private class ToEntityConverter implements ConditionalGenericConverter {
130+
private static class ToEntityConverter implements ConditionalGenericConverter {
125131

126132
private final RepositoryInvokerFactory repositoryInvokerFactory;
133+
private final Repositories repositories;
134+
private final ConversionService conversionService;
127135

128136
/**
129137
* Creates a new {@link ToEntityConverter} for the given {@link Repositories} and {@link ConversionService}.
@@ -132,7 +140,10 @@ private class ToEntityConverter implements ConditionalGenericConverter {
132140
* @param conversionService must not be {@literal null}.
133141
*/
134142
public ToEntityConverter(Repositories repositories, ConversionService conversionService) {
143+
135144
this.repositoryInvokerFactory = new DefaultRepositoryInvokerFactory(repositories, conversionService);
145+
this.repositories = repositories;
146+
this.conversionService = conversionService;
136147
}
137148

138149
/*
@@ -206,7 +217,16 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
206217
* @author Oliver Gierke
207218
* @since 1.10
208219
*/
209-
class ToIdConverter implements ConditionalGenericConverter {
220+
static class ToIdConverter implements ConditionalGenericConverter {
221+
222+
private final Repositories repositories;
223+
private final ConversionService conversionService;
224+
225+
public ToIdConverter(Repositories repositories, ConversionService conversionService) {
226+
227+
this.repositories = repositories;
228+
this.conversionService = conversionService;
229+
}
210230

211231
/*
212232
* (non-Javadoc)

src/test/java/org/springframework/data/repository/support/DomainClassConverterUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.mockito.junit.jupiter.MockitoExtension;
3030
import org.mockito.junit.jupiter.MockitoSettings;
3131
import org.mockito.quality.Strictness;
32-
3332
import org.springframework.aop.framework.Advised;
3433
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3534
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -181,6 +180,7 @@ void supportsConversionFromEntityToString() {
181180
void toIdConverterDoesNotMatchIfTargetTypeIsAssignableFromSource() throws NoSuchMethodException {
182181

183182
converter.setApplicationContext(initContextWithRepo());
183+
assertMatches(false);
184184

185185
@SuppressWarnings("rawtypes")
186186
Optional<ToIdConverter> toIdConverter = (Optional<ToIdConverter>) ReflectionTestUtils.getField(converter,

0 commit comments

Comments
 (0)