Each example I've seen for Faces Flow involves exclusive views that are only used within the particular flow. What I would like to do is create a flow that consists almost entirely of views that will be used in more than one flow, and/or potentially outside of a flow. Is this reusability of views possible, or were Faces Flows not meant to be used this way?
Faces Flow example from JavaEE 7 doc
Faces Flow is basically composed (or can be) by JSF views, being themselves reusable. If you refer to this post:
What's new in JSF 2.2 for flows ?
The flow of application is no longer restricted to flow between pages but instead defined as flow between "nodes". There are five different types of nodes:
View: Any JSF page in the application
Method Call: Invoke application logic from flow graph via an EL
Switch: Navigation decisions in the flow graph based on boolean EL
Flow Call: Call another flow with parameters and receive return values
Flow Return: Return to the calling flow
The first point itself answers your question!
EDIT FROM OP (#jdessey)
I've confirmed the accepted answer in testing, and wanted to share a few caveats in implementation.
Programmatic flow definition (i.e. #FlowDefinition annotation) is only processed if the class that contains the annotated method is itself a normal scoped CDI bean such as `#ApplicationScoped`. (Might be a bug - I'm using JSF 2.2.4 and Weld 2.0.4)
When defining the view node using FlowBuilder.viewNode(String viewNodeId, String vdlDocumentId), the document id must be the absolute path to the .xhtml file. This is in the javadoc but not intuitive IMO because since 2.0 we are used to implicit navigation.
Code:
#ApplicationScoped
public class MyFlow implements Serializable {
#Produces #FlowDefinition
public Flow defineFlow(#FlowBuilderParameter FlowBuilder flowBuilder) {
flowBuilder.id("", "myFlow");
flowBuilder.viewNode("anyView", "/absolutePathToView.xhtml").markAsStartNode();
return flowBuilder.getFlow();
}
}
Now to navigate to this flow, just use "myFlow" as an implicit navigation case such as:
<p:menuitem value="Begin Flow" action="myFlow" />
Related
I recently read this article from Neil Griffin Making Distinctions Between Different Kinds of JSF Managed-Beans and it got me thinking about the distinction between different beans in my own application. To quickly summarise the gist:
Model Managed-Bean: This type of managed-bean participates in the
"Model" concern of the MVC design pattern. When you see the word
"model" -- think DATA. A JSF model-bean should be a POJO that follows
the JavaBean design pattern with getters/setters encapsulating
properties.
Backing Managed-Bean: This type of managed-bean participates in the
"View" concern of the MVC design pattern. The purpose of a
backing-bean is to support UI logic, and has a 1::1 relationship with
a JSF view, or a JSF form in a Facelet composition. Although it
typically has JavaBean-style properties with associated
getters/setters, these are properties of the View -- not of the
underlying application data model. JSF backing-beans may also have JSF
actionListener and valueChangeListener methods.
Controller Managed-Bean: This type of managed-bean participates in
the "Controller" concern of the MVC design pattern. The purpose of a
controller bean is to execute some kind of business logic and return a
navigation outcome to the JSF navigation-handler. JSF controller-beans
typically have JSF action methods (and not actionListener methods).
Support Managed-Bean: This type of bean "supports" one or more views
in the "View" concern of the MVC design pattern. The typical use case
is supplying an ArrayList to JSF h:selectOneMenu drop-down
lists that appear in more than one JSF view. If the data in the
dropdown lists is particular to the user, then the bean would be kept
in session scope.
Utility Managed-Bean: This type of bean provides some type of
"utility" function to one or more JSF views. A good example of this
might be a FileUpload bean that can be reused in multiple web
applications.
This made sense to me and for the past few hours I have been refactoring my code and came up with the following with respect to the user login:
The AuthenticationController is an example of a Controller Managed-Bean. It is request-scoped and features two getters and setters for setting a username and password, and two navigation methods, authenticate and logout, navigating the user to either their private area upon successful login, or back to the main page when logging out.
The UserBean is an example of a Support Managed-Bean. It is session-scoped and features an instance of User class (which would be null when you are not authenticated) with a getter and setter, nothing more.
The AuthenticationController has this user as a managed property (#ManagedProperty(value = "#{userController.user} private User user;). Upon successful authentication, the AuthenticationController would set the managed property to the actual user instance with the corresponding username that was used for the login.
Any new beans would be able to grab the user as a managed property as well and pull the data they need, such as group membership for instance, if the User class would feature a list with group names.
Would this way be the proper way to go about with regard to the seperation of concerns?
This is a very subjective question. I personally disagree that article and find that it's giving really bad advice to starters.
Model Managed-Bean: This type of managed-bean participates in the "Model" concern of the MVC design pattern. When you see the word "model" -- think DATA. A JSF model-bean should be a POJO that follows the JavaBean design pattern with getters/setters encapsulating properties.
I would absolutely not make or call it a managed bean. Just make it a property of a #ManagedBean. For example a DTO or JPA #Entity.
Backing Managed-Bean: This type of managed-bean participates in the "View" concern of the MVC design pattern. The purpose of a backing-bean is to support UI logic, and has a 1::1 relationship with a JSF view, or a JSF form in a Facelet composition. Although it typically has JavaBean-style properties with associated getters/setters, these are properties of the View -- not of the underlying application data model. JSF backing-beans may also have JSF actionListener and valueChangeListener methods.
This way you keep duplicating and mapping the properties of the entity in the managed bean. This makes no sense to me. As said, just make the entity a property of the managed bean and let the input fields refer it directly like #{authenticator.user.name} instead of #{authenticator.username}.
Controller Managed-Bean: This type of managed-bean participates in the "Controller" concern of the MVC design pattern. The purpose of a controller bean is to execute some kind of business logic and return a navigation outcome to the JSF navigation-handler. JSF controller-beans typically have JSF action methods (and not actionListener methods).
This describes the #RequestScoped/#ViewScoped #ManagedBean class pretty much. Whether event listener methods are allowed or not depends on whether they are specific to the view which is tied to the bean and/or are for their job dependent on the bean's state. If they are, then they belongs in the bean. If not, then they should be a standalone implementation of any FacesListener interface, but definitely not a managed bean.
Support Managed-Bean: This type of bean "supports" one or more views in the "View" concern of the MVC design pattern. The typical use case is supplying an ArrayList to JSF h:selectOneMenu drop-down lists that appear in more than one JSF view. If the data in the dropdown lists is particular to the user, then the bean would be kept in session scope.
Fine. For application wide data like dropdown lists just use an #ApplicationScoped bean and for session wide data like logged-in user and its preferences just use a #SessionScoped one.
Utility Managed-Bean: This type of bean provides some type of "utility" function to one or more JSF views. A good example of this might be a FileUpload bean that can be reused in multiple web applications.
This makes not really sense to me. Backing beans are usually tied to single views. This sounds too much like an ActionListener implementation which is to be used by <f:actionListener> in command components to your choice. Definitely not a managed bean.
For kickoff examples of the right approach, see also:
Hello World example in Our JSF wiki page
"Bookstore CRUD" example in this answer
"Master-detail" example in this answer
JSF Service Layer
Communication in JSF 2
I'm working on a JSF webapp which purpose is to wrap a command-line program.
One of its main functionality is the ability to share a session between users (eg. for courses purpose), so that when an input is sent to an instance of the application, the output sent to every subscriber for this session.
As a result of this design, the webapp is mainly composed of a view-scoped bean which will request a controller of the command-line application.
It has also been chosen to identify a session with the URL fragment (eg. mydomain/myapp/#SESSIONID), so that anyone using the URL with the same fragment will share inputs and outputs, using its own instance of the view-scoped bean but sharing the same controller
In order to push results to all subscribers, I'm using Primefaces Push. Results are primarily text that has to be appened to the webapp's terminal, but some commands lead to the programmatic creation of a JSF component.
In order to handle this, I just render these components to a string that I send to all subscribers.
Then, I realized that in order to handle ajax requests from components (and from every subscriber), the associated UIComponent needs to be added to the UIViewRoot in the context of (don't know how to express this) each view-scope bean.
As a matter of fact, I first tried to bind a "common container" (a UIForm) to a property of the view scoped bean, in which I would put the programmatically created components, but I obviously had to face the chicken/egg issue #BalusC talks about in his blog, because the component was added again on each ajax request. Setting javax.faces.PARTIAL_STATE_SAVING to false didn't help either (I'm using MyFaces 2.2.5)
So, as somewhat of a workaround, when the controller needs to create a new component, it basically adds the id of the component to the data pushed (in a HashMap converted to Json), and all subscribers will trigger (back) a remoteCommand to its own instance of the view-scoped bean, in order to update the "common container" from its own UIViewRoot.
This does work, but I don't like this way of doing it!
So:
would it be possible to handle this kind of sharing between view-scope beans (with the same name) which are stored in different HTTP sessions? I'm refering to this answer from #BalusC... maybe playing with javax.faces.ViewState - would it even be possible?
Is there a "magical" scope for my currently-view-scoped bean I could use?
Shall I rather use a completely different design?
Thanks!
If you want share data between all your application users you can use application scope.
If you still want to use view scope, you can connect your view scope with another application scope like this:
ApplicationView appView = BeanUtil.findBean("applicationView", FacesContext.getCurrentInstance());
import javax.faces.context.FacesContext;
public class BeanUtil {
#SuppressWarnings("unchecked")
public static <T> T findBean(String beanName, FacesContext context) {
return (T) context.getApplication().evaluateExpressionGet(context,
"#{" + beanName + "}", Object.class);
}
}
I have been through this documentation on ADF declarative component but not still not clear on the intent of such a component . I want to know what is the use of this guy and what are the scenarios where such a component could become useful ? Is this related to ui:composition in JSF2.0 ?
af:declarativeComponent defines a dynamic declarative component and is used in ADF as a light weight form of encapsulating some UI logic. Think of it not as a template, but as a component that one can define without declaring a tag name (as for regular declarative components) and much lighter then a task-flow. When used you can pass parameters to such a component (including methods parameters since ADF 11.1.2). Such a component can also have a backing bean which executes in backing bean scope, so that if you have multiple instances of this component in a page you will have as many corresponding instances of the backing bean at the run-time, so the logic executed there will not interfere from one instance to another.
ADF Declarative component is composite component created using predefined ADF Faces components. It can be included in a packaged jar file and can be included in any ADF Pages or Page Fragments as a reusable component.
Example: Create a declarative component for user login
User Name [ af:InputText ]
Passwork [ af:InputText ]
SubmitButton
This component can be included in the login page in any application
I learnt how to use container authentication with JDBC realm.
I searched a lot on internet but I couldn't find anything on JSF authorization except the following article.
JSF authorization
My goal is to avoid access to protected pages using direct links and to show/hide menu items and form components based on the authenticated user privileges.
The last part can be implemented using the rendered attribute of JSF tags but before creating my own dirty and high coupled solution I wonder if there are some specific best practices or libraries that can help. in fact the number of components to be conditionally rendered is quite high and I wouldn't like to write a specific function for each of them.
Perhaps I can create for each authenticated user a map with the names (id) of all the conditionally rendered components and a single function with a String parameter (the unique name/id of the component). Is that a good idea ? What alternatives do I have ?
I wouldn't like to add to the project other general purpose frameworks such as spring for using only a small part of them (the security one).
Thanks
Filippo
With the Expression Language version in Java EE 6 you should be able to use expressions like these:
<h:inputText rendered="#{facesContext.externalContext.isUserInRole('foo')}" />
With older versions, you can create a managed bean of this form:
public class RoleMap implements Map<String, Boolean> {
public Boolean get(Object key) {
ExternalContext extCtxt = FacesContext.getCurrentInstance()
.getExternalContext();
return extCtxt.isUserInRole(key.toString());
}
//TODO: other methods; mostly throwing UnsupportedOperationException
The test can then be expression in the form:
<h:inputText rendered="#{roleMap['foo']}" />
Third party frameworks offer other options, such as the Apache Tomahawk library's visibleOnUserRole component attributes.
Take a look at Apache Shiro, a dedicated security framework (and supposedly erasier to use than Spring Security).
Let's say I've got a register page & a register confirm page. I enter user
details into the register page, navigate to the register confirm page where
I can return back to the register page if there are any mistakes.
I'm going to use view parameters to make the registration data available
from the register page to the confirm page, and vice versa.
Supposing there are 20 items of data to be moving from page to page, that's
a lot of view parameters and a lot of setPropertyActionListeners, especially
as all the data is going to end up nicely packaged in a User object.
So what I want to do is input the data on the register page into the
properties of a User record and send a reference to it to the register
confirm page. What gave me an idea was seeing the BalusC WeakHashMap
converter. This is a JSF converter which has a static weak hash map and
generates a uuid as the value for a map entry and the object reference as
the key. So by specifying this as a converter for f:viewParam you send
the uuid in the query string.
This works fine. The issue I have is that on the register page I have to
get an instance of a User class with new. Then I can do:
<h:inputText value="#{bean.user.firstname}"/>
(etc...), and pass the user instance as a view parameter. It works fine from
the register to the confirm page. The issue is that when I perform the
reverse, sending the user reference back to the register page from the
confirm page I absolutely cannot prevent the register page backing bean
from re-instantiating the user object, after the setter has been called
as a result of the view parameter.
So the converter does it's job and retrieves the User object from the
hash map, calls setUser() in the backing bean, and then I see the
constructor for the User class firing.
I've tried calling new User() from the bean constructor, in #PostConstruct,
in a preRenderView (also checking if an ajax request), but nothing I try
prevents the work of the view parameter from getting wiped out if new is
involved. I'm sure there's a simple solution but I just can't see it right
now.
I'd be grateful for any suggestions for how to solve this problem.
The issue I have is that on the register page I have to get an instance of a User class with new.
So what code is initially creating this new User instance then? If you do this in the preRenderView handler, then you can simply check for null, can't you?
If the view parameter and converter haven't done their job, user would still be null and you create a new instance. The bean constructor and #PostConstruct won't do you any good here, since they both run before the view parameter does its thing, but the preRenderView event is guaranteed to run after it.
#ManagedBean
public class Bean {
private User user;
public void onPreRenderView() {
if (user == null) {
user = new User();
}
}
}
(Something to additionally consider is that the conversation scope already does exactly what you're trying to do here. This is part of CDI not JSF, but if you're running in a Java EE 6 Web Profile compliant AS (JBoss AS 6 or 7, Glassfish V3, Resin 4, ...) you already have it. Otherwise it's just an extra jar.)
After several attempts over more than a year to find a solid long term solution
to this problem, at last! I've found one. The solution comes in the form of the
Apache Myfaces CDI extensions project, aka Myfaces CODI.
This provides additional scopes such as the #ViewAccessScoped which ensures that
if a bean is referenced by a page then it is available for that page. Also
provided is support for conversation groups. In the scenario where I want to
pass an object reference from a register page to a register confirm page, the
confirm page can just access the registerView bean directly on the next request.
Alternatively you can #Inject one bean into another and access it on the next
request, or use f:setPropertyActionListener from the source page.
Myfaces CODI works fine with Mojarra and also with ajaxified component libraries
such as primefaces. The concept is similar to what is provided by Jboss Seam,
though I've found the additional scope support to be better thought out and I've
tested this on glassfish 3.1.1 with no problems.
If you're using #ManagedBean and scope annotations from the javax.faces.bean
package in your code, codi intercepts these annotations and uses it's own
CDI based versions, so you can convert to CDI simply by adding codi as a
dependency to your project and not changing any code.
For me this is like moving from black and white TV to colour TV, I wish I'd
found this stuff sooner.
CODI documentation