How to add new ViewState programatically? - spring-webflow-2

I am trying to find out a way to add new ViewState while performing some action in application.
Use case :
I have a spring webflow with 2 static ViewState defined in the flow file. In the the first view there is a UI action that will add one new ViewState. I know, I can add the said ViewState in the flow but this is just a example. I have too many such cases. It was possible in earlier version of Spring webflow. But now ViewState object needs a ViewFactory instance.
How can I add new ViewState in a Flow programatically?

If the dynamic SPEL doesn't suffice then you'll have to resort to framework hacks.
The FlowModelFlowBuilder.class controls how flows are built/initialized. Extend the FlowModelFlowBuilder.class and override/add to existing methods.
http://docs.spring.io/spring-webflow/docs/current-SNAPSHOT/api/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.html
You'll probably be interested in the createFlow() method. By either overriding, adding to, or studying its functionality to inject your own "dynamic view-states" for predefined flows.
createFlow()
Factory method that initially creates the flow implementation during flow builder initialization.
Once you've implemented your own FlowBuilder you inject it in your webflow-registery config like this:
<webflow:flow-registery id="flowRegistry" flow-builder-services="someFlowBuilderService">
<webflow:flow-location-pattern value="/**/*-flow.xml"/>
<webflow:flow-builder class="com.my.package.MyCustomFlowModelFlowBuilder"/>
</webflow:flow-registery>
Disclaimer: I have personally never done this but the framework does allow you to inject your own custom FlowBuilder impl.

I think you're thinking about this problem incorrectly. You can pass variables into the 'view' attribute of a view-state tag using Spring Expression Language (SPEL) like so
<action-state id="determineWhichViewStateToRender">
<set name="flowScope.dynamicViewState" value="myService.determineWhichViewState()"/>
<set name="flowScope.modelObj" value="myService.getModelTypeForThisViewState(flowScope.dynamicViewState)"/>
<transition to="myDynamicViewState"/>
</action-state>
<view-state id="myDynamicViewState" view="#{flowScope.dynamicViewState}/edit" model="modelObj">
.....
</view-state>
and that would achieve a similar effect to "dynamic view-state" that you desire without resorting to frame work hacks.
Also, in the example modelObj can be set to initialized to any object type prior to entering the view-state.

Related

Liferay overriding JSONAction using hook

Liferay has feature to modify Struts Action using hook which is straight-forward. However I am trying to override getJSON method of RateEntryAction.
The use case is I need total positive score and total negative score instead of average score that Liferay's OOTB rating component provides.
I already have necessary methods readily available in Liferay API to get the total positive and negative scores. I created a custom type just like "stars" and "votes" to write my necessary logic in hook. I was then planning to override struts action represented by /portal/rate_enty to override the method and add negative and positive votes in the json that is already being returned.
But RateEntryAction (which is the original class) is extending JSONAction and overriding getJSON method. Is it possible to override just getJSON method using struts action hook?
I can see this action class in struts-config.xml, so it's a Struts Action.
This is the path you could try to override.
<action path="/portal/rate_entry" type="com.liferay.portal.action.RateEntryAction" />
I would try to override this path, and see if can put your logic there.
RateEntryAction extends from JSONAction , and this one from org.apache.struts.action.Action , which is the same class that PortletAction extends.
Hope this help
As per my research we can only hook com.liferay.portal.struts.PortletAction sub classes, Yeah JSONAction also extend org.apache.struts.action.Action class same as PortletAction, but liferay allow only those classes hookable which comes under PortletAction class not except that.
As RateEntryAction is not a Struts Action, you can't overload it with a Struts Action Hook. I'm not aware of any hookable way to override it, thus my best guess is that you'll have to either go for ext or introduce a whole new JSON API function and hook all places in Liferay that refer to the original implementation to now go to your implementation.
I suspect that in this case an ext plugin will be easier to maintain. Someone correct me if I'm wrong.

How exactly does p:panelGrid extends h:panelGrid

