I am trying to add webflow to a spring boot app using joinfaces library.
I am using primefaces-spring-boot-starter and jetty-spring-boot-starter to configure jetty server.
Added necessary webflow dependencies to pom and configured necessary flowregistry, flowbuilderservices, flowexecutor and flowhandlermapping, ...
The application start correctly, reads the flows definitions from xmls and if enter to a flow via url the decision states are running correctly, reads the corresponding view state .xhtml file, calls the managed bean methods, and all are working apparently well.
But... once finished executing bean methods, when I hope to html be rendered in browser, the application is redirected to app root folder without any error in the log.
I have this behavior with all the flows of the application. Bean methods are executed correctly and when I hope to see the html... redirected to root.
Anyone tried to add webflow to a joinfaces jsf application successfully? I am missing to override some default configuration of joinfaces?
Thanks.
public class MvcConfiguration implements WebMvcConfigurer {
#Autowired
private WebFlowConfiguration webFlowConfiguration;
#Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(this.webFlowConfiguration.flowRegistry());
return handlerMapping;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter() {
JsfFlowHandlerAdapter adapter = new JsfFlowHandlerAdapter();
adapter.setFlowExecutor(this.webFlowConfiguration.flowExecutor());
return adapter;
}
#Bean
public ViewResolver faceletsViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setViewClass(JsfView.class);
resolver.setPrefix("/");
resolver.setSuffix(".xhtml");
return resolver;
}
}
#Configuration
public class WebFlowConfiguration extends AbstractFacesFlowConfiguration {
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("classpath*:/META-INF/resources/flows")
.addFlowLocationPattern("/**/*.xml")
.setFlowBuilderServices(flowBuilderServices())
.build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setDevelopmentMode(true)
.setViewFactoryCreator(new JsfViewFactoryCreator())
.build();
}
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(new FlowFacesContextLifecycleListener())
.addFlowExecutionListener(new SecurityFlowExecutionListener())
.setMaxFlowExecutionSnapshots(0)
.build();
}
}
Related
I am trying to change the same site attribute of my springboot application using WebSessionIdResolver as described here : https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-webflux-custom-cookie.html
#Configuration
public class CookieConfiguration {
#Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.addCookieInitializer(builder -> builder.sameSite("None"));
return resolver;
}
}
I don't understand what is going, when debugging I can see the bean being initialized,but on every http call a session cookie is written with the default sameSite attribute "Lax", and the default CookieWebSessionIdResolver.cookieInitializer being null.
I was able to solve this adding 'spring-session-core' dependency and using the following config :
#EnableSpringWebSession
#Configuration
public class CookieConfiguration {
#Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.addCookieInitializer(builder -> builder.sameSite("None"));
return resolver;
}
#Bean
public ReactiveMapSessionRepository reactiveSessionRepository() {
return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
}
}
I have a problem in injecting multiple HttpSessionIdResolver for a single spring application.
For normal web application I would like to use CookieHttpSessionIdResolver
For Rest API I would go for HeaderHttpSessionIdResolver and Rest API url will be like "/api/**"
Internally spring sets a bean and uses that bean for all request(In this case HeaderHttpSessionIdResolver
and my web stopped working because i dont set X-Auth-Token header for every request) but i would like to override it.
Could any one please help me.
Thank you.
#EnableJdbcHttpSession(maxInactiveIntervalInSeconds = 3600)
public class SessionConfig extends AbstractHttpSessionApplicationInitializer{
#Autowired
#Qualifier("userDatabase")
private DataSource dataSource;
#Bean
public DataSource dataSource() {
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
#Bean(value = "httpSessionIdResolver")
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
#Bean(value = "cookieHttpSessionIdResolver")
public HttpSessionIdResolver cookieHttpSessionIdResolver() {
return new CookieHttpSessionIdResolver();
}
}
I overridden spring session to enable both cookie and header based session.
Now it's working fine.
Currently I'm checking for URL that contains /api/* and if it contains i'm using header based other wise cookie based session.
I need to redirect to a flow from a #Controller, but am not sure how to go about this. I need to either continue with MVC under a certain condition, or go into my flow under another condition. Here's the final line of my /auth method:
return new ModelAndView(isFlowProtected(getClientId(sessionDataPayloadJSON)) ?
"redirect:/login-flow" :
LoginConstants.LOGIN);
Essentially, I have two login flows, one through normal Spring MVC, one under webflow. Here's how I configured my flow:
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder().addFlowLocation("/webflow/login-flow.xml","login-flow"
.setFlowBuilderServices(this.flowBuilderServices())
.build();
}
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(this.flowRegistry())
.build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(this.mvcViewFactoryCreator()) // Important!
.setValidator(this.localValidatorFactoryBean).build();
}
#Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(this.flowRegistry());
return handlerMapping;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter handlerAdapter = new FlowHandlerAdapter();
handlerAdapter.setFlowExecutor(this.flowExecutor());
handlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
return handlerAdapter;
}
#Bean
public ViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
Assuming my path to my flow is correct, what am I doing wrong here? How can I redirect to the login-flow from my /auth endpoint when needed? I'm getting the following error currently:
java.io.FileNotFoundException: Could not open ServletContext resource [/webflow/login-flow.xml]
So maybe my path is wrong? The flow is inside of resources/webflow, so I think it's right, but maybe not?
Do you have a /webflow/login-flow.xml file in your WAR root directory? I think that's what that error indicates, that it can't find that file. I believe your redirect is working correctly, and your WebFlow configuration expects to find a flow configuration file at the location you specified, but it isn't finding it there.
I haven't used Java-based WebFlow configuration before, so I could be misunderstanding this, but best I read this, I think you might still need Flow xml files even when you do the rest of the configuration in Java.
See Configure Spring Web Flow with Java configuration
As the title states.
I am migrating a Spring-MVC application that uses XML based Configuration.
I don't know where to move the filters located in the web.xml file to the new Spring Boot Project.
You can make use of the annotation : #ImportResource for this
Find more details here
You can define your filters using Java Configurations when using Spring Boot.
As mentioned in the documentation, you only need to declare that filter as a Bean in a configuration class.
#Configuration
public class WebConfig {
#Bean
public Filter someFilter() {
return new someFilter();
}
}
If for some reason "SomeFilter" is not a spring managed bean, or if you need to customize the filter behaviour, then you can register the filter using FilterRegistrationBean as follows
#Configuration
public class WebConfig {
#Bean
public Filter someFilter() {
return new someFilter();
}
#Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(someFilter());
return registration;
}
}
In case of multiple Filters you can specify the order using FilterRegistrationBean.setOrder() as mentioned in the doc
Finally I registered my Interceptors using Java Configuration (no xml) this way.
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
ControllerInterceptor controllerInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.controllerInterceptor).addPathPatterns(this.buildPaths());
}
private String[] buildPaths() {
String paths[] = { "/api/example1/**", "/api/example2/**" };
return paths;
}
}
Although there are a lot of code example on the internet of integrating Spring Boot/Spring and Resteasy, but most of them are out of data or even don't work.
I am look at the latest Resteasy document, try to create a instance of SpringBeanProcessorServletAware in my config bean.
#Bean
public ServletListenerRegistrationBean<ResteasyBootstrap> resteasyBootstrapRegistratio() {
ServletListenerRegistrationBean<ResteasyBootstrap> registration = new ServletListenerRegistrationBean<>();
registration.setListener(new ResteasyBootstrap());
return registration;
}
#Bean
public ServletRegistrationBean resteasyServletRegistratio() {
ServletRegistrationBean registration = new ServletRegistrationBean();
registration.setServlet(new HttpServletDispatcher());
registration.addUrlMappings("/*");
return registration;
}
#Bean
public SpringBeanProcessorServletAware springBeanProcessorServletAware() {
SpringBeanProcessorServletAware springBeanProcessor = new SpringBeanProcessorServletAware();
return springBeanProcessor;
}
But it will throw Nullpoint exception. It seems like the servletContext is required to make SpringBeanProcessorServletAware work.
Then I try to inject servletContext. But the bean SpringBeanProcessorServletAware is being created before ServletContextInitializer finished.
How to make some bean created after ServletContextInitializer is finished?
Am I wrong in do the integration between Spring Boot and Resteasy.