spring-projects / spring-projects/spring-framework

Make BeanNameViewResolver use a supplied ApplicationContext

Open
#29,383 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: core status: pending-design-work type: enhancement
Dominant language
Java
Stars
60.2k
Forks
38.8k
Avg merge
5d 2h
Merged PRs (30d)
27

Description

With the deprecation of the XmlViewResolver and ResourceBundleViewResolver it is harder to have multiple ViewResolver instances to resolve a view with the same name but for a different content-types.

I thought of using the BeanNameViewResolver however as that is ApplicationContextAware it gets the ApplicationContext it runs in injected, resulting in an error.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pdfViewResolver' defined in class path resource [com/apress/spring6recipes/court/config/ViewResolverConfiguration.class]: Cannot reinitialize with different application context: current one is [org.springframework.context.support.GenericApplicationContext@61b718e, started on Tue Oct 25 17:31:00 GMT 2022], passed-in one is [WebApplicationContext for namespace 'dispatcher-servlet', started on Tue Oct 25 17:31:00 GMT 2022]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:606)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:931)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:916)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
        at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:699)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:576)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:169)
        at jakarta.servlet.GenericServlet.init(GenericServlet.java:158)
        at jakarta.servlet.http.HttpServlet.init(HttpServlet.java:140)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:995)
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:696)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:128)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1739)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: org.springframework.context.ApplicationContextException: Cannot reinitialize with different application context: current one is [org.springframework.context.support.GenericApplicationContext@61b718e, started on Tue Oct 25 17:31:00 GMT 2022], passed-in one is [WebApplicationContext for namespace 'dispatcher-servlet', started on Tue Oct 25 17:31:00 GMT 2022]
        at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:83)
        at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:109)
        at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:85)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:420)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)

It would be nice if we could use the constructor to pass in an ApplicationContext to be used with the BeanNameViewResolver much like the DispatcherServlet does. This way you can have a small ApplicationContext with functional beans to resolve to views with the same name but for different content-types.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading BeanNameViewResolver, ApplicationObjectSupport, and the DispatcherServlet context-handling path described in the stack trace. Determine how a supplied ApplicationContext should be used without conflicting with ApplicationContextAware, then add focused coverage showing resolution from the supplied context and run the relevant Spring MVC tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
web-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.