I'm using Primefaces and I know that p:panelGrid extends h:panelGrid as it's clearly stated in the documentation.
However I can't see the exact difference between them. What extra functionalities does p:panelGrid provide? In which cases should I prefer using the Primefaces version over the HTML Basic one?
Although p:panelGrid extends h:panelGrid, it actually lacks many of the attributes that h:panelGrid contains. Which ultimately got me confused.
I can't speak for PrimeFaces' actual intention (I'm no PrimeFaces developer), but based on my observations so far, I can only conclude that they omitted attributes which only invite bad practices in HTML perspective (mainly HTML-deprecated attributes — use CSS instead) or makes no sense otherwise (and are better at its place in a parent or child component). I can only say that it's a Good Thing.
Upon further inspection in the source code I can also confirm that it doesn't technically extend from <h:panelGrid> (HtmlPanelGrid class), but from the UIPanel superclass (which is also used by a.o. <h:panelGroup>). This design decision is most likely done to have more flexibility in the rendered output as shown in the showcase.
Generally, you should only prefer an enhanced component whenever you start to actually need the enhanced/new feature. This usually only happens once you figure out you actually need such one feature and discover that it is missing in the standard component. You'd then usually already know the keywords you're looking for and simply start exploring the component libraries using those keywords if they haven't already implemented it.

When to use parameterized method invocations introduced with EL 2.2 (especially in JSF 2.x )?

In the past I used a lot of getter and setter methods to move as much boolean logic as possible from facelet files to JSF backing beans.
This way, the interface of a view was given by the getter and setter methods of its backing bean as well as by the action methods of the backing bean.
An advantage of this approach is that the facelet files are rather logic-free and ,therefore, all logic is within the backing beans and can be unit tested.
But with EL 2.2 another programming style became possible. In EL 2.2 you can invoke methods with expressions like
#{bean.collection.size()},
#{bean.collection.add(elem)},
#{bean.property.substring(0, bean.property.indexOf(something))}.
Is the usage of rather complex expressions like parameterized method invocations good style now or do you rather advise against using such expressions?
Is there a rule of thumb when to use the new method invocation expressions and when not?
The major guideline is the following: reduce as much 'model' logic from the view as possible and leave only the 'view' logic. EL 2.2 made possible some model simplification and reduced the need for creation of artificial properies of JSF beans. Invocation of methods with parameters also enables to pass the necessary information from the view to the controller which would be tedious without that opportunity.
You can call arbitrary methods to access the model from the view that the view part relies on, but you should never call methods that modifies the model from the view.
Let me elaborate on that.
Some legal examples:
evaluate non-accessor methods when building view:
render UI components based on some conditions like rendered="#{request.isUserInRole('administrator')}";
make collection modifications where necessary like <ui:repeat value="#{bean.set.toArray()}" ... >
conditionally evaluate UI component / HTML element attributes like class="#{bean.name.contains('special') ? 'special' : ''}";
output non-accessor data like there are #{bean.list.size()} elements.
pass information to the controller in action methods or listeners:
execute action methods with currently iterated variables like var="data" and action="#{bean.action(data)}" with public String action(Data data);
pass additional data, like current iteration index, in listeners like varStatus="status" and actionListener="#{bean.action(status.index)}" with public String action(int index).
Some to-be-avoided examples:
use EL operators when possible:
use #{not empty bean.list} instead of #{bean.list.size() gt 0}.
use method call with parameters instead of extending the model:
use #{bean.name.contains('special')} instead of #{bean.special} with public boolean isSpecial() {return name.contains("special");}.
prefer leaving view logic in view for plain rendering of the right things and create model logic in case it applies purely to the model:
in case you need to perform some calculations to change the appearance of an object, do that in view directly without changing the model, in case some property is inherent to the model itself, introduce it directly in the model and refer to it from the view.
Some illegal examples:
modify the model from the view:
do not use EL 2.2 possibility of calling methods with parameters to break the MVC paradigm, i.e. do not call #{bean.list.add(element)} from the view side.
Of course, all things said apply to the cases that your goals don't contain targeting at the older servers without EL 2.2 support.
As a bigger picture, I'd recommend to also see BalusC's explanation of what MVC architecture represents within the context of JSF.
Personally, i prefer using "complex" EL expressions when really needed, and take any bit logic/traitement to the correspondant managed-beans.
For example: the first example you put is the only one that i may sometimes use directly, the two others however should be for me put in action methods with void/String returning type according to the need.
Use El 2.2 to reduce our JSF code, e.g. setPropertyActionListener is made redundant, see
JSF Core Tag :setPropertyActionListener vs attribute vs param

Purpose and use of properties 'action', 'actionListener', 'actionListeners'

In a button I can see three properties action, actionListener & actionListeners. I tried to use the actionListener property by creating a class implementing java.awt.event.ActionListener and implementing actionPerformed method and then calling the class using expression language. But nothing happened.
Even the documentation on these properties is cryptic. Can anyone explain how these properties are used and their purpose?
I think you need to use "javax.faces.event.actionlistener" and it uses processAction method. I assume you know though that xpages uses xp:eventHandler's instead of the vanilla JSF 1.1 attributes you mentioned.

How many ways there are to declare variables in facelets?

I noticed that c:set does not work well used inside "include of include of include", as important notice facelets documentation does't recommend it too.
Now I am using ui:param inside ui:include, but it is a bit dispersive when no attached notes about params comes with the include, is there something other way to declare "global vars"?
This is really a matter of trying to fit old JSP programming into the JSF framework. You should be using backing beans to hold your data.
If you try to hard-code data directly into your xhtml file, you are defeating the purpose of JSF's MVC framework. If you have a specific example of what you are trying to do, I could give you a specific recommendation.

Resources