All 2 entries tagged MVC
View all 5 entries tagged MVC on Warwick Blogs | View entries tagged MVC at Technorati | There are no images tagged MVC on this blog
March 21, 2006
Expert Spring MVC + Spring Web Flow errata
Writing about web page http://apress.com/book/bookDisplay.html?bID=10048
Below are the changes in Chapter 11 + Chapter 12 as a result of upgrading to Spring Web Flow 1.0 EA:
[global changes]
_flowExecutionId has been renamed to _flowExecutionKey
org.springframework.webflow.manager has been renamed to org.springframework.webflow.executor
FlowExecutionManager has been renamed to FlowExecutor
FlowExecutionManagerImpl has been renamed to FlowExecutorImpl
FlowExecutionContinuationKey has been renamed to FlowExecutionKey
FlowExecutionManagerParameterExtractor has been renamed to FlowExecutorArgumentExtractor
Chapter 11
– Figure 11–3 (page 7) has four boxes which all contain text starting "webflow.manager.". The word "manager" needs to be replaced with the word "executor", i.e the first box should read webflow.executor.struts.FlowAction etc.
– The first line of the last paragraph on page 7 refers to "FlowExecutionManager". This has been renamed to "FlowExecutor".
– Page 8 refers to "org.springframework.webflow.execution.FlowExecutionRepository". This has been renamed to "org.springframework.webflow.execution.repository.FlowExecutionRepository".
– Page 17 refers to "AbstractFlowexecutionTests" but the e after "Flow" should be capitalised: "AbstractFlowExecutionTests".
– The first two methods in Listing 11–8 are duplicates. Please remove the first method. The second method needs to change from:
protected Resource getFlowLocation() {
File flowDir = new File(.......);
return new FileSyste…..
}
to:
protected Resource getFlowLocation() {
File flowDir = new File(.......);
FileSystemResource resource = new FileSystemResource(new File(flowDir, "purchase-flow.xml"));
return new ExternalizedFlowDefinition("purchaseFlow", resource);
}
so essentially the first line stays the same, and the second line is replaced with two new lines.
– Listing 11–13 on page 22 refers to "org.springframework.webflow.manager.
mvc.FlowController" The word "manager" needs to be replaced with the word "executor".
– The next paragragh on page 22 contains a reference to "org.springframework.webflow.mvc.FlowController". This should be "org.springframework.webflow.executor.mvc.FlowController".
– Page 26 refers to " org.springframework.webflow.config.FlowBuilder". This should be "org.springframework.webflow.builder.FlowBuilder".
Chapter 12
[global and specific changes]
– Page 8, first sentence contains " org.springframework.binding.AttributeMapper". Should be "org.springframework.binding.mapping.AttributeMapper".
– Page 9, first paragraph contains "ParameterizableFlowAttributeMapper", should be DefaultFlowAttributeMapper.
– Page 9, Listing 12–9 first method signature is "public Map createSubflowInput(Request…..". Should be "public AttributeMap createSubflowInput(Request….".
First line in first method is "Map map = new HashMap()" should be "AttributeMap map = new AttributeMap()".
Second method signature is "public void mapSubflowOuput(Map subflowOutput…." should be "public void mapSubflowOutput(UnmodifiableAttributeMap…".
– Page 12, In "Integration With Web Frameworks" the term FlowExecutionManager needs to be replaced with FlowExecutor. There are 5 occurences (although any others you spot should also be changed).
The last but one sentence "Both methods accept org…... and return org…." should read "Both methods accept org.springframework.webflow.ExternalContext in their parameters and return org.springframework.webflow.executor.ResponseInstruction , from which the org.springframework.webflow.ViewSelection can be obtained."
Listing 12–11 has completely changed:
public interface ExternalContext {
public String getContextPath();
public String getDispatcherPath();
public String getRequestPathInfo();
public ParameterMap getRequestParameterMap();
public AttributeMap getRequestMap();
public SharedAttributeMap getSessionMap();
public SharedAttributeMap getApplicationMap();
public interface SharedMap extends Map {
public Object getMutex();
}
public static class SharedAttributeMap extends AttributeMap {
public SharedAttributeMap(SharedMap sharedMap) {
super(sharedMap);
}
public SharedMap getSharedMap() {
return (SharedMap)getMapInternal();
}
public Object getMutex() {
return getSharedMap().getMutex();
}
}
}
– Page 13 Last entry in Table 12–2 contains the word "manager." should be "executor."
"The FlowExecutionManager" should be renamed "FlowExecutor".
Listing 12–12 heading should be changed to "org.springframework.webflow.executor.FlowExecutor".
Both methods return "ViewSelection". They should return "ResponseInstruction".
Within the Note, "FlowExecutionManager" should be renamed to "FlowExecutor".
The next two paragraphs require all instances of "FlowExecutionManager" to be changed to "FlowExecutor". I count 2 instances
The next two paragraphs require all instances of "_flowExecutionId" to be changed to "_flowExecutionKey". I count 2 instances
The "org.springframework.webflow.executor.support.FlowExecutionManagerParameterExtractor" needs to be "org.springframework.webflow.executor.FlowExecutorArgumentExtractor".
-Page 15, Listing 12–13 Please remove the last method "rehydrate".
Listing 12–14 FlowExecutionContext has changed. It essentially needs to be:
public interface FlowExecutionContext extends FlowExecutionStatistics {
public Flow getFlow();
public AttributeMap getScope();
FlowSession getActiveSession();
}
The next paragraph contains the phrase "the active flow definition, the current state, and" which needs to be replaced with "conversation scope and".
The next paragraph contains the phrase "The root flow" which needs to be replaced with "The flow". The last sentence contains "getActiveFlow()" which needs to be "getFlow()".
Page 17, Listing 12–15 has changed. It should now be:
public interface RequestContext {
public Flow getActiveFlow() throws IllegalStateException;
public State getCurrentState() throws IllegalStateException;
public AttributeMap getRequestScope();
public AttributeMap getFlowScope();
public AttributeMap getConversationScope();
public ParameterMap getRequestParameters();
public ExternalContext getExternalContext();
public FlowExecutionContext getFlowExecutionContext();
public Event getLastEvent();
public Transition getLastTransition();
public UnmodifiableAttributeMap getAttributes();
public void setAttributes(AttributeCollection attributes);
public UnmodifiableAttributeMap getModel();
}
Page 18 contains two references to "org.springframework.webflow.manager.ConditionalFlowExecutionListenerLoader". They should be "org.springframework.webflow.executor.ConditionalFlowExecutionListenerLoader ".
Listing 12–17 on Page 18 contains a reference to "org.springframework.webflow.manager.FlowExecutionManagerImpl". It should be "org.springframework.webflow.executor.FlowExecutorImpl".
Page 19, Listing 12–18 has completely changed:
public interface FlowExecutionRepository {
public FlowExecution createFlowExecution(String flowId);
public FlowExecutionKey generateKey(FlowExecution flowExecution) throws FlowExecutionRepositoryException;
public FlowExecutionKey generateKey(FlowExecution flowExecution, Serializable conversationId) throws FlowExecutionRepositoryException;
public ConversationLock getLock(Serializable conversationId);
public FlowExecution getFlowExecution(FlowExecutionKey key) throws FlowExecutionRepositoryException;
public void putFlowExecution(FlowExecutionKey key, FlowExecution flowExecution) throws FlowExecutionRepositoryException;
public FlowExecutionKey getCurrentFlowExecutionKey(Serializable conversationId) throws FlowExecutionRepositoryException;
public ViewSelection getCurrentViewSelection(Serializable conversationId) throws FlowExecutionRepositoryException;
public void setCurrentViewSelection(Serializable conversationId, ViewSelection viewSelection) throws FlowExecutionRepositoryException;
public void invalidateConversation(Serializable conversationId) throws FlowExecutionRepositoryException;
}
– Page 22 contains a number of references to FlowExecutionContinuationKey. This has been renamed to FlowExecutionKey.
– Page 22 contains a number of references to _flowExecutionId. This has been renamed to _flowExecutionKey.
– Page 22 at the bottom contains a reference to "org.springframework.webflow.execution.repository.SimpleFlowExecutionRepository ". It should be "org.springframework.webflow.execution.repository.support.SimpleFlowExecutionRepository".
Page 23. The note should read "This is the default implementation."
Page 23 contains a reference to "_flowExecutionId", it should be "_flowExecutionKey".
Page 24 contains two references to "_flowExecutionId", they should be "_flowExecutionKey".
Page 30, Table 12–10 contains a reference to "RedirectViewSelector". Should be "ExternalRedirectSelector".
Table 12–11 is wrong, should be:
ApplicationViewSelector If viewName is specified.
ApplicationViewSelector If redirect:viewName is specified.
ExternalRedirectSelector If externalRedirect:/url?par1=x is specified
FlowRedirectSelector If flowRedrect:/url is specified
YourViewSelector If bean=yourBean is specified.
– Page 31 contains three references to "FlowExecutionManagerParameterExtractor". They should all be "FlowExecutorArgumentExtractor".
– Page 31 contains three references to "FEMPE". They should all be "FEAE".
– Page 34 contains a reference to "InvalidConversionationContinuationException". Should be "CannotContinueConversationException".
September 23, 2005
MVC Views; how stupid should they be
It seems to me that a lot of people are not utilising the full power of the "view" concept of the MVC paradigm.
For example, imagine a scenario where you want to render one page for logged in users or another for logged out users. Should this logic go in the controller, or the view? It seems the gut reaction is to put it into the controller, which I think is wrong :)
Controllers should be doing business logic, with complete disregard for how it is rendered. Controllers should not know whether they are returning html, rss etc. Of course this is naieve and it may well be that different models are required, in which case the controller has to know, but in the main, keep those MVC boundaries!
In the readonly/readwrite view example, I typically have a delegating view:
public final class PagePermissionsView implements View {
private View readView;
private View editView;
public void render(
final Map model,
final HttpServletRequest request,
final HttpServletResponse response) throws Exception {
ServletRequestAttributeAccessor accessor = new
boolean userLoggedIn = ….
if (userLoggedIn) {
editView.render(model, request, response);
} else {
readView.render(model, request, response);
}
}
public void setEditView(final View detailsView) {
this.editView = detailsView;
}
public void setReadView(final View simpleView) {
this.readView = simpleView;
}
}
This keeps view related logic firmly in the view.
Same with complicated reports. If you need to group data, a lot of developers will perform that grouping in the controller. I would rather do that in the jsp and utilise tag libraries to perform the data, for example, I very often have need of a tag which will take in a collection and return a map, where the key is the value of a property, and the value in the map is a collection of all the objects that matched.
I know exactly why developers are "afraid" to put logic into views, and that is because of the horror that was pre MVC :) But there is a difference between business logic and view logic.
A useful yardstick for any "where should this go" question is "if I need to change how this works, which layers would I need to change". If I decide to change how the view is rendered, I want to change the view, not the controller :)
Rant over; let the flames being…..