Spring Web Flow flowExecutionUrl is empty - spring

I'm making simple order-flow via Spring Web Flow, also i have Spring MVC on my project. I've been doing everything according to guides, but my web-app doesn't react to my flow at all. Spring Web Flow Config:
#Configuration
#ComponentScan(basePackages = "config")
public class WebFlowConfig extends AbstractFlowConfiguration {
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true).build();
}
#Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(
Collections.singletonList(this.webMvcConfig.resourceViewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
#Autowired
private DispatcherConfig webMvcConfig;
#Bean
public FlowDefinitionRegistry flowRegistry() {
FlowDefinitionRegistry registry = getFlowDefinitionRegistryBuilder().addFlowLocation("/WEB-INF/flows/order/flowcnf.xml","order").build();
return registry;
}
#Bean
public FlowExecutor flowExecutor() {
return
getFlowExecutorBuilder(flowRegistry()).build();
}
#Bean
public FlowHandlerMapping flowHandlerMapping(){
final FlowHandlerMapping handeler = new FlowHandlerMapping();
handeler.setFlowRegistry(flowRegistry());
handeler.setFlowUrlHandler(defaultFlowUrlHandler());
return handeler;
}
#Bean
public DefaultFlowUrlHandler defaultFlowUrlHandler(){
return new DefaultFlowUrlHandler();
}
#Bean
public FlowHandlerAdapter adapter(){
FlowHandlerAdapter adapter = new FlowHandlerAdapter();
adapter.setFlowUrlHandler(defaultFlowUrlHandler());
adapter.setFlowExecutor(flowExecutor());
return adapter;
}
}
As I said I'm using Spring MVC maybe the problems occurs due to it.
Code snippet below must run "thankCustomer" view-state, but it doesn't.
I get 404 eror if i click the link.
<a class=button href="${flowExecutionUrl}&_eventId=thankCustomer">Замовити!</a>
And the flow code:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
start-state="identify">
<var name="order" class="entity.BookOrder"/>
<subflow-state id="identify" subflow="order/custom" >
<output name="user" value="order.custName" />
<transition on="userIsReady" to="buildOrder"/>
</subflow-state>
<subflow-state id="buildOrder" subflow="order/build">
<input name="order" value="order" />
<transition to="takePayment" on="orderBuilt" />
</subflow-state>
<subflow-state id="takePayment" subflow="order/takePayment" >
<input name="order" value="order"/>
<transition on="paymentTaken" to="saveOrder" />
</subflow-state>
<action-state id="saveOrder">
<evaluate expression="userServiceImpl.addOrder(order.custName,order)"/>
<transition to="thankCustomer" />
</action-state>
<view-state id="thankCustomer" view="/WEB-INF/pages/greeting.jsp" >
<transition to="end-point" />
</view-state>
<end-state id="end-point"/>
<global-transitions>
<transition on="cancel" to="end-point" />
</global-transitions>
</flow>
I've tried to put flow id (order) instead of empty flowExecutionUrl, but still the same eror, I'll be grateful for any kinda help.

I needed to set "order" to my FlowHandlerMapping Bean, couse i already had 2 viewResolvers.

Related

Spring WebFlow doesn't use the the implemented validator

