I'm having a weird problem with my Spring application with Spring Webflow. The problem is, when I set flow like in documentation:
@Bean
public FlowBuilderServices flowBuilderServices()
{
return getFlowBuilderServicesBuilder()
.setValidator(validator)
.build();
}
It does not find beans in my application.I described this problem here: Spring web flow can't resolve service bean? However when I set application context manually like this :
@Bean
public FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = getFlowBuilderServicesBuilder().build();
fbs.setApplicationContext(getApplicationContext());
fbs.setValidator(validator);
return fbs;
}
It works fine. I haven't seen yet someone setting application config manually like I do, so i think there is some problem with config of my application. Here is my application config:
public class ElectronicsStoreWebInitialiser extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected void customizeRegistration(Dynamic registration) {
registration.setMultipartConfig(
new MultipartConfigElement("/tmp/images",
2097152, 4194304, 0));
}
}
Webconfig:
@Configuration
@Import(godziszewski.patryk.ElectronicsStore.config.FlowConfiguration.class)
@EnableWebMvc
@ComponentScan(basePackages = "godziszewski.patryk")
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
@Override
public Validator getValidator() {
return validator();
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/**").addResourceLocations("/resources/");
}
@Bean
TilesConfigurer tilesConfigurer() {
TilesConfigurer tiles = new TilesConfigurer();
tiles.setDefinitions(new String[] {
"/WEB-INF/tiles/definition/tile-definition.xml"
});
tiles.setCheckRefresh(true);
return tiles;
}
@Bean
public ViewResolver tilesViewResolver() {
TilesViewResolver tv = new TilesViewResolver();
tv.setOrder(-2);
return tv;
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
rb.setBasename("messages");
return rb;
}
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
public ContentNegotiatingViewResolver contentResolver() {
ContentNegotiatingViewResolver cn = new ContentNegotiatingViewResolver();
List<View> listOfViews = new ArrayList<View>();
listOfViews.add(jsonView());
listOfViews.add(xmlView());
cn.setDefaultViews(listOfViews);
return cn;
}
@Bean
public MappingJackson2JsonView jsonView() {
MappingJackson2JsonView mj= new MappingJackson2JsonView();
mj.setPrettyPrint(true);
return mj;
}
@Bean
public MarshallingView xmlView() {
Jaxb2Marshaller ja = new Jaxb2Marshaller();
ja.setClassesToBeBound(Product.class);
MarshallingView mv = new MarshallingView(ja);
return mv;
}
@Bean
public Validator validator() {
LocalValidatorFactoryBean lv = new LocalValidatorFactoryBean();
lv.setValidationMessageSource(messageSource());
return lv;
}
}
And flow configuration:
public class FlowConfiguration extends AbstractFlowConfiguration {
@Autowired
Validator validator;
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setFlowBuilderServices(flowBuilderServices())
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(securityFlowExecutionListener())
.build();
}
@Bean
public FlowHandlerMapping flowHandlerMapping()
{
FlowHandlerMapping fh = new FlowHandlerMapping();
fh.setFlowRegistry(flowRegistry());
return fh;
}
@Bean
public FlowHandlerAdapter flowHandlerAdapter()
{
FlowHandlerAdapter fh = new FlowHandlerAdapter();
fh.setFlowExecutor(flowExecutor());
return fh;
}
@Bean
public FlowBuilderServices flowBuilderServices()
{
return getFlowBuilderServicesBuilder()
.setValidator(validator)
.build();
/*FlowBuilderServices fbs = getFlowBuilderServicesBuilder().build();
System.out.println(fbs.getApplicationContext());
fbs.setApplicationContext(getApplicationContext());
fbs.setValidator(validator);
return fbs;*/
}
@Bean
public SecurityFlowExecutionListener securityFlowExecutionListener()
{
return new SecurityFlowExecutionListener();
}
}
Now it doesn't bother me that much, cause when I set application context manually - it works like it should, but it's rather weird behaviour and I spent some time figuring out the fix and I feel that it should not work like this. Can you take a look at my code? Thanks in advance