Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache setup failure does not provide nested cause #25250

Closed
Bluselye opened this issue Jun 15, 2020 · 8 comments
Closed

Cache setup failure does not provide nested cause #25250

Bluselye opened this issue Jun 15, 2020 · 8 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@Bluselye
Copy link

Bluselye commented Jun 15, 2020

When the our spring-framework project is started, we defined multi CacheManager, but not set which is primary, then running the class AbstractApplicationContext.finishBeanFactoryInitialization, there is an IllegalStateException:

No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary or declare a specific CacheManager to use.

But it not catched, it only catched BeansException, then it will do the finally code, it will lose some key message to help find the issue.

It's hard to find the issue because the exception is not logged. So can spring catch the exception of IllegalStateException or RuntimeException?

It's solved by setting the primary CacheManager via @Primary.

Code:org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization

        @Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

There has exception code:
org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated:

	@Override
	public void afterSingletonsInstantiated() {
		if (getCacheResolver() == null) {
			// Lazily initialize cache resolver via default cache manager...
			Assert.state(this.beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect");
			try {
				setCacheManager(this.beanFactory.getBean(CacheManager.class));
			}
			catch (NoUniqueBeanDefinitionException ex) {
				throw new IllegalStateException("No CacheResolver specified, and no unique bean of type " +
						"CacheManager found. Mark one as primary or declare a specific CacheManager to use.");
			}
			catch (NoSuchBeanDefinitionException ex) {
				throw new IllegalStateException("No CacheResolver specified, and no bean of type CacheManager found. " +
						"Register a CacheManager bean or remove the @EnableCaching annotation from your configuration.");
			}
		}
		this.initialized = true;
	}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 15, 2020
@snicoll
Copy link
Member

snicoll commented Jun 15, 2020

The error message is intended to guide you as what the next steps are for this:

No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary or declare a specific CacheManager to use.

I don't really understand how the nested cause would have helped you. If you have multiple cache managers, you need to flag one as @Primary or you should define a CacheResolver instead. Both these options are provided in the error message.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Jun 15, 2020
@Bluselye
Copy link
Author

My means that the IllegalStateException not catched, so my project is also running but not have error log or other message, and the project is also can't do request, so can in class AbstractApplicationContext's method: refresh() can catch the same as IllegalStateException?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 15, 2020
@snicoll
Copy link
Member

snicoll commented Jun 15, 2020

I am not sure I understand what you mean by that. It must not be caught. It is supposed to fail hard and prevent your application to start as its configuration is incorrect.

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jun 15, 2020
@Bluselye
Copy link
Author

Yes,my application is incorrect, but the exception is not logged,so it's make me many hours to find the exception. If I can know the exception,I will quickly solve it.

@snicoll
Copy link
Member

snicoll commented Jun 15, 2020

I don't see how the exception would not be logged. Can you please share a small sample that demonstrates the problem (either a zip attached to this issue or a link to a GitHub repo)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 15, 2020
@pmv
Copy link

pmv commented Apr 28, 2021

No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary or declare a specific CacheManager to use.

I don't really understand how the nested cause would have helped you. If you have multiple cache managers, you need to flag one as @Primary or you should define a CacheResolver instead. Both these options are provided in the error message.

Both options are provided, but having the nested cause is clearer. Having

java.lang.IllegalStateException: No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary or declare a specific CacheManager to use.
	at org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated(CacheAspectSupport.java:223)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:899)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)

means I start in CacheAspectSupport.afterSingletonsInstantiated and drill down to the real problem. Whereas if I'd have known

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cache.CacheManager' available: more than one 'primary' bean found among candidates: [...]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandidate(DefaultListableBeanFactory.java:1574)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1171)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:419)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated(CacheAspectSupport.java:220)

from the outset, it clarifies things a bit ("So that's why @Primary on the bean I want doesn't work")

"Hours" is definitely an exaggeration in my case (10 minutes?), but the missing root cause did feel like enough of a "bug" that I searched for and found this issue.

@snicoll
Copy link
Member

snicoll commented Apr 29, 2021

Your case is different, you have two beans marked as @Primary. I think the bottom line here is " and no unique bean of type CacheManager found". I'll have a look to see if we can provide a bit more context.

@snicoll snicoll changed the title When has multi CacheManager but not set @Primary,there will throw a exception but not cached,can springframework-context can catched this Exception? Cache setup failure does not provide nested cause Apr 29, 2021
@snicoll snicoll added type: bug A general bug and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 29, 2021
@snicoll snicoll self-assigned this Apr 29, 2021
@snicoll snicoll added this to the 5.3.7 milestone Apr 29, 2021
@Bluselye
Copy link
Author

Thanks for take my advice, I think it's better than before.

@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement and removed type: bug A general bug labels May 28, 2021
Zoran0104 pushed a commit to Zoran0104/spring-framework that referenced this issue Aug 20, 2021
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants