Skip to content

Commit af86398

Browse files
GH-2684 - Make Neo4j templates safer to use outside an application context.
While still not recommended to use outside an application context, this allows basic usage. Closes #2684.
1 parent 571d3a1 commit af86398

File tree

2 files changed

+36
-22
lines changed

2 files changed

+36
-22
lines changed

src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java

+19-12
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public final class Neo4jTemplate implements
123123

124124
private EventSupport eventSupport;
125125

126-
private ProjectionFactory projectionFactory;
126+
private ProjectionFactory projectionFactoryf;
127127

128128
private Renderer renderer;
129129

@@ -169,6 +169,11 @@ public Neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingCo
169169
this.neo4jMappingContext = neo4jMappingContext;
170170
this.cypherGenerator = CypherGenerator.INSTANCE;
171171
this.eventSupport = EventSupport.useExistingCallbacks(neo4jMappingContext, entityCallbacks);
172+
this.renderer = Renderer.getDefaultRenderer();
173+
}
174+
175+
ProjectionFactory getProjectionFactory() {
176+
return Objects.requireNonNull(this.projectionFactoryf, "Projection support for the Neo4j template is only available when the template is a proper and fully initialized Spring bean.");
172177
}
173178

174179
@Override
@@ -283,7 +288,7 @@ <T, R> List<R> doFind(@Nullable String cypherQuery, @Nullable Map<String, Object
283288

284289
if (resultType.isInterface()) {
285290
return intermediaResults.stream()
286-
.map(instance -> projectionFactory.createProjection(resultType, instance))
291+
.map(instance -> getProjectionFactory().createProjection(resultType, instance))
287292
.collect(Collectors.toList());
288293
}
289294

@@ -370,23 +375,24 @@ public <T, R> R saveAs(T instance, Class<R> resultType) {
370375
return resultType.cast(save(instance));
371376
}
372377

373-
ProjectionInformation projectionInformation = projectionFactory.getProjectionInformation(resultType);
378+
ProjectionFactory localProjectionFactory = getProjectionFactory();
379+
ProjectionInformation projectionInformation = localProjectionFactory.getProjectionInformation(resultType);
374380
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(instance.getClass(), resultType,
375-
projectionFactory, neo4jMappingContext);
381+
localProjectionFactory, neo4jMappingContext);
376382

377383
T savedInstance = saveImpl(instance, pps, null);
378384
if (!resultType.isInterface()) {
379385
@SuppressWarnings("unchecked") R result = (R) new DtoInstantiatingConverter(resultType, neo4jMappingContext).convertDirectly(savedInstance);
380386
return result;
381387
}
382388
if (projectionInformation.isClosed()) {
383-
return projectionFactory.createProjection(resultType, savedInstance);
389+
return localProjectionFactory.createProjection(resultType, savedInstance);
384390
}
385391

386392
Neo4jPersistentEntity<?> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(savedInstance.getClass());
387393
Neo4jPersistentProperty idProperty = entityMetaData.getIdProperty();
388394
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(savedInstance);
389-
return projectionFactory.createProjection(resultType,
395+
return localProjectionFactory.createProjection(resultType,
390396
this.findById(propertyAccessor.getProperty(idProperty), savedInstance.getClass()).get());
391397
}
392398

@@ -570,15 +576,16 @@ public <T, R> List<R> saveAllAs(Iterable<T> instances, Class<R> resultType) {
570576
return saveElements;
571577
}
572578

573-
ProjectionInformation projectionInformation = projectionFactory.getProjectionInformation(resultType);
579+
ProjectionFactory localProjectionFactory = getProjectionFactory();
580+
ProjectionInformation projectionInformation = localProjectionFactory.getProjectionInformation(resultType);
574581

575582
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(commonElementType, resultType,
576-
projectionFactory, neo4jMappingContext);
583+
localProjectionFactory, neo4jMappingContext);
577584

