|
|
Search on blog
Petition by Java EE Guardians
marți, 29 martie 2016
luni, 28 martie 2016
JSF 2.3 Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
You also may like:
WebSocket integration by Arjan Tijms
JSF 2.3 - The WebSocket Quickstart under Payara
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
In order to understand how this upload is implemented, you have to be familiar with the following article: JSF 2.2 Multiple File Upload with HTML 5 and AJAX.
WebSocket integration by Arjan Tijms
JSF 2.3 - The WebSocket Quickstart under Payara
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
In order to understand how this upload is implemented, you have to be familiar with the following article: JSF 2.2 Multiple File Upload with HTML 5 and AJAX.
The source code from the above article was modified to support a
progress bar via the JSF 2.3 web sockets. The main modifications implies:
- add <f:websocket/>
in page
Note: In production, this
web socket should be adjusted to distinguish between users there are login (in case that you have this feature) via
the optional user
attribute (e.g. you can use: user="#{request.remoteUser}") - this is needed for sending messages to a single login user, the one
who initiated the upload. In the form below, JSF will push messages to to the current view only. You can also set scope="session" and push messages to all
views in the current user session only. But we don't take into account if the user is login or not!
<f:websocket
channel="upload" onmessage="socketListener" scope="view"
/>
Notice that this web socket it is automatically open when you start the application and it is not explictly closed. If you want to accomplish such features please read further JSF 2.3 - Explicitly open/close a websocket channel.
- provide a div
where the upload progress is displayed (we display the percent as: x%), but you can choose to implement a
visual progress bar:
<div
id="progressBarId">0 %</div>
- provide the JavaScript listener for processing the incoming messages:
function
socketListener(message, channel, event) {
document.getElementById("progressBarId").innerHTML
= message + "%";
}
- on server-side, in UploadBean,
you have to inject the PushContext
via @Push annotation
on the given channel name (upload):
@Inject
@Push(channel =
"upload")
private
PushContext push;
- and, finally, push the messages during upload:
push.send((totalReadSize
* 100) / totalSize);
Below, you can see a possible output:
The complete application is available here.
JSF 2.3 - Firing one-time push when the web socket channel has been opened
Read also:
WebSocket integration by Arjan Tijms
In this post, we want to write an application that uses a web socket to "say" Hello world! - pushes the Hello World! message to a channel named hello. This should take place automatically (when the channel has been opened) and one-time only.
WebSocket integration by Arjan Tijms
JSF 2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
In this post, we want to write an application that uses a web socket to "say" Hello world! - pushes the Hello World! message to a channel named hello. This should take place automatically (when the channel has been opened) and one-time only.
Since a web socket channel is automatically opened, we don't need to
put any effort in this step. We just define in page a simple web socket like
below:
<f:websocket
channel="hello" onmessage="socketListener" />
Note: In such cases, we should use this together with the optional user attribute of <f:websocket/> to push the message to a specific user that it is login. Moreover, we can use the optional scope attribute set to session (push messages to all views in the current user session only) or view (push messages to to the current view only). In such cases, the CDI managed bean should be annotated with the CDI @SessionScoped respectively @ViewScoped. Since we just want to show the technique of firing one-time push when the web socket channel has been opened, we will not "pollute" the code and we will use the application scope.
Note: In such cases, we should use this together with the optional user attribute of <f:websocket/> to push the message to a specific user that it is login. Moreover, we can use the optional scope attribute set to session (push messages to all views in the current user session only) or view (push messages to to the current view only). In such cases, the CDI managed bean should be annotated with the CDI @SessionScoped respectively @ViewScoped. Since we just want to show the technique of firing one-time push when the web socket channel has been opened, we will not "pollute" the code and we will use the application scope.
Since this channel should "transport" a single message, we need to close
the channel after receiving the first message, like below:
<div
id="helloId"></div>
<script
type="text/javascript">
function socketListener(message, channel,
event) {
document.getElementById("helloId").innerHTML = message;
jsf.push.close("hello");
}
</script>
Further, we have an application bean capable to push the message to hello channel:
@Named
@ApplicationScoped
public class
PushBean implements Serializable {
@Inject
@Push(channel = "hello")
private PushContext push;
public void pushAction() {
push.send("Hello world!");
}
}
The only aspect that we didn't cover so far refers to pushing the
message automatically when the channel has been opened. For this, we can use two
server events:
CDI WebsocketEvent
will be fired with @WebsocketEvent.Opened qualifier
This event is fired when a web socket channel has been opened.
CDI WebsocketEvent
will be fired with @WebsocketEvent.Closed qualifier
This event is fired when a web socket channel has been closed.
Both events can be observed in an application scoped CDI bean as below.
So, in our case we can take advantage of the event fired when the web socket
channel has been opened and push the Hello world! message:
@ApplicationScoped
public class
WebsocketObserver {
private static final Logger LOG =
Logger.getLogger(WebsocketObserver.class.getName());
@Inject
private PushBean pushBean;
public void onOpen(@Observes @Opened
WebsocketEvent event) {
pushBean.pushAction();
}
public void onClose(@Observes @Closed
WebsocketEvent event) {
String channel = event.getChannel();
LOG.log(Level.INFO, "Channel {0} was
successfully closed!", channel);
}
}
Notice that via the WebsocketEvent
object we can obtain information such as:
Returns a string representing the <f:websocket/> channel name:
event.getChannel();
Returns
a string representing the <f:websocket/> user:
event.getUser();
Returns a CloseCode instance
representing the close reason code:
event.getCloseCode();
Now, our application output will be like in figure below:
The complete application is available here.
duminică, 27 martie 2016
JSF 2.3 - Conditionally open/close a websocket channel
Read also:
JSF
2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
In this post, you will see how to conditionally open/close a channel.
In order to accomplish this, we place the condition on the connected attribute
via a ValueExpression.
This attribute (condition) will be evaluated at each AJAX request, and if the
value of this EL expression becomes false during an AJAX request then the push connection
will explicitly be closed during oncomplete
of that AJAX request.
In the JSF 2.3 - The WebSocket Quickstart under
Payara post, we are pushing a message that indicates the current server
time in format, hh:mm:ss. Let's re-write that example for limiting the pushing
service only between 8-9 AM (PM).
The relevant part of the JSF page will look like this (notice the connected attribute at
work):
<h:form>
<h:commandButton value="Clock"
action="#{pushBean.clockAction()}">
<f:ajax render="@form"/>
</h:commandButton>
Service status:
<h:outputText
value="#{pushBean.info}"/>
</h:form>
<f:websocket
channel="clock"
connected="#{pushBean.connected}"
onopen="websocketOpenListener"
onclose="websocketCloseListener"
onmessage="socketListener" />
On server-side we implement the condition logic as follows:
@Named
@ApplicationScoped
public class
PushBean implements Serializable {
private static final Logger LOG =
Logger.getLogger(PushBean.class.getName());
@Inject
@Push(channel = "clock")
private PushContext push;
private boolean connected;
private String info;
private String time;
private void pingClock() {
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
connected = (hour >= 8) && (hour < 9);
if (connected) {
time = now.get(Calendar.HOUR_OF_DAY) +
":"
+ now.get(Calendar.MINUTE) +
":" + now.get(Calendar.SECOND);
info = "Service is available";
} else {
time = null;
info = "Service is available only
between 8-9 AM/PM";
}
}
public void clockAction() {
pingClock();
if
(time != null) {
LOG.log(Level.INFO, "Time: {0}",
time);
push.send(time);
}
}
public boolean isConnected() {
return connected;
}
public void setConnected(boolean connected) {
this.connected = connected;
}
public String getInfo() {
return info;
}
}
So, the connected
attribute will be set initially to false (default it is true meaning auto-connect). Furthermore, the
attribute is evaluated to true
only between the 8:00:00 - 8:59:59 server-time. This means that the first AJAX
request that take place after 8:00:00 and before 8:59:59 will open the connection,
while the first AJAX request that take place after 8:59:59 will close the
connection.
The figures below shows a flow of usage:
-request fired before 8:00:00
-request fired after 8:00:00 opens the connection
- between 8:00:00 and 8:59:59 the connection is open
-after 8:59:59, the first request close the connection
The complete application is available here.
vineri, 25 martie 2016
JSF 2.3 - Explicitly open/close a websocket channel
Before you read this post I recommend you to read:
JSF
2.3 - The WebSocket Quickstart under Payara
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
In this post, you will see how to explicitly open/close a channel. By
default, a channel is automatically open when we start the application, but
this is not always the desired behavior. As a consequence, first we need to
instruct JSF to not open our channel automatically, and for this we set the
optional channel
attribute to false.
This attribute can be a javax.el.ValueExpression
that must be evaluated to boolean,
and by default it is set to true.
<f:websocket
channel="clock" connected="false" onmessage="socketListener"
/>
This attribute is re-evaluated on every AJAX request, but since we have
set it to false,
our channel will never be connected. This give us the freedom to open/close the
channel explicitly via JavaScript functions:
jsf.push.open("channelName") - explicitly open
a channel
jsf.push.close("channelName") - explicitly close
a channel
Since these are JavaScript functions they can be invoked exactly as any
other JavaScript function. For example, you can invoke them from a snippet of
JavaScript, or from the onclick
event of a button, as below:
<h:form>
<h:commandButton value="Open
channel" onclick="jsf.push.open('clock')">
<f:ajax />
</h:commandButton>
<h:commandButton value="Close
channel" onclick="jsf.push.close('clock')">
<f:ajax />
</h:commandButton>
<h:commandButton value="Clock"
action="#{pushBean.clockAction()}">
<f:ajax />
</h:commandButton>
</h:form>
Moreover, we may want to be informed when the channel is open/close.
For this, we can attach two special JavaScript listeners, as follows:
<f:websocket
channel="clock" connected="false"
onopen="websocketOpenListener"
onclose="websocketCloseListener"
onmessage="socketListener" />
The optional onopen
and onclose
attributes are javax.el.ValueExpression
that must be evaluated to String.
These Strings represents the JavaScript listener functions that are invoked when the web socket
is opened/closed. The JavaScript listener corresponding to onopen will receive a
single argument represented by the channel name. The JavaScript listener
corresponding to onclose
will be invoked with three arguments: the close reason code, the channel name
and the raw CloseEvent
itself. Since this function is invoked on errors also, it is a good practice to
have it around. Below, you can see two dummy implementation of our listeners:
function
websocketOpenListener(channel) {
alert("Channel " + channel + "
was successfully open!");
}
function
websocketCloseListener(code, channel, event) {
if (code == -1) {
//
Web sockets not supported by client.
alert("Web sockets not supported by
client");
} else if (code == 1000) {
// Normal close (as result of expired
session or view).
alert("The channel " + channel + " was successfully
closed");
} else {
// Abnormal close reason (as result of an
error).
alert("The channel " + channel +
" was abnormally closed");
}
}
Now, the interface will look like in figure below:
Explicitly open the channel
Use the opened channel
Explicitly close the channel
When you run the application, you can notice that the Clock button will not
"work" until the channel is opened, and will not "work"
after the channel is closed. This means that you are controlling the channel
status explicitly via Open
channel and Close
channel buttons.
The complete application is available here.
JSF 2.3 - The WebSocket Quickstart under Payara
Read also:
WebSocket integration by Arjan Tijms
JSF 2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
Starting with JSF 2.3-m05 we can take advantage of a brand new feature - register a web socket push connection in client side. Thanks to the JSF team (especially to Bauke Scholtz (aka BalusC)) this feature is available in today milestone via <f:websocket/> tag.
WebSocket integration by Arjan Tijms
JSF 2.3 - Explicitly open/close a websocket channel
JSF 2.3 - Conditionally open/close a websocket channel
JSF 2.3 - Firing one-time push when the web socket channel has been opened
JSF 2.3 - Multiple File Upload with HTML 5, AJAX and upload progress bar via web sockets
Starting with JSF 2.3-m05 we can take advantage of a brand new feature - register a web socket push connection in client side. Thanks to the JSF team (especially to Bauke Scholtz (aka BalusC)) this feature is available in today milestone via <f:websocket/> tag.
In this post, let's see a minimal
usage of <f:websocket/> tag.
In JSF page, we need to add the <f:websocket/> tag with its two
required attributes:
·
channel
- This is javax.el.ValueExpression
that must be evaluated to String
and it represents the name of the web socket channel. A channel name is
restricted to alphanumeric characters, hyphens, underscores and periods. A
channel can have multiple open web sockets, and each of these sockets will
receive the same push notification from the server.
·
onmessage
- This is javax.el.ValueExpression
that must be evaluated to String
and it represents the a JavaScript listener function that is automatically invoked
when a push notification is received from the server.
The signature of the listener function for onmessage is of type:
function fooListener(message, channel, event)
{
// message - the message pushed by the server
// channel - the channel name
// event - the raw MessageEvent instance
}
So, a simple <f:websocket/>
tag usage will look like this:
<f:websocket
channel="clock" onmessage="socketListener" />
<div
id="clockId"></div>
<script
type="text/javascript">
function socketListener(message, channel,
event) {
document.getElementById("clockId").innerHTML += message +
"<br/>";
}
</script>
By default, when we start the application, the web socket is automatically
connected and open. As long as the document is open the web socket is open. When
the document is unloaded the web socket is automatically closed. In the web
socket is initially successfully connected but the connection is closed as a
result of e.g. a network error or server restart, JSF will try to auto-reconnect
it at increasing intervals.
Now, let's focus on the server side. Here we have to take into account
the push messages mechanism. This mechanism is based on javax.faces.push.PushContext interface
and javax.faces.push.Push
API.
First, you need to know that by default the web socket is application
scoped. This means that the managed bean that can push messages to this web
socket must be in application scope (annotated with @ApplicationScope). In this case, the
push message can be sent by all users and the application itself.
Furthermore, you have to inject PushContext via @Push annotation on the given channel name in
any CDI/container managed artifact. For example:
@Inject
@Push(channel =
"clock")
private
PushContext push;
Finally, we need to write an action method capable to push messages to
web socket via PushContext.
For example:
public void
clockAction(){
Calendar now = Calendar.getInstance();
String time = now.get(Calendar.HOUR_OF_DAY) +
":" +
now.get(Calendar.MINUTE) +
":" +
now.get(Calendar.SECOND);
LOG.log(Level.INFO, "Time: {0}",
time);
push.send(time);
}
Let's glue everything together. First, the JSF page:
<h:body>
<h:form>
<h:commandButton value="Clock"
action="#{pushBean.clockAction()}">
<f:ajax />
</h:commandButton>
</h:form>
<f:websocket channel="clock"
onmessage="socketListener" />
<hr/>
<div id="clockId"></div>
<script
type="text/javascript">
function socketListener(message, channel, event) {
document.getElementById("clockId").innerHTML += message +
"<br/>";
}
</script>
</h:body>
Next, our simple CDI bean:
@Named
@ApplicationScoped
public class
PushBean implements Serializable {
private static final Logger LOG =
Logger.getLogger(PushBean.class.getName());
@Inject
@Push(channel = "clock")
private PushContext push;
public void clockAction(){
Calendar now = Calendar.getInstance();
String time = now.get(Calendar.HOUR_OF_DAY) +
":" +
now.get(Calendar.MINUTE) +
":" + now.get(Calendar.SECOND);
LOG.log(Level.INFO, "Time: {0}",
time);
push.send(time);
}
}
In order to avoid an error as in figure below (from Payara), we need to add a fake endpoint:
As BalusC pointed out, this fake endpoint should look like below:
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.Session;
public class FakeEndpoint extends Endpoint {
@Override
public void onOpen(Session session, EndpointConfig config) {
// https://java.net/jira/browse/WEBSOCKET_SPEC-240
}
}
Update provided by Arjan Tijms
"Nevertheless, the GlassFish/Tyrus seems to be the only implementation that do not support adding an EndPoint dynamically, so JSF team have added an SPI jar for Tyrus in GlassFish, that negates the need for the fake end point. See https://github.com/jsf-spec/mojarra/tree/master/spi. As far as we know the fake endpoint is also only needed for Tyrus, not for the other WebSocket implementations (such as the one in Tomcat)."
Finally, the m05 requires the following settings in web.xml:
<context-param>
<param-name>javax.faces.ENABLE_CDI_RESOLVER_CHAIN</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name>
<param-value>true</param-value>
</context-param>
Done! The complete application was tested under Payara server and it is available here.
joi, 10 martie 2016
luni, 7 martie 2016
JSF Navigation Tutorial - Declarative Navigation
Check also:
The three golden rules of use
JSF Navigation Tutorial - Implicit Navigation
JSF Navigation Tutorial - Conditional Navigation
JSF Navigation Tutorial - Preemptive Navigation
JSF Navigation Tutorial - Programmatic Navigation
JSF VS Series: Implicit Navigation VS Declarative (explicit) Navigation
Declarative navigation refers to defining the navigation cases in faces-config.xml via a bunch of dedicated tags. Before implicit navigation, this was the only way to navigate after an action. These days the implicit navigation is available, so declarative navigation is considered obsolete (officially speaking they are not obsolete or deprecated!). But, since this is a navigation tutorial we cannot simply ignore declarative navigation, therefore let's have a quick intro and some examples.
The three golden rules of use
JSF Navigation Tutorial - Implicit Navigation
JSF Navigation Tutorial - Conditional Navigation
JSF Navigation Tutorial - Preemptive Navigation
JSF Navigation Tutorial - Programmatic Navigation
JSF VS Series: Implicit Navigation VS Declarative (explicit) Navigation
Declarative navigation refers to defining the navigation cases in faces-config.xml via a bunch of dedicated tags. Before implicit navigation, this was the only way to navigate after an action. These days the implicit navigation is available, so declarative navigation is considered obsolete (officially speaking they are not obsolete or deprecated!). But, since this is a navigation tutorial we cannot simply ignore declarative navigation, therefore let's have a quick intro and some examples.
In order to navigate, JSF needs the well-known coordinates: view ID,
logical outcome and/or action expression signature. Only that this time they
are described in the faces-config.xml
descriptor using XML-based rules, as follow:
<navigation-rule/>
This tag wraps the navigation cases of a specific view ID.
<from-view-id/>
This is a child of <navigation-rule/>
and it defines the view ID from which we navigate.
<navigation-case/>
This is a child of <navigation-rule/>
and it wraps a single navigation case characterized by view ID, logical outcome
and/or action expression signature. There can be multiple navigation cases.
<from-outcome/>
This tag is a child of <navigation-case/>
and represents the logical outcome.
<from-action/>
This tag is a child of <navigation-case/>
and represents an action expression signature (optional).
<to-view-id/>
This tag is a child of <navigation-case/>
and represents the view ID that resolve the logical outcome and/or action
expression signature.
<redirect/>
This tag is a child of <navigation-case/>
and instructs JSF that the navigation should be accomplish via PRG. By default,
JSF will navigate via POST request based in forward mechanism.
For example, check the below navigation items:
<h:link
value="Success" outcome="success"/>
<h:button
value="Success" outcome="success"/>
<h:commandButton
value="Success" action="success"/>
<h:commandLink
value="Success" action="success"/>
The declarative version of this is as follows—thanks to implicit
navigation, this code
is not needed:
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Let's see some more examples. The managed bean used in the next
examples is listed first and the application is named DeclarativeNavigation:
@Named
@RequestScoped
public class
TheBean {
private static final Logger LOG =
Logger.getLogger(TheBean.class.getName());
public String theActionWithDoneOutcome() {
LOG.info("TheBean#theActionWithDoneOutcome()
called ...");
return "done";
}
public String theActionWithOutcomeForSuccess()
{
LOG.info("TheBean#theActionWithOutcomeForSuccess()
called ...");
return
"doneFromTheActionWithOutcome";
}
public String theActionWithOutcomeForFailure()
{
LOG.info("TheBean#theActionWithOutcomeForFailure()
called ...");
return
"doneFromTheActionWithOutcome";
}
public String
theActionWithRedirectForSuccess() {
LOG.info("TheBean#theActionWithRedirectForSuccess()
called ...");
return
"doneFromTheActionWithRedirect";
}
public String
theActionWithRedirectForFailure() {
LOG.info("TheBean#theActionWithRedirectForFailure()
called ...");
return
"doneFromTheActionWithRedirect";
}
}
FIRE A JSF GET REQUEST AND NAVIGATE TO THE VIEW
ID COMPUTED FROM THE SPECIFIED OUTCOME
JSF will interpret the outcome value of <h:link/>/<h:button/> as the targeted page name (done becomes success.xhtml
via declarative navigation)
<h:link value="Click me!"
outcome="done"/>
<h:button value="Click me! "
outcome="done"/>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>done</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
FIRE A JSF GET REQUEST. PROVIDE THE NAVIGATION
OUTCOME VIA A SERVER-SIDE METHOD CALLED DURING COMPUTING THE VIEW ID (AT
RENDERING TIME)
JSF will interpret the outcome value of <h:link/>/<h:button/> as the targeted page name (done returned by theActionWithDoneOutcome() becomes success.xhtml
via declarative navigation)
<h:link value="Click me!"
outcome="#{theBean.theActionWithDoneOutcome()}"/>
<h:button value="Click
me!" outcome="#{theBean.theActionWithDoneOutcome()}"/>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>done</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
FIRE (SUBMIT) A POST REQUEST VIA FORWARD
MECHANISM AND NAVIGATE TO THE VIEW ID COMPUTED FROM THE SPECIFIED OUTCOME
JSF will interpret the action value of <h:commandLink/Button/> as the targeted page name (done becomes success.xhtml
via declarative navigation)
<h:form>
<h:commandLink value="Click Me!"
action="done"/>
<h:commandButton value="Click
Me!" action="done"/>
</h:form>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>done</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
FIRE (SUBMIT) A POST REQUEST VIA REDIRECT
MECHANISM AND NAVIGATE TO THE VIEW ID COMPUTED FROM THE SPECIFIED OUTCOME
The presence of <redirect/> in navigation case will instruct JSF to rely on POST-redirect-GET
(PRG) navigation pattern
<h:form>
<h:commandLink value="Click Me!"
action="doneredirect"/>
<h:commandButton value="Click
Me!" action="doneredirect"/>
</h:form>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>doneredirect</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
FIRE (SUBMIT) A POST REQUEST VIA FORWARD
MECHANISM. INVOKE AN ACTION METHOD AND NAVIGATE TO THE VIEW ID COMPUTED BASED
ON THE OUTCOME RETURNED BY THIS METHOD
The action can
point to an action method that returns a String. This
string is considered the outcome and it will be interpreted as the targeted
page name (doneFromtheActionWithOutcome becomes success/failure.xhtml via declarative navigation)
// theActionWithOutcomeForSuccess()
→ doneFromTheActionWithOutcome → success.xhtml
<h:form>
<h:commandLink value="Click Me!"
action="#{theBean.theActionWithOutcomeForSuccess()}"/>
<h:commandButton value="Click
Me!" action="#{theBean.theActionWithOutcomeForSuccess()}"/>
</h:form>
// theActionWithOutcomeForFailure()
→ doneFromTheActionWithOutcome → failure.xhtml
<h:form>
<h:commandLink value="Click Me!"
action="#{theBean.theActionWithOutcomeForFailure()}"/>
<h:commandButton value="Click Me!"
action="#{theBean.theActionWithOutcomeForFailure()}"/>
</h:form>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>doneFromTheActionWithOutcome</from-outcome>
<from-action>#{theBean.theActionWithOutcomeForSuccess()}</from-action>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>doneFromTheActionWithOutcome</from-outcome>
<from-action>#{theBean.theActionWithOutcomeForFailure()}</from-action>
<to-view-id>/failure.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
FIRE (SUBMIT) A POST REQUEST VIA REDIRECT
MECHANISM. INVOKE AN ACTION METHOD AND NAVIGATE TO THE VIEW ID COMPUTED BASED
ON THE OUTCOME RETURNED BY THIS METHOD
The presence of <redirect/> in navigation case will instruct JSF to rely on
POST-redirect-GET (PRG) navigation pattern
// theActionWithRedirectForSuccess()
→ doneFromTheActionWithRedirect → success.xhtml
<h:form>
<h:commandLink value="Click Me!"
action="#{theBean.theActionWithRedirectForSuccess()}"/>
<h:commandButton value="Click
Me!" action="#{theBean.theActionWithRedirectForSuccess()}"/>
</h:form>
// theActionWithRedirectForFailure()
→ doneFromTheActionWithRedirect → failure.xhtml
<h:form>
<h:commandLink value="Click Me!"
action="#{theBean.theActionWithRedirectForFailure()}"/>
<h:commandButton value="Click Me!"
action="#{theBean.theActionWithRedirectForFailure()}"/>
</h:form>
Declaratively, we have:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>doneFromTheActionWithRedirect</from-outcome>
<from-action>#{theBean.theActionWithRedirectForSuccess()}</from-action>
<to-view-id>/success.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>doneFromTheActionWithRedirect</from-outcome>
<from-action>#{theBean.theActionWithRedirectForFailure()}</from-action>
<to-view-id>/failure.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
The complete application is available here.
Abonați-vă la:
Postări
(
Atom
)
|
[JSF Page Author Beginner's Guide] |
Postări populare
-
If you like this article, I think you are going to like JSF 2.3 Tutorial as well.
-
Starting with JSF 2.3 the JSF "native" managed bean annotations are officially deprecated. So, there is no doubt now that CDI is ...
-
[OmniFaces utilities] The getRequestURL() method returns the HTTP request URL with query string, regardless of any forward. This is the f...
-
Let's checkout a common practice for declaring constants in Java using the public static final declaration: public class Circle { ...
-
[OmniFaces utilities] The getActionExpressionsAndListeners() method returns a list of all action expressions and listeners associated wit...
-
[OmniFaces utilities] The getCurrentActionSource() method returns the source of the currently invoked action, or null if there is none, ...
-
Before you read this post please read: Use a CDI alternative as a mock implementation for a stateless session bean So, since you are fa...
-
Starting with JSF 2.3, more exactly with m07 , we can take advantage of using the auto detection of convertors based on 1st UISelectMany it...
-
[OmniFaces utilities] The isSerializable() method returns true if the given object is serializable. Method: Usage: Example 1 - te...
-
[OmniFaces utilities] The reverseArray() function returns a copy of the array with items in reversed order. Function: Usage: Let...
OmniFaces/JSF Fans
-
▼
2016
(
96
)
-
▼
martie
(
15
)
- What Is PrimeFaces? on developer.com
- JSF 2.3 Multiple File Upload with HTML 5, AJAX and...
- JSF 2.3 - Firing one-time push when the web socket...
- JSF VS Series: @ManagedBean VS @Named
- JSF VS Series: Forward VS Redirect
- JSF 2.3 - Conditionally open/close a websocket cha...
- JSF 2.3 - Explicitly open/close a websocket channel
- JSF 2.3 - The WebSocket Quickstart under Payara
- JavaServer Faces 2.3 Quick Reference
- JSF VS Series: Implicit Navigation VS Declarative ...
- JSF Navigation Tutorial - Declarative Navigation
- [OmniFaces utilities (2.3)] Get the Internet Proto...
- JSF VS Series: The <f:event preRenderView/> VS <f:...
- [OmniFaces utilities (2.3)] Remove server side JSF...
- JSF built-in debug component
-
▼
martie
(
15
)
-
►
2015
(
516
)
- ► septembrie ( 38 )
JSF/OmniFaces Resources |