Page 3 of 4 FirstFirst 1234 LastLast
Results 21 to 30 of 38

Thread: handling end states

  1. #21
    Join Date
    Dec 2004
    Location
    Poland:Konin
    Posts
    7

    Default

    This is my code:
    Code:
    /*
     * Copyright 2002-2006 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    /**
     * created 2006-08-09
     */
    package net.chrisrichardson.foodToGo.webflow;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.lang.ClassUtils;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.webflow.ExternalContext;
    import org.springframework.webflow.context.servlet.ServletExternalContext;
    import org.springframework.webflow.executor.mvc.FlowController;
    import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor;
    import org.springframework.webflow.executor.support.SpringWebFlowExceptionResolver;
    
    /**
     * FoodToGoSWFExceptionResolver is a custom extension of {@link SpringWebFlowExceptionResolver}
     * @see org.springframework.webflow.executor.support.SpringWebFlowExceptionResolver
     * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
     * @author <a href="http://www.witalis.neostrada.pl/foodtogo.html" title="Food To Go sample application">Witold Buszkiewicz</a>
     *
     */
    public class FoodToGoSWFExceptionResolver extends
    		SpringWebFlowExceptionResolver {
    	private FlowController flowController;
    	@Override
    	/**
    	 * @return A ModelAndView which will launch a new flow, when current flow is active. When flow is ended default flow will launch 
    	 * (if FlowController defaultFlowId is set) or defaultErrorView will display 
    	 */
    	protected ModelAndView resolveSwfException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
            String servletPath = request.getServletPath();
            if (LOG.isDebugEnabled()) {
                LOG.debug("servletPath [" + servletPath + "].");
            }
            FlowExecutorArgumentExtractor feae = flowController.getArgumentExtractor();
            String flowIdParameterName = feae.getFlowIdParameterName();
            ExternalContext externalContext = new ServletExternalContext(null, request, response); 
            String flowId = feae.extractFlowId(externalContext);
            servletPath = servletPath + "?" + flowIdParameterName + "=" + flowId;
            if (LOG.isDebugEnabled()) {
                LOG.debug("Processed SWF exception [" + ClassUtils.getShortClassName(exception.getClass())
                        + "]. Redirecting to [" + servletPath + "].");
            }
    
            return getModelAndView("redirect:" + servletPath, exception, request);
    	}
    	/**
    	 * @param flowController the flowController to set
    	 */
    	public void setFlowController(FlowController flowController) {
    		this.flowController = flowController;
    	}
    }
    and portion of my context:
    Code:
    	<bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController">
    		<property name="flowExecutor" ref="flowExecutor"/>
    		<property name="cacheSeconds" value="5"/>
    		<property name="defaultFlowId" value="placeOrder-flow"/>
    	</bean>
    	<bean id="globalExceptionResolver" class="net.chrisrichardson.foodToGo.webflow.FoodToGoSWFExceptionResolver">
    		<property name="supportedSwfExceptions">
    			<list>
    				<value>org.springframework.webflow.execution.repository.NoSuchFlowExecutionException</value>
    			</list>
    		</property>
    		<property name="defaultErrorView" value="index" />
    		<property name="flowController" ref="/flowController.htm"></property>
    	</bean>
    I now, that it is very poor solution, but working for me.

    regards

    Witek.

  2. #22
    Join Date
    Jan 2006
    Location
    Zürich, Switzerland
    Posts
    423

    Default

    Hi Witek,

    Quote Originally Posted by witalis3
    This is my code:
    Thanks for posting it. I'm sure others will find it useful. In fact, you might consider adding it to the Jira issue (see earlier post in this thread).

    Quote Originally Posted by witalis3
    I now, that it is very poor solution, but working for me.
    I don't think it's that bad, and well, if it works for you, that's all that matters -- right?

    I do have one tip though: AFAIK, you do not need to add the flowController field to your class. Instead, you can simply cast the Object handler parameter in resolveSwfException() to a FlowController. You could/should, of course, check its type first via instanceof.

    So why don't you give that a try?

    If it doesn't work (i.e., if the handler passed in is not the FlowController you expect), please let me know. Actually, I would appreciate it if you let us know in any either case, for success or failure.

    Thanks in advance,

    Sam

  3. #23
    Join Date
    Dec 2004
    Location
    Poland:Konin
    Posts
    7

    Default

    Quote Originally Posted by sbrannen
    I do have one tip though: AFAIK, you do not need to add the flowController field to your class. Instead, you can simply cast the Object handler parameter in resolveSwfException() to a FlowController. You could/should, of course, check its type first via instanceof.

    So why don't you give that a try?
    Thanks for quick replay. I search, how to get an instance of FlowController and it is!
    I follow Your tips and here my corected class:
    Code:
    /*
     * Copyright 2002-2006 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    /**
     * created 2006-08-09
     */
    package net.chrisrichardson.foodToGo.webflow;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.lang.ClassUtils;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.webflow.ExternalContext;
    import org.springframework.webflow.context.servlet.ServletExternalContext;
    import org.springframework.webflow.executor.mvc.FlowController;
    import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor;
    import org.springframework.webflow.executor.support.SpringWebFlowExceptionResolver;
    
    /**
     * FoodToGoSWFExceptionResolver is a custom extension of {@link SpringWebFlowExceptionResolver}
     * @see org.springframework.webflow.executor.support.SpringWebFlowExceptionResolver
     * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
     * @author <a href="http://www.witalis.neostrada.pl/foodtogo.html" title="Food To Go sample application">Witold Buszkiewicz</a>
     *
     */
    public class FoodToGoSWFExceptionResolver extends
    		SpringWebFlowExceptionResolver {
    	@Override
    	/**
    	 * @return A ModelAndView which will launch a new flow, when current flow is active. When flow is ended default flow will launch 
    	 * (if FlowController defaultFlowId is set) or defaultErrorView will display 
    	 */
    	protected ModelAndView resolveSwfException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
            String servletPath = request.getServletPath();
            ModelAndView modelAndView = null;
            if (LOG.isDebugEnabled()) {
                LOG.debug("servletPath [" + servletPath + "].");
            }
            if (handler instanceof FlowController) {
    	        FlowController flowController = (FlowController)handler;
    	        FlowExecutorArgumentExtractor feae = flowController.getArgumentExtractor();
    	        String flowIdParameterName = feae.getFlowIdParameterName();
    	        ExternalContext externalContext = new ServletExternalContext(null, request, response); 
    	        String flowId = feae.extractFlowId(externalContext);
    	        servletPath = servletPath + "?" + flowIdParameterName + "=" + flowId;
    	        if (LOG.isDebugEnabled()) {
    	            LOG.debug("Processed SWF exception [" + ClassUtils.getShortClassName(exception.getClass())
    	                    + "]. Redirecting to [" + servletPath + "].");
    	        }
    	        modelAndView = getModelAndView("redirect:" + servletPath, exception, request);
            }
    		return modelAndView;
    	}
    }
    and context after modification:
    Code:
    	<bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController">
    		<property name="flowExecutor" ref="flowExecutor"/>
    		<property name="cacheSeconds" value="5"/>
    		<property name="defaultFlowId" value="placeOrder-flow"/>
    	</bean>
    	<bean id="globalExceptionResolver" class="net.chrisrichardson.foodToGo.webflow.FoodToGoSWFExceptionResolver">
    		<property name="supportedSwfExceptions">
    			<list>
    				<value>org.springframework.webflow.execution.repository.NoSuchFlowExecutionException</value>
    			</list>
    		</property>
    		<property name="defaultErrorView" value="index" />
    	</bean>
    It was tested and still works!

    regards
    Witek.

  4. #24
    Join Date
    Jan 2006
    Location
    Zürich, Switzerland
    Posts
    423

    Default

    Quote Originally Posted by witalis3
    Thanks for quick replay. I search, how to get an instance of FlowController and it is!

    ...

    It was tested and still works!
    Great!

    Your code looks much cleaner now and easier to use.

    Glad you worked it out.

    FYI: I'll try to combine your code and my code to create the first two pluggable strategy implementations for SWF exeception resolving. With these two implementations, I think most standard use cases will be covered.

    Thanks for sharing your code.

    Regards,

    Sam

  5. #25

    Default

    Thanks for providing the code.
    I copied the code and tried to get it working but I have a problem. May be I am missing something here... If I have multiple flows ... i can't set a defaultFlowId for my FlowExecutor and _flowId parameter is not passed around in the URL once the flow kicks-off.... how do I extract what flow to start from available info ?(which seems to be just the expired _flowExecutionKey)?

  6. #26
    Join Date
    Mar 2007
    Posts
    3

    Default could not catch NoSuchFlowExecutionException

    I am trying to use the swf struts birthdate example and put the SpringWebFlowExceptionResolver in my code, but the NoSuchFlowExecutionException still is throwed outside my application.
    Anything else do I need to do besides adding it to applicationContext.xml
    Here is my applicationContext.xml
    Code:
    <beans>
    	<bean id="globalExceptionResolver" class="org.springframework.webflow.executor.support.SpringWebFlowExceptionResolver">
    		<property name="supportedSwfExceptions">
    		<list>
    			<value>org.springframework.webflow.execution.NoSuchFlowDefinitionException</value>
    			<value>org.springframework.webflow.execution.repository.NoSuchFlowExecutionException</value>
    			<value>org.springframework.webflow.conversation.NoSuchConversationException</value>
    			<value>org.springframework.webflow.executor.support.FlowExecutorArgumentExtractionException</value>
    		</list>
    		</property>
    		<property name="defaultErrorView" value="birthdateForm" />
    	</bean>
    </beans>
    Code:
    2007-03-05 13:42:52,093 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/swf_date].[action]] - <Servlet.service() for servlet action threw exception>
    org.springframework.webflow.execution.repository.NoSuchFlowExecutionException: No flow execution could be found with key '_c654AC1DB-D558-B0DD-7C5D-31900A3BA54F_k0E04E495-E1AD-E335-72D9-E883B473BED4' -- perhaps this executing flow has ended or expired? This could happen if your users are relying on browser history (typically via the back button) that references ended flows.; nested exception is org.springframework.webflow.conversation.NoSuchConversationException: No conversation could be found with id '654AC1DB-D558-B0DD-7C5D-31900A3BA54F' -- perhaps this conversation has ended? 
    Caused by: 
    org.springframework.webflow.conversation.NoSuchConversationException: No conversation could be found with id '654AC1DB-D558-B0DD-7C5D-31900A3BA54F' -- perhaps this conversation has ended? 
    	at org.springframework.webflow.conversation.impl.ConversationContainer.getConversation(ConversationContainer.java:91)
    	at org.springframework.webflow.conversation.impl.SessionBindingConversationManager.getConversation(SessionBindingConversationManager.java:109)
    	at org.springframework.webflow.execution.repository.support.AbstractConversationFlowExecutionRepository.getConversation(AbstractConversationFlowExecutionRepository.java:239)
    	at org.springframework.webflow.execution.repository.support.AbstractConversationFlowExecutionRepository.getLock(AbstractConversationFlowExecutionRepository.java:124)
    	at org.springframework.webflow.executor.FlowExecutorImpl.refresh(FlowExecutorImpl.java:268)
    	at org.springframework.webflow.executor.support.FlowRequestHandler.handleFlowRequest(FlowRequestHandler.java:122)
    	at org.springframework.webflow.executor.struts.FlowAction.execute(FlowAction.java:218)
    	at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)
    	at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)
    	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)
    	at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    	at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:833)
    	at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:639)
    	at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1285)
    	at java.lang.Thread.run(Thread.java:595)

  7. #27
    Join Date
    Jan 2006
    Location
    Zürich, Switzerland
    Posts
    423

    Default

    Hi Wang,

    First and foremost, SpringWebFlowExceptionResolver has only been tested in conjunction with Spring MVC as the view/controller technology. Thus I'm not really sure that you can even use the SpringWebFlowExceptionResolver "as is" with Struts, but let's look at your problem in more detail to see if we can help...

    Quote Originally Posted by wang View Post
    I am trying to use the swf struts birthdate example and put the SpringWebFlowExceptionResolver in my code, but the NoSuchFlowExecutionException still is throwed outside my application.
    Anything else do I need to do besides adding it to applicationContext.xml
    With Spring MVC, that's all you'd need; with Struts that unfortunately doesn't appear to be the case.

    Quote Originally Posted by wang View Post
    Here is my applicationContext.xml
    (snip)
    Your config looks fine as well.

    Quote Originally Posted by wang View Post
    Code:
    2007-03-05 13:42:52,093 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/swf_date].[action]] - <Servlet.service() for servlet action threw exception>
    org.springframework.webflow.execution.repository.NoSuchFlowExecutionException: No flow execution could be found with key '_c654AC1DB-D558-B0DD-7C5D-31900A3BA54F_k0E04E495-E1AD-E335-72D9-E883B473BED4' -- perhaps this executing flow has ended or expired? This could happen if your users are relying on browser history (typically via the back button) that references ended flows.; nested exception is org.springframework.webflow.conversation.NoSuchConversationException: No conversation could be found with id '654AC1DB-D558-B0DD-7C5D-31900A3BA54F' -- perhaps this conversation has ended?
    Based on your stack trace, it appears that SpringWebFlowExceptionResolver is never coming into the picture: it's simply never called in program execution.

    I am not a Struts expert, but I believe I have an idea of what is going here. Perhaps Keith or somebody with more Struts experience can verify my assumptions.

    In struts-config.xml for the birthdate example, you have something like the following:

    Code:
    	<action-mappings>
    		<action path="/home" forward="index.jsp"/>
    		<action path="/flowAction" name="actionForm" scope="request" type="org.springframework.webflow.executor.struts.FlowAction"/>
    	</action-mappings>
    And from web.xml, you configured a Struts ActionServlet to act as your front-end controller, similar to the following:

    Code:
    	<servlet>
    		<servlet-name>action</servlet-name>
    		<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    	</servlet>
    The difference between this configuration for using Struts and the analogous configuration for using Spring MVC is that the program's flow of control passes from the Struts ActionServlet to SWF's FlowAction, which then delegates to the internals of SWF. Your FlowAction is, however, not managed by your Spring ApplicationContext. Thus, to make a long story short, when an SWF exception is thrown in FlowAction's execute() method, the unhandled exception trickles back up to the Struts ActionServlet instead of to Spring's ApplicationContext, and the globalExceptionResolver you configured never gets a chance to handle the exception.

    Make sense?! :o

    You'd probably also like a solution to your problem. So I came up with two possibilities:

    1. Custom Struts ExceptionHandler
    2. Spring's DelegatingActionProxy


    You can try them out and let us know if they work.

    I did some quick research and came across this page:

    http://www.objectsource.com/j2eechap...n_Handling.htm

    Skim down to section "18.7 Exception handling – Struts way". You'll see there that you can configure custom exception handlers (i.e., that extend org.apache.struts.action.ExceptionHandler) in action mappings in struts-config.xml. Basically, you would have to devise a way to perform the same processing provided by SpringWebFlowExceptionResolver in a custom Struts ExceptionHandler.

    But... there may be an easy way out! You might be able to use Spring's DelegatingActionProxy (see the JavaDoc for details: org.springframework.web.struts.DelegatingActionPro xy) to have your FlowAction managed by Spring's ApplicationContext. I haven't tested it, but I think/hope that would allow your globalExceptionResolver to be able to handle the exception thrown from your FlowAction.

    Good Luck!!! (and please let us know how it turns out)

    Sam

  8. #28
    Join Date
    Mar 2007
    Posts
    3

    Default handling end states in struts

    Hi Sam,
    Thanks for your quick response.
    I have been trying the Spring's DelegatingActionProxy for a while, it gives me NullPointerException. Here is what I did
    In applicationContext.xml
    Code:
    	<bean name="/flowAction"   
            class="org.springframework.webflow.executor.struts.FlowAction">
      	</bean>
    and in struts-config.xml
    Code:
     <!-- 
    		<action path="/flowAction" name="actionForm" scope="request" type="org.springframework.webflow.executor.struts.FlowAction"/>
    		-->
    		
    		<action path="/flowAction" name="actionForm" scope="request" type="org.springframework.web.struts.DelegatingActionProxy"/>
    But I keep getting the exeception
    Code:
    **** detActionBeanName /flowAction
    beanName /flowAction
    Action class org.apache.struts.action.Action
    ****** action org.springframework.webflow.executor.struts.FlowAction@998537
    ****** delegateAction org.springframework.webflow.executor.struts.FlowAction@998537
    ****** mapping ActionConfig[path=/flowAction,name=actionForm,scope=request,type=org.springframework.web.struts.DelegatingActionProxy
    ****** form org.springframework.web.struts.SpringBindingActionForm@f8e24a
    ****** request  org.apache.catalina.connector.RequestFacade@10608e6
    ****** response org.apache.catalina.connector.ResponseFacade@1325877
    2007-03-08 18:22:43,823 WARN [org.apache.struts.action.RequestProcessor] - <Unhandled Exception thrown: class java.lang.NullPointerException>
    2007-03-08 18:22:43,823 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/swf_date].[action]] - <Servlet.service() for servlet action threw exception>
    java.lang.NullPointerException
    	at org.springframework.web.struts.ActionSupport.getServletContext(ActionSupport.java:121)
    	at org.springframework.webflow.executor.struts.FlowAction.execute(FlowAction.java:217)
    	at org.springframework.web.struts.DelegatingActionProxy.execute(DelegatingActionProxy.java:113)
    	at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)
    	at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)
    	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)
    	at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    	at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:833)
    	at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:639)
    	at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1285)
    	at java.lang.Thread.run(Thread.java:595)
    I put some println in DelegatingActionProxy.java seems it got everything, from the output before exception track
    Code:
    	public ActionForward execute(
    			ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
    			throws Exception {
    
    		Action delegateAction = getDelegateAction(mapping);
    		System.out.println("****** delegateAction "+delegateAction);
    		System.out.println("****** mapping "+mapping);
    		System.out.println("****** form "+form);
    		System.out.println("****** request  "+request);
    		System.out.println("****** response "+response);
    		
    		ActionForward forward = null;
    		forward = delegateAction.execute(mapping, form, request, response);  //Exception is thrown here
                    
    		System.out.println("****** forward "+forward);
    		return forward;
    	}
    Any idea? Thanks

  9. #29
    Join Date
    Mar 2007
    Posts
    3

    Default

    Follow my previous post, I found that my Spring webApplicationContext is null, does anyone know how to set it up, so it can work together with Struts?
    Thanks

  10. #30

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •