How to enter or go to the next page in JSF flow - jsf

In normal way to enter to flow or go from some page to next page in flow we use
<h:commandButton> or <h:commandLink>
But how is it possible to enter to flow or go to the next page in flow (if we currently are in flow) from backing bean?
I try to dispatch from faces context but it doesn't work. Do you know how to do it?
I use only viewnode pages. I configure a flow using a
#FlowDefinition
#Producent
#Flowdefinition
public Flow defineFlow(#FlowbuilderParameter FlowBuilder FlowBuilder){
flowBuilder.id("","registerFlow");
flowBuilder.viewNode("registerStart","/faces/start.xhtm").Markasstartnode();
flowBuilder.viewNode("step2","/faces/step2.xhtm");
…
}
And now i would enter to flow from backing bean. Something like
FacesContext.getCurrenInstance().getExternalContext().dispatch("registerFlow");
I think possible i have to use FlowHandler from context
FlowHandler handler = FacesContext.getApplication().getFlowHandler();
handler.transition(); // and what next?
how here i can redirect user to some viewnode of flow?

Related

PrimeFaces push to OmniFaces push migration questions

Since PrimeFaces push is going to be discontinued, I started to migrate to OmniFaces push. For notification purposes it's all working as expected, but I have a chat on my application where I'm missing two things in OmniFaces:
1) Change the user of the socket on demand. I require this for private conversations. On PrimeFaces I create a channel for each conversation based on the logged users id, and I pass it to the connect method of their socket component. With OmniFaces I tried to place the socket component inside a PrimeFaces output panel, bind the user property to a view scoped bean, update the panel on a ajax request and on the oncomplete event call OmniFaces.Push.open('channelName'), but I can see on the SocketObserver class(from the showcase) that the user has not been updated. As a workaround I created the channel using the logged user id as user, and if someone different from the person that he is talking at the moment sends a message, I ignore it at the JavaScript callback instead of appending it.
2) When I don't specify the user on PushContext.send, I'd like that the message was sent to everyone connected on the channel, similar to "/channel/*" on PrimeFaces. My requirement with this is to update the list off online/offline users off this chat application. A a workaround I could create a separate channel for these notifications, but as the application don't require this to work, I preferred to check here first.
I'll add code if necessary, but first I'd like to check if these concepts are present in OmniFaces push.
Thanks
It was indeed not possible to change the <o:socket user="#{...}"> value while staying in the same JSF view (ajax updates, etc). As per issue 472, it has been improved in OmniFaces 3.2-SNAPSHOT.
Any dynamic change in value of <o:socket user="#{...}"> during any ajax request in the same JSF view will now be reflected in push behavior.
In other words, below construct will now be possible:
<h:form>
<h:selectOneMenu value="#{bean.chat}">
<f:selectItems value="#{bean.chats}" />
<f:ajax render="#form" />
<h:selectOneMenu>
...
<o:socket channel="chat" user="#{bean.chat.id}" />
</h:form>
If you start by using the user attribute on the o:socket like in the example
<o:socket channel="sess" scope="session" user="#{pushTestUser}" />
1) seems possible by using the 'user id' as can be seen in the showcase push test page
From http://showcase.omnifaces.org/push/socket:
#Inject #Push
private PushContext someChannel;
public void sendMessage(Object message, User recipientUser) {
Long recipientUserId = recipientUser.getId();
someChannel.send(message, recipientUserId);
}
In this example the pass the User which is an 'example' object that could be your own or whatever. In the showcase the user is passed on by binding the id to an input field, but that could be done server-side as well. Up to you
2) seems possible with sending messages to the generic channel or even groups as can be seen in http://showcase.omnifaces.org/push/socket.
#Inject #Push
private PushContext someChannel;
public void sendMessage(Object message, Group recipientGroup) {
Collection<Long> recipientUserIds = recipientGroup.getUserIds();
someChannel.send(message, recipientUserIds);
}
The group here is an example Object that could be your own, it could be passed from the 'frontend' or just read in the backend somewhere. It just needs to contain id's of users (can be mapped guids, does not need to be internal user id's) that are subscribed to the channel. All are just example methods.
So both seem possible in my opinion.

JSF - Redirect and pass an attribute

I have two facelets pages (login.xhtml and user-registration.xhtml). In the login page I have two forms, one for the login and another for the user registration (where I only ask for the email and password twice).
I would like to pass the email and password as attributes from the user registration form to the user-registration.xhtml page (where I ask for the rest of the user registration fields). I don't want to pass them as parameters in the GET url for security reasons.
Can I pass them as attributes while doing a redirect to the user-registration.xhtml page?
you can use this
<p:button outcome="page2" >
<f:param name="nameofData" value="theInformation"></f:param>
</p:button>
I suppose that this composant is in the page1.xhtml and the page1 and page2 are in the same folder (in case note you need to change your outcome) , and for your param you will send theInformation with a name in our case it is nameofData and you will get the informations with nameofData.
Hope that helped you

jsf spring security user info

I'm new at Spring Security. I'm using jsf2 with spring security 3. Three questions:
How can I access, from a session managed bean, the user info (name,password,roles) of the user currently logged in?
In order to use it in a view, for example for rendering elements depending on the roles of the user.
How can I know if a user is logged in? In order to show in a view a "login link" if the user is not logged in, or a "logout link" if the user is logged in. Which property of Spring Security do I have to use in my managed bean to store this info and use it in the view?
The "login link" is just a GET request to the URL of the login page. But how can I show "logout link"? Do it have to be a POST request and use "h:commandLink" like this?:
<h:commandLink value="Logout" action="#{request.contextPath}/j_spring_security_logout" />
Or can it be a GET request?:
<h:link value="Logout" outcome="#{request.contextPath}/j_spring_security_logout" />
Thank you very much in advanced.
The object authentication is who save this properties, you can obtain with next line in your managedBean:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
A user is logged if his Authentication is not a instace of AnonymousAuthenticationToken, in your spring-security-context.xml you must define the urls intercepted by Spring.
The first interceptor is not analyzed by Spring. In this case the Authentication object is an instance of AnonymousAuthenticationToken.
The second interceptor is analyzed by Spring and the user is redirected to login page declared in spring-security-context.xml
/* This is a example for to obtain the rol name for example for generate automatic menu */
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String namePrincipalRol = null;
if (auth instanceof AnonymousAuthenticationToken) {
namePrincipalRol = "ROLE_ANONYMOUS";
} else {
namePrincipalRol = auth.getAuthorities().iterator().next().getAuthority();
}
Good question, I am not sure but I think I remember having read that it must be POST, would be interesting to try. I use h:outputLink
Kind regards.

Is there any easy way to preprocess and redirect GET requests?

I'm looking for a best practise answer. I want to do some preprocessing for GET requests. So e.g. if the user is not allowed to see the page, redirect him to another page. But I don't want to use normal servlet filter, because I would like to express this behavior in the faces-config.xml. Is this possible and how is that called, how can it be done?
Can I define some Filter bean that also returns a String telling the faces-config.xml where to go next?
I googled for this but only hit on the normal filters. If I use filters, can a #WebFilter be a #ManagedBean at the same time? Or is that bad style?
If you're homegrowing HTTP request authentication on top of JSF, then a servlet filter is really the best approach. JSF is "just" a MVC framework and nothing in the JSF API is been specified to filter incoming HTTP requests to check user authentication. On normal GET requests, a JSF managed bean is usually only constructed when the HTTP response is about to be created and sent, or maybe already is been committed. This is not controllable from inside the managed bean. If the response is already been committed, you would not be able anymore to change (redirect) it. Authentication and changing the request/response really needs to be done far before the response is about to be sent.
If you were not homegrowing authentication, then you could have used the Java EE provided container managed authentication for this which is to be declared by <security-constraint> entries in web.xml. Note that this is also decoupled from JSF, but it at least saves you from homegrowing a servlet filter and a managed bean.
The general approach is to group the restricted pages behind a certain URL pattern like /app/*, /private/*, /secured/*, etc and to take the advantage of the fact that JSF stores session scoped beans as HttpSession attributes. Imagine that you've a JSF session scoped managed bean UserManager which holds the logged-in user, then you could check for it as follows:
#WebFilter(urlPatterns={"/app/*"})
public class AuthenticationFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
UserManager userManager = (session != null) ? (UserManager) session.getAttribute("userManager") : null;
if (userManager == null || !userManager.isLoggedIn()) {
response.sendRedirect(request.getContextPath() + "/login.xhtml"); // No logged-in user found, so redirect to login page.
} else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
// ...
}
If you're using JSF 2.2+, there's another way to control the response right before it is been sent. You can make use of the <f:viewAction>. Put the following somewhere in your view:
<f:metadata>
<f:viewAction action="#{authenticator.check}" />
</f:metadata>
with
#Named
#RequestScoped // Scope doesn't matter actually. The listener will always be called on every request.
public class Authenticator {
public String check() {
if (authenticated) {
return null;
}
else {
return "login?faces-redirect=true";
}
}
// ...
}
This is guaranteed to be fired before the response is to be rendered. Otherwise when you do the job in e.g. #PostConstruct, then you may risk java.lang.IllegalStateException: response already committed when the bean is created for the first time when the response has already partially been rendered (and committed).
I only wouldn't consider it to be a "best" practice when it comes to handling HTTP authentication. It makes it too tight coupled into JSF. You should really keep using a servlet filter. But for other purposes, it may be fine.
See also:
When to use f:viewAction / preRenderView versus PostConstruct?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Limitations of using a PhaseListener instead of a Servlet Filter for authorization

jsf navigation question

I have a JSF2 project with a "view user" page that reads the currently selected user from a session bean; userHandler.selectedUser.
The page is intended to be visited by navigating with links in the app.
However, if the user attempts to hit the "view user" page directly by this URL ...
http://localhost:8080/webapp/userView.jsf
... they see the page with no data on it (because there's no selected user in the userHandler).
I think what I'd like to do is redirect the user to the main page of the app if they try to hit it directly like that. What is a simple and elegant way of handling this problem?
Thanks,
Rob
You'd like to hook on the preRenderView event and then send a redirect when this is the case.
<f:metadata>
<f:event type="preRenderView" listener="#{bean.preRenderView}" />
</f:metadata>
with
public void preRenderView() throws IOException {
if (userHandler.getSelectedUser() == null) {
FacesContext.getCurrentInstance().getExternalContext().redirect("home.jsf");
}
}
A way to avoid this problem from the start is to have pages that you don't want to be accessed directly via URL into the WEB-INF folder of your project.
This way, your pages aren't accessible directly via URL.

Resources