Spring webflow does not use the custom validator PatientValidator to validate Patient model while transitioning from selectPatient state to selectDoctor state.
Here is my code
Patient.java
#Data
#Entity
public class Patient implements Serializable {
private static final long serialVersionUID = -5116169782847291743L;
...
}
PatientValidator.java
#Component
public class PatientValidator extends FieldValidator {
public PatientValidator() { }
public void validateSelectPatient(Patient patient, Errors errors) {
System.out.println("PatientValidator . validateSelectPatient");
}
public void validateSelectDoctor(Patient patient, Errors errors) {
System.out.println("PatientValidator . validateSelectDoctor");
}
}
submit-request-flow.xml
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<secured attributes="ROLE_OFFICER" match="any"/>
<on-start>
<evaluate expression="submitRequestFlow.getPatient()" result="flowScope.patient"></evaluate>
</on-start>
<view-state id="selectPatient" view="flows/requests/new/select-patient" model="patient">
<transition on="select" to="selectDoctor"></transition>
</view-state>
<view-state id="selectDoctor" view="flows/requests/new/select-doctor">
<transition on="select" to="selectTestType"></transition>
<transition on="back" to="selectPatient"></transition>
</view-state>
...
<end-state id="finishFlow" view="externalRedirect:#{uri.get('requests')}">
<output name="success" value="'Request has been added successfully'"/>
</end-state>
<end-state id="cancelFlow" view="externalRedirect:#{uri.get('requests')}">
</end-state>
<global-transitions>
<transition on="cancel" to="cancelFlow" history="discard" bind="false" validate="false"></transition>
</global-transitions>
</flow>
Even if I use the validation method inside Patient.java, the webflow uses it.
#Data
#Entity
public class Patient implements Serializable {
private static final long serialVersionUID = -5116169782847291743L;
...
public void validateSelectPatient(Errors errors) {
errors.reject("NoResultFound");
}
}
I have to use the custom validation rather than the model one, it works just the first time, but I guess after I rebooted spring boot project it doesn't work anymore.
Update #1
I am using
Spring boot 1.5.6.RELEASE
Spring WebFlow 2.4.5.RELEASE
Thymeleaf 3.0.7.RELEASE
Thymeleaf SpringSecurity4 3.0.2.RELEASE
I guess issue is related how spring DevTools works, here is a workaround I have done for another issue here SpelEvaluationException Method cannot be found.

Spring-Tiles annotation based configuration

Hi I am a newbie in Spring framework, In my application I need to integrate Spring with Tiles. How can I add viewResolver for Tiles as well as internalViewResolver for my login page, or how can I make it as one.I am using annotation based configuration. My login page location is
My config class is
public class AppConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
........//
}
where should I place my Tiles JSPs. I hope my question is clear, Please comment for additional information. Thanks!
You should be using UrlBasedViewResolver view resolver and not the InternalResourceViewResolver since the suffix, view name and prefix would be specified in the Tiles Definition XML files.
#Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(TilesView.class);
return viewResolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setDefinitions(new String[]{
"/WEB-INF/defs/general.xml",
"/WEB-INF/defs/tiles.xml" //another definition
});
tilesConfigurer.setCheckRefresh(true);
return tilesConfigurer;
}
And add in your Tiles Def XML file for each views like this:
For url path http://localhost:8080/register:
#RequestMapping("/register")
Definition:
<definition name="page" template="/WEB-INF/layout/page.jsp">
<put-list-attribute name="stylesheets">
<add-attribute value="/resources/css/AdminLTE.min.css" />
</put-list-attribute>
<put-list-attribute name="javascripts">
<add-attribute value="/resources/js/main.js" />
</put-list-attribute>
</definition>
<definition name="register" extends="page">
<put-attribute name="title" value="User Registeration" />
<put-attribute name="body" value="/WEB-INF/jsp/register.jsp" />
<put-attribute name="current" value="register" />
</definition>
I have an example on Github for Spring Tiles but it is using XML Configuration, you can use above #Bean Configuration to make it use JavaConfig.

Spring Batch Integration JobLaunchRequest from Controller

