Skip to content

Commit 52a63fe

Browse files
GH-1691 - Fail early if bookmark setup is enabled without a bookmark manager.
This change adds a bean through `@EnableBookmarkManagement` that asserts the presence of a bean implementing `org.springframework.data.neo4j.bookmark.BookmarkManager`. Thus the context will fail to start up early when the user assumes that the combination of `@EnableBookmarkManagement` and `@UseBookmark` is enough and not only on the latest point in time possible. This closes #1691.
1 parent c44eb9b commit 52a63fe

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

spring-data-neo4j/src/main/java/org/springframework/data/neo4j/bookmark/BookmarkManagementConfiguration.java

+34
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
*/
1616
package org.springframework.data.neo4j.bookmark;
1717

18+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
19+
import org.springframework.beans.factory.ObjectProvider;
1820
import org.springframework.beans.factory.config.BeanDefinition;
21+
import org.springframework.context.ApplicationListener;
1922
import org.springframework.context.annotation.Bean;
2023
import org.springframework.context.annotation.Configuration;
2124
import org.springframework.context.annotation.Role;
25+
import org.springframework.context.event.ContextRefreshedEvent;
2226

2327
/**
2428
* Configuration used by @{@link org.springframework.data.neo4j.annotation.EnableBookmarkManagement}
@@ -33,6 +37,7 @@
3337
* provide the BookmarkManager bean.
3438
*
3539
* @author Frantisek Hartman
40+
* @author Michael J. Simons
3641
*/
3742
@Configuration
3843
public class BookmarkManagementConfiguration {
@@ -52,4 +57,33 @@ public BookmarkInterceptor bookmarkInterceptor() {
5257
return new BookmarkInterceptor();
5358
}
5459

60+
@Bean
61+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
62+
public BookmarkManagerContextValidator bookmarkManagerContextValidator(
63+
ObjectProvider<BookmarkManager> bookmarkManagerProvider) {
64+
return new BookmarkManagerContextValidator(bookmarkManagerProvider);
65+
}
66+
67+
/**
68+
* A helper class that asserts the presence of a {@link BookmarkManager} on startup.
69+
*/
70+
static class BookmarkManagerContextValidator implements ApplicationListener<ContextRefreshedEvent> {
71+
72+
private final ObjectProvider<BookmarkManager> bookmarkManagerProvider;
73+
74+
public BookmarkManagerContextValidator(ObjectProvider<BookmarkManager> bookmarkManagerProvider) {
75+
this.bookmarkManagerProvider = bookmarkManagerProvider;
76+
}
77+
78+
@Override
79+
public void onApplicationEvent(ContextRefreshedEvent event) {
80+
try {
81+
bookmarkManagerProvider.getObject();
82+
} catch (NoSuchBeanDefinitionException e) {
83+
throw new IllegalStateException(
84+
"Bookmark management has been enabled via `@EnableBookmarkManagement` but no bean implementing `org.springframework.data.neo4j.bookmark.BookmarkManager` has been provided.\n"
85+
+ "Preventing the start of the context as all `@UseBookmark` annotated methods would fail. Please provide a bookmark manager.");
86+
}
87+
}
88+
}
5589
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2011-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.bookmark;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
20+
21+
import java.util.Collection;
22+
import java.util.Collections;
23+
24+
import org.junit.Test;
25+
import org.springframework.context.ConfigurableApplicationContext;
26+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.data.neo4j.annotation.EnableBookmarkManagement;
30+
import org.springframework.transaction.annotation.EnableTransactionManagement;
31+
32+
/**
33+
* @author Michael J. Simons
34+
*/
35+
public class BookmarkManagementConfigurationTests {
36+
37+
@Test // GH-1691
38+
public void bookmarkManagerShouldBeRequired() {
39+
40+
assertThatIllegalStateException().isThrownBy(() -> new AnnotationConfigApplicationContext(BookmarkManagementConfiguration.class))
41+
.withMessageStartingWith("Bookmark management has been enabled via `@EnableBookmarkManagement` but no bean implementing `org.springframework.data.neo4j.bookmark.BookmarkManager` has been provided.");
42+
}
43+
44+
@Test // GH-1691
45+
public void bookmarkManagerShouldBeRecognized() {
46+
47+
try(ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BookmarkManagementConfiguration.class, BookmarkManagerConfiguration.class)) {
48+
assertThat(ctx.getBean(BookmarkInterceptor.class)).isNotNull();
49+
assertThat(ctx.getBean(BeanFactoryBookmarkOperationAdvisor.class)).isNotNull();
50+
assertThat(ctx.getBean(
51+
org.springframework.data.neo4j.bookmark.BookmarkManagementConfiguration.BookmarkManagerContextValidator.class)).isNotNull();
52+
}
53+
}
54+
55+
@Configuration
56+
@EnableBookmarkManagement
57+
@EnableTransactionManagement
58+
static class BookmarkManagementConfiguration {
59+
}
60+
61+
@Configuration
62+
static class BookmarkManagerConfiguration {
63+
@Bean
64+
public BookmarkManager bookmarkManager() {
65+
return new BookmarkManager() {
66+
@Override
67+
public Collection<String> getBookmarks() {
68+
return Collections.emptyList();
69+
}
70+
71+
@Override
72+
public void storeBookmark(String bookmark, Collection<String> previous) {
73+
}
74+
};
75+
}
76+
}
77+
}

spring-data-neo4j/src/test/java/org/springframework/data/neo4j/bookmark/BookmarkManagementTests.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.junit.Test;
2121
import org.junit.runner.RunWith;
2222
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.context.ApplicationContext;
24+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2325
import org.springframework.context.annotation.Bean;
2426
import org.springframework.context.annotation.Configuration;
2527
import org.springframework.data.neo4j.annotation.EnableBookmarkManagement;
@@ -143,7 +145,7 @@ public void givenNoBookmark_whenRunMethod_thenShouldUseBookmarkIsSet() {
143145

144146
@Configuration
145147
@EnableBookmarkManagement
146-
@EnableTransactionManagement()
148+
@EnableTransactionManagement
147149
static class BookmarkManagementConfiguration {
148150

149151
@Bean
@@ -166,6 +168,11 @@ public UseBookmarkWrapperOnClassBean useBookmarkWrapperOnClassBean() {
166168
return new UseBookmarkWrapperOnClassBean();
167169
}
168170

171+
@Bean
172+
public BookmarkManager bookmarkManager() {
173+
return new CaffeineBookmarkManager();
174+
}
175+
169176
@Bean
170177
public UseBookmarkWrapperOnMethodBean useBookmarkWrapperOnMethodBean() {
171178
return new UseBookmarkWrapperOnMethodBean();

0 commit comments

Comments
 (0)