无法将 GenericApplicationContext 转换为 WebApplicationContext:Spring Web Flow
GenericApplicationContext cannot be cast to WebApplicationContext : Spring Web Flow
我正在尝试在 Spring 环境中仅使用 Java 注释来设置 Spring Web Flow,该环境也仅使用 Java 注释。但是,当我尝试访问我的流程时,出现以下异常
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/forms] threw exception [Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'referral' of flow 'test-flow'] with root cause
java.lang.ClassCastException: org.springframework.context.support.GenericApplicationContext cannot be cast to org.springframework.web.context.WebApplicationContext
at org.springframework.web.servlet.support.RequestContext.initContext(RequestContext.java:235)
at org.springframework.web.servlet.support.RequestContext.<init>(RequestContext.java:202)
at org.springframework.web.servlet.view.AbstractView.createRequestContext(AbstractView.java:316)
at org.springframework.web.servlet.view.AbstractView.createMergedOutputModel(AbstractView.java:296)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:265)
at org.springframework.webflow.mvc.servlet.ServletMvcView.doRender(ServletMvcView.java:55)
at org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:196)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:293)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:242)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:220)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
我已将错误的根源追溯到 RequestContext
对象的实例化,该对象被传递给视图,以便它们访问 ApplicationContext
(以及其他内容)。由于 Spring 能够调用我的流程,因此我相信这是由于我的 Web 流程文件中某处的错误配置而引发的异常。我已经多次审查它们,但找不到任何看起来非常明显的东西。您可以在下面找到我的 Web Flow 配置文件:
DispatcherConfig
@Configuration
@ComponentScan(basePackages = "----")
public class DispatcherConfig {
@Autowired
private FlowDefinitionRegistry flowDefinitionRegistry;
@Autowired
private FlowExecutor flowExecutor;
@Autowired
private AnnotationConfigWebApplicationContext appContext;
@Bean
public FlowHandlerAdapter flowHandlerAdapter()
{
FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
flowHandlerAdapter.setFlowExecutor(flowExecutor);
return flowHandlerAdapter;
}
@Bean
public FlowHandlerMapping flowHandlerMapping()
{
FlowHandlerMapping mapping = new FlowHandlerMapping();
mapping.setFlowRegistry(flowDefinitionRegistry);
mapping.setApplicationContext(appContext);
mapping.setOrder(-1);
return mapping;
}
}
WebFlowConfig
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private List<ViewResolver> viewResolvers;
@Autowired
private ConversionService conversionService;
@Autowired
private AnnotationConfigWebApplicationContext appContext;
@Bean
public FlowDefinitionRegistry flowRegistry()
{
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.setFlowBuilderServices(getFlowBuilderServices())
.build();
}
@Bean
public FlowExecutor flowExecutor()
{
return getFlowExecutorBuilder(flowRegistry()).build();
}
public ExpressionParser getExpressionParser()
{
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
return new WebFlowSpringELExpressionParser(spelExpressionParser);
}
public FlowBuilderServices getFlowBuilderServices()
{
MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
creator.setViewResolvers(viewResolvers);
creator.setApplicationContext(appContext);
creator.setUseSpringBeanBinding(true);
FlowBuilderServices services = new FlowBuilderServices();
services.setViewFactoryCreator(creator);
services.setConversionService(conversionService);
services.setExpressionParser(getExpressionParser());
return services;
}
}
WebMvcConfig
@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public UrlBasedViewResolver velocityViewResolver()
{
UrlBasedViewResolver resolver = new VelocityViewResolver();
resolver.setSuffix(".vm");
resolver.setViewClass(VelocityView.class);
return resolver;
}
@Bean
public VelocityConfigurer velocityConfig()
{
VelocityConfigurer velocityConfigurer = new VelocityConfigurer();
velocityConfigurer.setResourceLoaderPath("/templates/views/");
return velocityConfigurer;
}
@Bean
public List<ViewResolver> viewResolvers()
{
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(velocityViewResolver());
return resolvers;
}
}
我使用的视图技术是 Velocity。 Spring Webflow 版本 2.4.1.RELEASE, Spring 版本 4.1.2.RELEASE, Java 1.8.0_45, Tomcat 7.0.62 .
知道是什么导致了这个异常吗?
更新:已修复
感谢罗曼提供答案。我制作了 FlowBuilderServices
和 MvcViewFactoryCreator
@Bean
,这摆脱了 ClassCastException
。但是,我的配置仍然存在一些问题。我的 @Autowired
List<ViewResolver> viewResolvers
直到 MvcViewFactoryCreator
之后才被实例化。因此,我必须创建一个方法来为 MvcViewFactoryCreator
创建 ViewResolver
列表。我正在寻找使创建顺序正确的方法,但目前这是可行的。以下是我为使 Web Flow 正常运行而必须进行的更改
WebFlowConfig
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
===
-private List<ViewResolver> viewResolvers;
====
+private UrlBasedViewResolver viewResolver
===
...
@Autowired
===
-private AnnotationConfigWebApplicationContext appContext;
===
+private MvcViewFactoryCreator mvcViewFactoryCreator;
===
...
+public List<ViewResolver> getViewResolvers()
+{
+ List<ViewResolver> resolvers = new ArrayList<>();
+ resolvers.add(viewResolver);
+
+ return resolvers;
+}
...
+@Bean
+public MvcViewFactoryCreator mvcViewFactoryCreator()
+{
+ MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
+ creator.setViewResolvers(getViewResolvers());
+ creator.setUseSpringBeanBinding(true);
+ return creator;
+}
@Bean
public FlowBuilderServices flowBuilderServices()
{
===
-MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
-creator.setViewResolvers(viewResolvers);
-creator.setApplicationContext(appContext);
-creator.setUseSpringBeanBinding(true);
===
FlowBuilderServices services = new FlowBuilderServices();
===
-services.setViewFactoryCreator(creator);
===
+services.setViewFactoryCreator(mvcViewFactoryCreator);
===
services.setConversionService(conversionService);
services.setExpressionParser(getExpressionParser());
return services;
}
}
FlowBuilderServices
是一个 Spring-managed bean,但在您的配置中它只是一个 new
实例。它喜欢 ApplicationContextAware
和 InitializingBean
,但这只有在由 Spring.
管理时才有效
解决方法很简单:将@Bean
放在getFlowBuilderServices()
方法上。而且我认为您还应该将 MvcViewFactoryCreator
设为单独的 @Bean
而不是手动使用其 setApplicationContext()
。
我正在尝试在 Spring 环境中仅使用 Java 注释来设置 Spring Web Flow,该环境也仅使用 Java 注释。但是,当我尝试访问我的流程时,出现以下异常
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/forms] threw exception [Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'referral' of flow 'test-flow'] with root cause
java.lang.ClassCastException: org.springframework.context.support.GenericApplicationContext cannot be cast to org.springframework.web.context.WebApplicationContext
at org.springframework.web.servlet.support.RequestContext.initContext(RequestContext.java:235)
at org.springframework.web.servlet.support.RequestContext.<init>(RequestContext.java:202)
at org.springframework.web.servlet.view.AbstractView.createRequestContext(AbstractView.java:316)
at org.springframework.web.servlet.view.AbstractView.createMergedOutputModel(AbstractView.java:296)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:265)
at org.springframework.webflow.mvc.servlet.ServletMvcView.doRender(ServletMvcView.java:55)
at org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:196)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:293)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:242)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:220)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
我已将错误的根源追溯到 RequestContext
对象的实例化,该对象被传递给视图,以便它们访问 ApplicationContext
(以及其他内容)。由于 Spring 能够调用我的流程,因此我相信这是由于我的 Web 流程文件中某处的错误配置而引发的异常。我已经多次审查它们,但找不到任何看起来非常明显的东西。您可以在下面找到我的 Web Flow 配置文件:
DispatcherConfig
@Configuration
@ComponentScan(basePackages = "----")
public class DispatcherConfig {
@Autowired
private FlowDefinitionRegistry flowDefinitionRegistry;
@Autowired
private FlowExecutor flowExecutor;
@Autowired
private AnnotationConfigWebApplicationContext appContext;
@Bean
public FlowHandlerAdapter flowHandlerAdapter()
{
FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
flowHandlerAdapter.setFlowExecutor(flowExecutor);
return flowHandlerAdapter;
}
@Bean
public FlowHandlerMapping flowHandlerMapping()
{
FlowHandlerMapping mapping = new FlowHandlerMapping();
mapping.setFlowRegistry(flowDefinitionRegistry);
mapping.setApplicationContext(appContext);
mapping.setOrder(-1);
return mapping;
}
}
WebFlowConfig
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private List<ViewResolver> viewResolvers;
@Autowired
private ConversionService conversionService;
@Autowired
private AnnotationConfigWebApplicationContext appContext;
@Bean
public FlowDefinitionRegistry flowRegistry()
{
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.setFlowBuilderServices(getFlowBuilderServices())
.build();
}
@Bean
public FlowExecutor flowExecutor()
{
return getFlowExecutorBuilder(flowRegistry()).build();
}
public ExpressionParser getExpressionParser()
{
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
return new WebFlowSpringELExpressionParser(spelExpressionParser);
}
public FlowBuilderServices getFlowBuilderServices()
{
MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
creator.setViewResolvers(viewResolvers);
creator.setApplicationContext(appContext);
creator.setUseSpringBeanBinding(true);
FlowBuilderServices services = new FlowBuilderServices();
services.setViewFactoryCreator(creator);
services.setConversionService(conversionService);
services.setExpressionParser(getExpressionParser());
return services;
}
}
WebMvcConfig
@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public UrlBasedViewResolver velocityViewResolver()
{
UrlBasedViewResolver resolver = new VelocityViewResolver();
resolver.setSuffix(".vm");
resolver.setViewClass(VelocityView.class);
return resolver;
}
@Bean
public VelocityConfigurer velocityConfig()
{
VelocityConfigurer velocityConfigurer = new VelocityConfigurer();
velocityConfigurer.setResourceLoaderPath("/templates/views/");
return velocityConfigurer;
}
@Bean
public List<ViewResolver> viewResolvers()
{
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(velocityViewResolver());
return resolvers;
}
}
我使用的视图技术是 Velocity。 Spring Webflow 版本 2.4.1.RELEASE, Spring 版本 4.1.2.RELEASE, Java 1.8.0_45, Tomcat 7.0.62 .
知道是什么导致了这个异常吗?
更新:已修复
感谢罗曼提供答案。我制作了 FlowBuilderServices
和 MvcViewFactoryCreator
@Bean
,这摆脱了 ClassCastException
。但是,我的配置仍然存在一些问题。我的 @Autowired
List<ViewResolver> viewResolvers
直到 MvcViewFactoryCreator
之后才被实例化。因此,我必须创建一个方法来为 MvcViewFactoryCreator
创建 ViewResolver
列表。我正在寻找使创建顺序正确的方法,但目前这是可行的。以下是我为使 Web Flow 正常运行而必须进行的更改
WebFlowConfig
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
===
-private List<ViewResolver> viewResolvers;
====
+private UrlBasedViewResolver viewResolver
===
...
@Autowired
===
-private AnnotationConfigWebApplicationContext appContext;
===
+private MvcViewFactoryCreator mvcViewFactoryCreator;
===
...
+public List<ViewResolver> getViewResolvers()
+{
+ List<ViewResolver> resolvers = new ArrayList<>();
+ resolvers.add(viewResolver);
+
+ return resolvers;
+}
...
+@Bean
+public MvcViewFactoryCreator mvcViewFactoryCreator()
+{
+ MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
+ creator.setViewResolvers(getViewResolvers());
+ creator.setUseSpringBeanBinding(true);
+ return creator;
+}
@Bean
public FlowBuilderServices flowBuilderServices()
{
===
-MvcViewFactoryCreator creator = new MvcViewFactoryCreator();
-creator.setViewResolvers(viewResolvers);
-creator.setApplicationContext(appContext);
-creator.setUseSpringBeanBinding(true);
===
FlowBuilderServices services = new FlowBuilderServices();
===
-services.setViewFactoryCreator(creator);
===
+services.setViewFactoryCreator(mvcViewFactoryCreator);
===
services.setConversionService(conversionService);
services.setExpressionParser(getExpressionParser());
return services;
}
}
FlowBuilderServices
是一个 Spring-managed bean,但在您的配置中它只是一个 new
实例。它喜欢 ApplicationContextAware
和 InitializingBean
,但这只有在由 Spring.
解决方法很简单:将@Bean
放在getFlowBuilderServices()
方法上。而且我认为您还应该将 MvcViewFactoryCreator
设为单独的 @Bean
而不是手动使用其 setApplicationContext()
。