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.
This commit is contained in:
Michael Simons
2021-01-12 11:08:52 +01:00
parent c44eb9bf25
commit 52a63fe911
3 changed files with 119 additions and 1 deletions

View File

@@ -15,10 +15,14 @@
*/
package org.springframework.data.neo4j.bookmark;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.context.event.ContextRefreshedEvent;
/**
* Configuration used by @{@link org.springframework.data.neo4j.annotation.EnableBookmarkManagement}
@@ -33,6 +37,7 @@ import org.springframework.context.annotation.Role;
* provide the BookmarkManager bean.
*
* @author Frantisek Hartman
* @author Michael J. Simons
*/
@Configuration
public class BookmarkManagementConfiguration {
@@ -52,4 +57,33 @@ public class BookmarkManagementConfiguration {
return new BookmarkInterceptor();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BookmarkManagerContextValidator bookmarkManagerContextValidator(
ObjectProvider<BookmarkManager> bookmarkManagerProvider) {
return new BookmarkManagerContextValidator(bookmarkManagerProvider);
}
/**
* A helper class that asserts the presence of a {@link BookmarkManager} on startup.
*/
static class BookmarkManagerContextValidator implements ApplicationListener<ContextRefreshedEvent> {
private final ObjectProvider<BookmarkManager> bookmarkManagerProvider;
public BookmarkManagerContextValidator(ObjectProvider<BookmarkManager> bookmarkManagerProvider) {
this.bookmarkManagerProvider = bookmarkManagerProvider;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
bookmarkManagerProvider.getObject();
} catch (NoSuchBeanDefinitionException e) {
throw new IllegalStateException(
"Bookmark management has been enabled via `@EnableBookmarkManagement` but no bean implementing `org.springframework.data.neo4j.bookmark.BookmarkManager` has been provided.\n"
+ "Preventing the start of the context as all `@UseBookmark` annotated methods would fail. Please provide a bookmark manager.");
}
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.bookmark;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import java.util.Collection;
import java.util.Collections;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.annotation.EnableBookmarkManagement;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author Michael J. Simons
*/
public class BookmarkManagementConfigurationTests {
@Test // GH-1691
public void bookmarkManagerShouldBeRequired() {
assertThatIllegalStateException().isThrownBy(() -> new AnnotationConfigApplicationContext(BookmarkManagementConfiguration.class))
.withMessageStartingWith("Bookmark management has been enabled via `@EnableBookmarkManagement` but no bean implementing `org.springframework.data.neo4j.bookmark.BookmarkManager` has been provided.");
}
@Test // GH-1691
public void bookmarkManagerShouldBeRecognized() {
try(ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BookmarkManagementConfiguration.class, BookmarkManagerConfiguration.class)) {
assertThat(ctx.getBean(BookmarkInterceptor.class)).isNotNull();
assertThat(ctx.getBean(BeanFactoryBookmarkOperationAdvisor.class)).isNotNull();
assertThat(ctx.getBean(
org.springframework.data.neo4j.bookmark.BookmarkManagementConfiguration.BookmarkManagerContextValidator.class)).isNotNull();
}
}
@Configuration
@EnableBookmarkManagement
@EnableTransactionManagement
static class BookmarkManagementConfiguration {
}
@Configuration
static class BookmarkManagerConfiguration {
@Bean
public BookmarkManager bookmarkManager() {
return new BookmarkManager() {
@Override
public Collection<String> getBookmarks() {
return Collections.emptyList();
}
@Override
public void storeBookmark(String bookmark, Collection<String> previous) {
}
};
}
}
}

View File

@@ -20,6 +20,8 @@ import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.annotation.EnableBookmarkManagement;
@@ -143,7 +145,7 @@ public class BookmarkManagementTests {
@Configuration
@EnableBookmarkManagement
@EnableTransactionManagement()
@EnableTransactionManagement
static class BookmarkManagementConfiguration {
@Bean
@@ -166,6 +168,11 @@ public class BookmarkManagementTests {
return new UseBookmarkWrapperOnClassBean();
}
@Bean
public BookmarkManager bookmarkManager() {
return new CaffeineBookmarkManager();
}
@Bean
public UseBookmarkWrapperOnMethodBean useBookmarkWrapperOnMethodBean() {
return new UseBookmarkWrapperOnMethodBean();