I have a controller from which I would like to run a Spring Batch job. The FilePoller acts as a poller that runs on a schedule but we'd like to run it manually, too. The FilePoller is working on the cron schedule and the JobLaunchRequest works in this fashion. But when we use JobLaunchRequest called from the controller, nothing happens -- the Spring Batch job is not launched. Here is the controller:
#Controller
public class PollerController {
#Autowired
FilePoller FilePoller;
#Autowired
private ApplicationContext appContext;
#RequestMapping(value = "ui/manualPoll.action", method = RequestMethod.GET)
public void manualPollRequest() {
Message<File> message = filePoller.fileMessageSource().receive();
filePoller.setFileParameterName(message.getPayload().getName());
filePoller.setJob((Job)appContext.getBean("myJob"));
filePoller.toRequest(message);
}
The message payload has the file name and I get the Spring Batch job to run from the application context. I have debugged and stepped through code and ensured that the file name from the message payload is not null and that the Spring Batch job is also not null. Inside the FilePoller class I have this:
#Configuration
#PropertySource("classpath:my.properties")
#EnableIntegration
#IntegrationComponentScan
public class FilePoller {
private Job job;
private String fileParameterName;
#Autowired
MyProperty myProperty;
public void setFileParameterName(String fileParameterName) {
this.fileParameterName = fileParameterName;
}
public void setJob(Job job) {
this.job = job;
}
#Bean
#InboundChannelAdapter(value = "inboundFileChannel", poller = #Poller(cron="${my/POLLER}"))
public MessageSource<File> fileMessageSource() {
FileReadingMessageSource source = initialSetUp();
source.setDirectory(new File(myProperty.getProperty(MyConstants.WORKING_DIR)))
return source;
}
private FileReadingMessageSource initialSetUp() {
FileReadingMessageSource source = new FileReadingMessageSource();
CompositeFileListFilter<File> compositeFileListFilter = new CompositeFileListFilter<File>();
SimplePatternFileListFilter simplePatternFileListFilter = new SimplePatternFileListFilter("*.done");
AcceptOnceFileListFilter<File> acceptOnceFileListFilter = new AcceptOnceFileListFilter<File>();
compositeFileListFilter.addFilter(simplePatternFileListFilter);
compositeFileListFilter.addFilter(acceptOnceFileListFilter);
source.setFilter(compositeFileListFilter);
return source;
}
#Transformer
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
jobParametersBuilder.addString(fileParameterName, message.getPayload().getAbsolutePath());
return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
}
The JobLaunchRequest doesn't seem to do anything. I never get into my first step, shown here in the XML config:
<int:annotation-config />
<int:channel id="inboundFileChannel" />
<int:channel id="outboundJobRequestChannel" />
<int:channel id="jobLaunchReplyChannel" />
<int:transformer input-channel="inboundFileChannel"
output-channel="outboundJobRequestChannel">
<bean
class="org.my.poller.FilePoller">
<property name="job" ref="myJob" />
<property name="fileParameterName" value="input.file.name" />
</bean>
</int:transformer>
<batch-int:job-launching-gateway request-channel="outboundJobRequestChannel" reply-channel="jobLaunchReplyChannel" />
<int:logging-channel-adapter channel="jobLaunchReplyChannel" />
<job id="myJob" xmlns="http://www.springframework.org/schema/batch">
<step id="Step1" next="Step2">
<tasklet ref="checkifFileinLogTbl"/>
UPDATE
Thanks, Gary. It works now. If anyone else is interested:
#Autowired
MessageChannel outboundJobRequestChannel;
#Autowired
MessagingTemplate template;
#RequestMapping(value = "ui/manualPoll.action", method = RequestMethod.GET)
public void manualPollRequest() {
Message<File> message = filePoller.fileMessageSource().receive();
//if message !=null, there is a file present on inboundFileChannel
if(message !=null){
filePoller.setFileParameterName("input.file.name");
filePoller.setJob((Job) appContext.getBean("myJob"));
template.convertAndSend(outboundJobRequestChannel, filePoller.toRequest(message));
}
And in the XML I added:
<bean class="org.springframework.integration.core.MessagingTemplate" />
filePoller.toRequest(message);
Just builds the request object.
You need to send it to the outboundJobRequestChannel.
Use a MessagingTemplate (convertSendAndReceive()) or a MessagingGateway to do that.

Spring Webflow + Spring MVC: Action Bean in Java Annotation

I'm using Spring MVC + Spring Webflow 2.
I would like to define a #Bean for an action-state, but i don't know how to do this in Java Annotation, as i get this error:
Method call: Method execute() cannot be found on
com.myapp.action.GaraAgenziaAction type
here an example of what i want to do: spring-webflow-no-actions-were-executed
My Bean:
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
public class GaraAgenziaAction implements Action {
#Override
public Event execute(RequestContext rc) throws Exception {
return new Event(this, "success");
}
}
Flow XML:
<transition on="fail" to="gara-agenzie"/>
<transition on="success" to="gara-conferma"/>
My webAppConfig:
#Bean
public Action GaraAgenziaAction()
{
GaraAgenziaAction garaAgenziaAction = new GaraAgenziaAction();
return garaAgenziaAction;
}
Thank you very much
UPDATE resolved thanks to #Prasad suggestions:
My Bean (added #Component):
import org.springframework.stereotype.Component;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
#Component
public class GaraAgenziaAction implements Action {
#Override
public Event execute(RequestContext rc) throws Exception {
return new Event(this, "success");
}
}
My webAppConfig (changed name of the bean with lowercase):
#Bean
public Action garaAgenziaAction()
{
GaraAgenziaAction beanAction = new GaraAgenziaAction();
return beanAction;
}
Flow XMl configuration (changed bean name to lowercase and pass flowRequestContext as parameter):
<action-state id="action-agenzie">
<evaluate expression="garaAgenziaAction.execute(flowRequestContext)"></evaluate>
<transition on="fail" to="gara-agenzie"/>
<transition on="success" to="gara-conferma"/>
</action-state>
Now it's working fine!
Define the action class in your servlet xml file as:
<!--Class which handles the flow related actions-->
<bean id="garaAgenziaAction" class=" com.myapp.action.GaraAgenziaAction">
</bean>
or annotate it with Component as:
#Component
public class GaraAgenziaAction implements Action{
#Override
public Event execute(RequestContext rc) throws Exception {
return new Event(this, "success");
}
}
In your flow xml access it as:
<action-state id="action-agenzie">
<evaluate expression="garaAgenziaAction.execute(flowRequestContext)"></evaluate>
<transition on="fail" to="gara-agenzie"/>
<transition on="success" to="gara-conferma"/>
</action-state>
For configuration details you can find it in the answer in this link.

How custom authentication-provider works

Good day people.
Please help. Can not understands how my custom authentication-provider should be triggered.
I have:
Spring-context.xml
<security:http pattern="/login" security="none" />
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/login"/>
<security:intercept-url pattern="/" access="hasRole('ROLE_USER')"/>
<security:form-login authentication-failure-url="www.google.com"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userSecurityService"/>
</security:authentication-manager>
<bean id="webContentDAOImpl" class="demidov.pkg.persistence.WebContentDAOImpl">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
<bean id="userSecurityService" class="demidov.pkg.persistence.UserSecurityService">
<property name="webContentDAOIF" >
<ref bean="webContentDAOImpl"/>
</property>
</bean>
Login Controller:
#Controller
public class LoginController {
#RequestMapping(value="/login", method=RequestMethod.GET)
public String login() {
return "login";
}
#RequestMapping(value="/security/j_spring_security_check", method=RequestMethod.POST)
public String access() {
return "redirect:/";
}
}
Login JSP page:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="security/j_spring_security_check" method="post">
UserName: <input type="text"/> <br>
Password: <input type="password"/> <br>
<br>
<input type="submit"/>
</form>
</body>
</html>
Custom principal resolver:
public class UserSecurityService implements UserDetailsService{
WebContentDAOIF webContentDAOIF;
public WebContentDAOIF getWebContentDAOIF() {
return webContentDAOIF;
}
public void setWebContentDAOIF(WebContentDAOIF webContentDAOIF) {
this.webContentDAOIF = webContentDAOIF;
}
#Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException {
UserDetails userDetails = null;
TheUser theUser = webContentDAOIF.fetchUserByName(userName);
userDetails = new User(theUser.getUserEmale(), theUser.getUserPassword(), true, true, true, true, getAthorities(theUser.getRoleAccess()));
return userDetails;
}
public Collection<GrantedAuthority> getAthorities(String role) {
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);
authList.add(new SimpleGrantedAuthority(" "));
if ( role.equals("ROLE_USER")) {
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
}
// Return list of granted authorities
return authList;
}
}
I just can not understand how my custom principal resolver should work with security. How it should be triggered and by what??? When I put wrong username and password on login page it seems not work with my UserSecurityService and just simply redirect me on login page again because of my hasRole(ROLE_USER) in spring-context.xml . I believe that j_spring_security_check may do something, but so doubt of it. Please help me to understand.
kindly refer to below mentioned link, may be of some help :-
spring security custom authentication
method loadUserByUsername is having param userName which is having value posted from browser that userName is compared with DB and password is fetched from DB and passed to UserDetail object which is having a password posted from browser so now it will compare the passwords internally and acts accordingly for authentication

Resources