Spring Web Flow Passing Model Object from Flow to Controller
What is the proper way to pass a model object used in Spring W开发者_开发知识库eb Flow to a Controller?
My use case is as follows:
I have a flow and the end state displays a model object that contains some calculated results. That works good. I also have a link on the page to generate a pdf to display the results. That too works fine if I manually set the model object.
So how do I get the model object used in the flow to the controller? Or is there a cleaner way to view pdfs using webflow?
Thanks
There unfortunately is not an easy way to do this. Webflow maintains all objects and their states at different times within its own repository. So a model object at e1s2 will be a different physical object then e1s3 and so forth.
The easiest way I can think of is to store the object in the session as part of an end step. You can then redirect the user to the controller and get/remove the object from the session.
The alternative is to actually save the results in some persistent store (database for instance) and the link can have an ID which will allow you to pull the information and regenerate the results (if possible)
Edit: Because placing flow control objects in the session can become an annoying process to involve yourself in this may not be the best solution, but here is an example on how to do it:
public class MainFlowController{
...rest of the flow's logic
public void endFlow(RequestContext context){
ModelObject obj = ...;
HttpServletRequest req = (HttpServletRequest )context.getExternalContext().getNativeRequest();
req.getSession().setAttribute("endModelObject",obj );
}
}
Here you are assigning the ModelObject to the session and would need to pull it back with endModelObject
The RequestContext is a webflow owned object and you would pass in this will get you the pdf byte array into the session. You can assign that using the action-state
element from webflow
<action-state id="setPDF">
<evaluate expression="mainFlowController.endFlow(flowRequestContext)"/>;
<transition to="endFlow"/>
</action-state>
<end-state id="endFlow" view="end.jsp"/>
Since its now in the session the link would have to hit the controller you want and pull from the session directly.
@John V. thank you your post did help me in the right direction. This is what I have working now:
in my flow.xml
<view-state id="summary" view="summary.jsp">
<on-entry>
<set name="result" value="conversationScope.result" />
<evaluate expression="printPDF" />
</on-entry>
<transition on="startOver" to="startOver" />
</view-state>
in my webflowContext.xml file
<bean id="printPDF" class="com.example.actions.PrintPDF"/>
PrintPDF.class
public class PrintPDF extends AbstractAction {
@Override
public Event doExecute(RequestContext context) {
Result obj = (Result)context.getFlowExecutionContext().getConversationScope().get("result");
HttpServletRequest req = (HttpServletRequest) context.getExternalContext().getNativeRequest();
req.getSession().setAttribute("result", obj);
return success();
}
}
in my controller
@RequestMapping(method=RequestMethod.GET, value="/pdf")
public ModelAndView showPDF(ModelMap model, HttpServletRequest request) {
Result result = (Result)request.getSession().getAttribute("result");
model.addAttribute("result", result);
return new ModelAndView("PDF", model);
}
PDF is defined as a bean in my spring-pdf-views.xml file
<bean id="PDF" class="com.example.view.PDF">
<property name="url" value="/pdf/example.pdf" />
</bean>
That class contains the following:
public class PDF extends AbstractPdfStamperView {
@Override
protected void mergePdfDocument(Map<String, Object> model, PdfStamper stamper,
HttpServletRequest request, HttpServletResponse response) throws Exception {
Result result = (Result)model.get("result");
AcroFields form = stamper.getAcroFields();
//map form fields
and finally the jsp has a link like
<a href="/pdf.html">
I hope that can help someone else. I am not sure if that is the most efficient way of doing it but I am open to any suggestions.
精彩评论