578585
List<T> savedInstances = saveAllImpl(instances, pps, null);
579586

580587
if (projectionInformation.isClosed()) {
581-
return savedInstances.stream().map(instance -> projectionFactory.createProjection(resultType, instance))
588+
return savedInstances.stream().map(instance -> localProjectionFactory.createProjection(resultType, instance))
582589
.collect(Collectors.toList());
583590
}
584591

@@ -591,7 +598,7 @@ public <T, R> List<R> saveAllAs(Iterable<T> instances, Class<R> resultType) {
591598
}).collect(Collectors.toList());
592599

593600
return findAllById(ids, commonElementType)
594-
.stream().map(instance -> projectionFactory.createProjection(resultType, instance))
601+
.stream().map(instance -> localProjectionFactory.createProjection(resultType, instance))
595602
.collect(Collectors.toList());
596603
}
597604

@@ -1024,7 +1031,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
10241031
SpelAwareProxyProjectionFactory spelAwareProxyProjectionFactory = new SpelAwareProxyProjectionFactory();
10251032
spelAwareProxyProjectionFactory.setBeanClassLoader(beanClassLoader);
10261033
spelAwareProxyProjectionFactory.setBeanFactory(beanFactory);
1027-
this.projectionFactory = spelAwareProxyProjectionFactory;
1034+
this.projectionFactoryf = spelAwareProxyProjectionFactory;
10281035

10291036
Configuration cypherDslConfiguration = beanFactory
10301037
.getBeanProvider(Configuration.class)
@@ -1078,7 +1085,7 @@ <T, R> List<R> doSave(Iterable<R> instances, Class<T> domainType) {
10781085
Class<?> resultType = TemplateSupport.findCommonElementType(instances);
10791086

10801087
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(domainType, resultType,
1081-
projectionFactory, neo4jMappingContext);
1088+
getProjectionFactory(), neo4jMappingContext);
10821089

10831090
NestedRelationshipProcessingStateMachine stateMachine = new NestedRelationshipProcessingStateMachine(neo4jMappingContext);
10841091
List<R> results = new ArrayList<>();

src/main/java/org/springframework/data/neo4j/core/ReactiveNeo4jTemplate.java

+17-10
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ public ReactiveNeo4jTemplate(ReactiveNeo4jClient neo4jClient, Neo4jMappingContex
150150
this.neo4jMappingContext = neo4jMappingContext;
151151
this.cypherGenerator = CypherGenerator.INSTANCE;
152152
this.eventSupport = ReactiveEventSupport.useExistingCallbacks(neo4jMappingContext, ReactiveEntityCallbacks.create());
153+
this.renderer = Renderer.getDefaultRenderer();
154+
}
155+
156+
ProjectionFactory getProjectionFactory() {
157+
return Objects.requireNonNull(this.projectionFactory, "Projection support for the Neo4j template is only available when the template is a proper and fully initialized Spring bean.");
153158
}
154159

155160
@Override
@@ -264,7 +269,7 @@ <T, R> Flux<R> doFind(@Nullable String cypherQuery, @Nullable Map<String, Object
264269
}
265270

266271
if (resultType.isInterface()) {
267-
return intermediaResults.map(instance -> projectionFactory.createProjection(resultType, instance));
272+
return intermediaResults.map(instance -> getProjectionFactory().createProjection(resultType, instance));
268273
}
269274

270275
DtoInstantiatingConverter converter = new DtoInstantiatingConverter(resultType, neo4jMappingContext);
@@ -355,9 +360,10 @@ public <T, R> Mono<R> saveAs(T instance, Class<R> resultType) {
355360
return save(instance).map(resultType::cast);
356361
}
357362

358-
ProjectionInformation projectionInformation = projectionFactory.getProjectionInformation(resultType);
363+
ProjectionFactory localProjectionFactory = getProjectionFactory();
364+
ProjectionInformation projectionInformation = localProjectionFactory.getProjectionInformation(resultType);
359365
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(instance.getClass(), resultType,
360-
projectionFactory, neo4jMappingContext);
366+
localProjectionFactory, neo4jMappingContext);
361367

362368
Mono<T> savingPublisher = saveImpl(instance, pps, null);
363369

@@ -369,7 +375,7 @@ public <T, R> Mono<R> saveAs(T instance, Class<R> resultType) {
369375
});
370376
}
371377
if (projectionInformation.isClosed()) {
372-
return savingPublisher.map(savedInstance -> projectionFactory.createProjection(resultType, savedInstance));
378+
return savingPublisher.map(savedInstance -> localProjectionFactory.createProjection(resultType, savedInstance));
373379
}
374380

375381
return savingPublisher.flatMap(savedInstance -> {
@@ -378,7 +384,7 @@ public <T, R> Mono<R> saveAs(T instance, Class<R> resultType) {
378384
Neo4jPersistentProperty idProperty = entityMetaData.getIdProperty();
379385
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(savedInstance);
380386
return this.findById(propertyAccessor.getProperty(idProperty), savedInstance.getClass())
381-
.map(loadedValue -> projectionFactory.createProjection(resultType, loadedValue));
387+
.map(loadedValue -> localProjectionFactory.createProjection(resultType, loadedValue));
382388
});
383389
}
384390

@@ -391,7 +397,7 @@ <T, R> Flux<R> doSave(Iterable<R> instances, Class<T> domainType) {
391397
Class<?> resultType = TemplateSupport.findCommonElementType(instances);
392398

393399
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(domainType, resultType,
394-
projectionFactory, neo4jMappingContext);
400+
getProjectionFactory(), neo4jMappingContext);
395401

396402
NestedRelationshipProcessingStateMachine stateMachine = new NestedRelationshipProcessingStateMachine(neo4jMappingContext);
397403
EntityFromDtoInstantiatingConverter<T> converter = new EntityFromDtoInstantiatingConverter<>(domainType, neo4jMappingContext);
@@ -515,13 +521,14 @@ public <T, R> Flux<R> saveAllAs(Iterable<T> instances, Class<R> resultType) {
515521
return saveAll(instances).map(resultType::cast);
516522
}
517523

518-
ProjectionInformation projectionInformation = projectionFactory.getProjectionInformation(resultType);
524+
ProjectionFactory localProjectionFactory = getProjectionFactory();
525+
ProjectionInformation projectionInformation = localProjectionFactory.getProjectionInformation(resultType);
519526
Collection<PropertyFilter.ProjectedPath> pps = PropertyFilterSupport.addPropertiesFrom(commonElementType, resultType,
520-
projectionFactory, neo4jMappingContext);
527+
localProjectionFactory, neo4jMappingContext);
521528

522529
Flux<T> savedInstances = saveAllImpl(instances, pps, null);
523530
if (projectionInformation.isClosed()) {
524-
return savedInstances.map(instance -> projectionFactory.createProjection(resultType, instance));
531+
return savedInstances.map(instance -> localProjectionFactory.createProjection(resultType, instance));
525532
}
526533

527534
Neo4jPersistentEntity<?> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(commonElementType);
@@ -530,7 +537,7 @@ public <T, R> Flux<R> saveAllAs(Iterable<T> instances, Class<R> resultType) {
530537
return savedInstances.flatMap(savedInstance -> {
531538
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(savedInstance);
532539
return findById(propertyAccessor.getProperty(idProperty), commonElementType);
533-
}).map(instance -> projectionFactory.createProjection(resultType, instance));
540+
}).map(instance -> localProjectionFactory.createProjection(resultType, instance));
534541
}
535542

536543
private <T> Flux<T> saveAllImpl(Iterable<T> instances, @Nullable Collection<PropertyFilter.ProjectedPath> includedProperties, @Nullable BiPredicate<PropertyPath, Neo4jPersistentProperty> includeProperty) {

0 commit comments

Comments
 (0)