Refresh JSF/PF component from scheduled bean / timer [duplicate] - jsf

When we create a JSF page, a client request allows generation of HTML dynamically using a combination of Java code and HTML.
Can we introduce hooks in the HTML page using JSF framework, that allow server to update the HTML page based on asynchronous events occurring later at the server, usually via different threads?

JSF 2.3+
You can use #Push and <f:websocket> for this. Below is a kickoff example which updates a data table upon an application scoped event fired by the backend.
<h:dataTable id="notifications" value="#{bean.notifications}" var="notification">
<h:column>#{notification.message}</h:column>
</h:dataTable>
<h:form>
<f:websocket channel="push">
<f:ajax event="updateNotifications" render=":notifications" />
</f:websocket>
</h:form>
#Named #ApplicationScoped
public class Bean {
private List<Notification> notifications;
#Inject
private NotificationService service;
#Inject #Push
private PushContext push;
#PostConstruct
public void load() {
notifications = service.list();
}
public void onNewNotification(#Observes Notification newNotification) {
notifications.add(0, newNotification);
push.send("updateNotifications");
}
public List<Notification> getNotifications() {
return notifications;
}
}
#Stateless
public class NotificationService {
#Inject
private EntityManager entityManager;
#Inject
private BeanManager beanManager;
public void create(String message) {
Notification newNotification = new Notification();
newNotification.setMessage(message);
entityManager.persist(newNotification);
beanManager.fireEvent(newNotification);
}
public List<Notification> list() {
return entityManager
.createNamedQuery("Notification.list", Notification.class)
.getResultList();
}
}
JSF 2.2-
If you're not on JSF 2.3 yet, you need to head to 3rd party JSF libraries.
OmniFaces has <o:socket> (JSR356 WebSocket + CDI)
PrimeFaces has <p:socket> (Atmosphere)
ICEfaces has ICEpush (long polling)
Noted should be that the <o:socket> was the basis for the JSF 2.3 <f:websocket>. So if you have found a lot of similarities, then that's correct.
PrimeFaces uses Atmosphere under the hoods (which is troublesome to setup without Maven). Atmosphere supports websockets with fallback to SSE and long polling. ICEfaces is based on ancient long polling technique. All of those do not implement native JSR356 WebSocket API which was only later introduced in Java EE 7.
OmniFaces uses native JSR356 WebSocket API (supported in all Java EE 7 servers and Tomcat 7.0.27+). It is therefore also most simple to setup and use (one JAR, one context param, one tag and one annotation). It only requires CDI (not hard to install on Tomcat), but it enables you to even push from a non-JSF artifact on (e.g. a #WebServlet). For security and JSF view state keeping reasons, it only supports one-way push (server to client), not the other way round. For that you can keep using JSF ajax the usual way. The JSF 2.3 <f:websocket> is largely based on OmniFaces <o:socket>, hence you'll find a lot of similarities in their APIs (JSF - OmniFaces).
Alternatively, you can also use polling instead of pushing. Pretty much every ajax aware JSF component library has a <xxx:poll> component, such as PrimeFaces with <p:poll>. This allows you to send every X seconds an ajax request to the server and update the content whenever necessary. It's only less efficient than push.
See also:
How to monitor asynchronous/background thread status and get notifications in a JSF component
Real time updates from database using JSF/Java EE
Notify only specific user(s) through WebSockets, when something is modified in the database

Simplest for you can be introduction of ajax4jsf library's "poll" component:
https://ajax4jsf.dev.java.net/nonav/documentation/ajax-documentation/entire.html#d0e1955
It will not need application reconfiguration and big changes in JSF page (only adding a4j:poll component)
It worked very good in couple of my projects.

You can have a look at Seam (see this article for a discussion to use Seam with JSF and AJAX).
When I used Seam the last time, it was pretty slow, though. You may want to create your own JSF component that generates JavaScript (for example using jQuery as explained in this article).

If you need fully-featured Comet updates (reverse Ajax) and so on, then its worth taking a look at the DWR library.

Related

#PreDestroy method not called when leaving page of bean annotated with OmniFaces "ViewScoped"

I am trying to invoke a method annotated with #PreDestroy in a #ViewScoped bean when the user leaves the page associated with that bean in a rather large JSF powered web application.
After reading https://stackoverflow.com/a/15391453/5467214 and several other questions and answers on SO as well as https://showcase.omnifaces.org/cdi/ViewScoped, I came to the understanding that the OmniFaces ViewScoped annotation provides exactly that behavior by utilizing the unload page event as well as sendBeacon on modern browsers.
So I used the #ViewScoped annotation from OmniFaces in my bean:
import javax.annotation.PreDestroy;
import org.omnifaces.cdi.ViewScoped;
#Named("DesktopForm")
#ViewScoped
public class DesktopForm implements Serializable {
...
}
and annotated the method I want to invoke with the PreDestroy annotation:
#PreDestroy
public void close() {
System.out.println("Destroying view scoped desktop bean");
...
}
Unfortunately, this "close" method is not called when I click some link or leave the page
by entering an entirely new URL. Instead, the network analysis of my browser (a current Firefox) shows me that a POST request is send when leaving the page that returns with an 403 http error code:
As you can see in the screenshot, the "Initiator" of the POST request seems to be an unload.js.jsf script with a beacon mentioned in parentheses, which I assume is part of the OmniFaces library. So presumably the functionality described in the OmniFaces ViewScoped documentation is somehow triggered, but does not result in the expected behavior for me.
The browser still navigates to the new page, but the PreDestroy annotated method was not triggered. When I switch to the standard version of ViewScoped (javax.faces.view.ViewScoped instead of org.omnifaces.cdi.ViewScoped), naturally the method still does not get invoked, but there is also no POST method resulting in a 403 error status when leaving the page in the network analysis of my browser (because the standard ViewScoped annotation of Java does not try to invoke any bean side action on unload events, I guess)
I am using MyFaces 2.3.10 in combination with OmniFaces 2.7.18 (and PrimeFaces 8.0.5, I don't know if that is relevant), Spring Security 5.7.3 and Java 11.
Since "403" is the http status for "forbidden", could this have something to do with using "http" instead of "https" in my local development environment? Does this "send beacon" only work with secure connections?
Any help appreciated!
Edit: I also consulted the official documentation of the OmniFaces ViewScoped annotation under https://omnifaces.org/docs/javadoc/2.7/index.html?org/omnifaces/cdi/ViewScoped.html but could not find a reason for the problem I encounter.
With the help of BalusC's comment to my question above, I was able to solve my problem.
What it came down to was that unload events were not processed correctly by our filter chain. Specifically, they were denied access in the doFilter method of our class extending org.springframework.web.filter.GenericFilterBean.
Therefore I added
if (ViewScopeManager.isUnloadRequest(httpServletRequest)) {
chain.doFilter(request, response);
}
to the doFilter method of the mentioned class and then it worked.
On a side note, I had to update my OmniFaces library from 2.7.18 to 3.13.3, because the ViewScopeManager class of OmniFaces 2 only has one isUnloadRequest method that accepts an FacesContext as parameter, which I did not have available in the our GenericFilterBean extension. OmniFaces 3.1 on the other hand provides another method with the same name that works with an HttpServletRequest instance instead, which I had access to and therefore resolved the issue

Websocket push notification to several JSF applications on Tomcat

I have two JSF applications running on Tomcat.
localhost:8080/app1/index.xhmtl
localhost:8080/app2/index.xhmtl
In both index files the same f:websocket tag is placed in the form section.
<h:form>
...
...
...
<f:websocket channel="test" onmessage="socketListener" />
<h:outputScript>
function socketListener(message, channel, event) {
console.log(message);
}
</h:outputScript>
</h:form>
In both managed beans the same channel is used.
#ApplicationScoped
#Named
public class AppController implements Serializable
{
#Inject
#Push(channel = "test")
private PushContext pushContext;
public void sendMessage(String p_message)
{
pushContext.send(p_message);
}
...
...
...
}
But when I send a notification via JAVA method pushContext.send of app1, the JS method socketListener of app2 does not work.
Is it possible to push notification to several JSF applications at once?
The web socket is by default application scoped. Both applications have their own application scope. Both applications don't at all share the same application scope. You see, the application scope is a scope which is, well, tied to a single application. That's because one application is one application. Ah well, I think you get it now :)
You basically want cross-application communication. Standard Java EE API offers JMS for this out the box. But as you're using a barebones Tomcat servlet container, your options are pretty limited. You could install JMS on Tomcat, but better is to migrate to a normal Java EE server. The Java EE variant of Tomcat is TomEE. It already ships JSF, CDI, JMS and more out the box (basically, everything from Java EE), without the need to manually carry around a lot of JAR files via the WAR deployment.
Once having JMS installed in Tomcat, or migrated to a normal Java EE server, then you can follow the instructions in "Cluster design hints" section of the documentation of OmniFaces <o:socket> (the godfather of the <f:websocket>).

Sending message to client(JSF view ) from server(websocket) with ejb timer service [duplicate]

When we create a JSF page, a client request allows generation of HTML dynamically using a combination of Java code and HTML.
Can we introduce hooks in the HTML page using JSF framework, that allow server to update the HTML page based on asynchronous events occurring later at the server, usually via different threads?
JSF 2.3+
You can use #Push and <f:websocket> for this. Below is a kickoff example which updates a data table upon an application scoped event fired by the backend.
<h:dataTable id="notifications" value="#{bean.notifications}" var="notification">
<h:column>#{notification.message}</h:column>
</h:dataTable>
<h:form>
<f:websocket channel="push">
<f:ajax event="updateNotifications" render=":notifications" />
</f:websocket>
</h:form>
#Named #ApplicationScoped
public class Bean {
private List<Notification> notifications;
#Inject
private NotificationService service;
#Inject #Push
private PushContext push;
#PostConstruct
public void load() {
notifications = service.list();
}
public void onNewNotification(#Observes Notification newNotification) {
notifications.add(0, newNotification);
push.send("updateNotifications");
}
public List<Notification> getNotifications() {
return notifications;
}
}
#Stateless
public class NotificationService {
#Inject
private EntityManager entityManager;
#Inject
private BeanManager beanManager;
public void create(String message) {
Notification newNotification = new Notification();
newNotification.setMessage(message);
entityManager.persist(newNotification);
beanManager.fireEvent(newNotification);
}
public List<Notification> list() {
return entityManager
.createNamedQuery("Notification.list", Notification.class)
.getResultList();
}
}
JSF 2.2-
If you're not on JSF 2.3 yet, you need to head to 3rd party JSF libraries.
OmniFaces has <o:socket> (JSR356 WebSocket + CDI)
PrimeFaces has <p:socket> (Atmosphere)
ICEfaces has ICEpush (long polling)
Noted should be that the <o:socket> was the basis for the JSF 2.3 <f:websocket>. So if you have found a lot of similarities, then that's correct.
PrimeFaces uses Atmosphere under the hoods (which is troublesome to setup without Maven). Atmosphere supports websockets with fallback to SSE and long polling. ICEfaces is based on ancient long polling technique. All of those do not implement native JSR356 WebSocket API which was only later introduced in Java EE 7.
OmniFaces uses native JSR356 WebSocket API (supported in all Java EE 7 servers and Tomcat 7.0.27+). It is therefore also most simple to setup and use (one JAR, one context param, one tag and one annotation). It only requires CDI (not hard to install on Tomcat), but it enables you to even push from a non-JSF artifact on (e.g. a #WebServlet). For security and JSF view state keeping reasons, it only supports one-way push (server to client), not the other way round. For that you can keep using JSF ajax the usual way. The JSF 2.3 <f:websocket> is largely based on OmniFaces <o:socket>, hence you'll find a lot of similarities in their APIs (JSF - OmniFaces).
Alternatively, you can also use polling instead of pushing. Pretty much every ajax aware JSF component library has a <xxx:poll> component, such as PrimeFaces with <p:poll>. This allows you to send every X seconds an ajax request to the server and update the content whenever necessary. It's only less efficient than push.
See also:
How to monitor asynchronous/background thread status and get notifications in a JSF component
Real time updates from database using JSF/Java EE
Notify only specific user(s) through WebSockets, when something is modified in the database
Simplest for you can be introduction of ajax4jsf library's "poll" component:
https://ajax4jsf.dev.java.net/nonav/documentation/ajax-documentation/entire.html#d0e1955
It will not need application reconfiguration and big changes in JSF page (only adding a4j:poll component)
It worked very good in couple of my projects.
You can have a look at Seam (see this article for a discussion to use Seam with JSF and AJAX).
When I used Seam the last time, it was pretty slow, though. You may want to create your own JSF component that generates JavaScript (for example using jQuery as explained in this article).
If you need fully-featured Comet updates (reverse Ajax) and so on, then its worth taking a look at the DWR library.

How to render current time in JSF every second by #Schedule [duplicate]

When we create a JSF page, a client request allows generation of HTML dynamically using a combination of Java code and HTML.
Can we introduce hooks in the HTML page using JSF framework, that allow server to update the HTML page based on asynchronous events occurring later at the server, usually via different threads?
JSF 2.3+
You can use #Push and <f:websocket> for this. Below is a kickoff example which updates a data table upon an application scoped event fired by the backend.
<h:dataTable id="notifications" value="#{bean.notifications}" var="notification">
<h:column>#{notification.message}</h:column>
</h:dataTable>
<h:form>
<f:websocket channel="push">
<f:ajax event="updateNotifications" render=":notifications" />
</f:websocket>
</h:form>
#Named #ApplicationScoped
public class Bean {
private List<Notification> notifications;
#Inject
private NotificationService service;
#Inject #Push
private PushContext push;
#PostConstruct
public void load() {
notifications = service.list();
}
public void onNewNotification(#Observes Notification newNotification) {
notifications.add(0, newNotification);
push.send("updateNotifications");
}
public List<Notification> getNotifications() {
return notifications;
}
}
#Stateless
public class NotificationService {
#Inject
private EntityManager entityManager;
#Inject
private BeanManager beanManager;
public void create(String message) {
Notification newNotification = new Notification();
newNotification.setMessage(message);
entityManager.persist(newNotification);
beanManager.fireEvent(newNotification);
}
public List<Notification> list() {
return entityManager
.createNamedQuery("Notification.list", Notification.class)
.getResultList();
}
}
JSF 2.2-
If you're not on JSF 2.3 yet, you need to head to 3rd party JSF libraries.
OmniFaces has <o:socket> (JSR356 WebSocket + CDI)
PrimeFaces has <p:socket> (Atmosphere)
ICEfaces has ICEpush (long polling)
Noted should be that the <o:socket> was the basis for the JSF 2.3 <f:websocket>. So if you have found a lot of similarities, then that's correct.
PrimeFaces uses Atmosphere under the hoods (which is troublesome to setup without Maven). Atmosphere supports websockets with fallback to SSE and long polling. ICEfaces is based on ancient long polling technique. All of those do not implement native JSR356 WebSocket API which was only later introduced in Java EE 7.
OmniFaces uses native JSR356 WebSocket API (supported in all Java EE 7 servers and Tomcat 7.0.27+). It is therefore also most simple to setup and use (one JAR, one context param, one tag and one annotation). It only requires CDI (not hard to install on Tomcat), but it enables you to even push from a non-JSF artifact on (e.g. a #WebServlet). For security and JSF view state keeping reasons, it only supports one-way push (server to client), not the other way round. For that you can keep using JSF ajax the usual way. The JSF 2.3 <f:websocket> is largely based on OmniFaces <o:socket>, hence you'll find a lot of similarities in their APIs (JSF - OmniFaces).
Alternatively, you can also use polling instead of pushing. Pretty much every ajax aware JSF component library has a <xxx:poll> component, such as PrimeFaces with <p:poll>. This allows you to send every X seconds an ajax request to the server and update the content whenever necessary. It's only less efficient than push.
See also:
How to monitor asynchronous/background thread status and get notifications in a JSF component
Real time updates from database using JSF/Java EE
Notify only specific user(s) through WebSockets, when something is modified in the database
Simplest for you can be introduction of ajax4jsf library's "poll" component:
https://ajax4jsf.dev.java.net/nonav/documentation/ajax-documentation/entire.html#d0e1955
It will not need application reconfiguration and big changes in JSF page (only adding a4j:poll component)
It worked very good in couple of my projects.
You can have a look at Seam (see this article for a discussion to use Seam with JSF and AJAX).
When I used Seam the last time, it was pretty slow, though. You may want to create your own JSF component that generates JavaScript (for example using jQuery as explained in this article).
If you need fully-featured Comet updates (reverse Ajax) and so on, then its worth taking a look at the DWR library.

How to call EJB in PhaseListener

I use JSF 2 and EJB 3.1, all of them are deployed on Glassfish 3.1.
When i setup a class named MyInterceptor which is implemented PhaseListener, i can not revoke remote EJB interface inside it.
It notice "NullPointerException ..."
public class MyInterceptor implements PhaseListener {
#EJB(name="AuthorizationEJB",
beanInterface=AuthorizationService.class,
mappedName="corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")
public AuthorizationService authorizationService;
....
}
When I call authorizationService.dosomestuff(), it raise error NullPointerException
How can i do to fix it?
Thank in advance
In JSF 2.1 and earlier, PhaseListeners are unfortunately no injection targets (meaning you can't use injection in them). You can do your lookup programmatically via JNDI instead though.
In JSF 2.2 all JSF artifacts (including PhaseListeners) will be injection targets, but this will probably not help you now.
Unrelated to your question, but I'm not sure what you're trying to achieve by specifying the beanInterface in your annotation. Most likely you'll also don't need the name attribute and if your bean is a local bean you'll also don't need mappedName.
Use a servlet filter instead of a JSF phase listener to do authorization. You can inject an #EJB in a #WebFilter.
Yeah in web filter you could have just used plain #EJB. Maximimum you needed to add beanName if you had two beans implement same AuthorizationService interface.
Servlet filter is per request, I don't think you need to do security stuff at a certain phase from JSF's lifecycle (which is a more granular level than the whole http request).
For normal lookup you can do:
AuthorizationService.class.cast(new InitialContext().lookup("corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")).dosomestuff();
in a try catch javax.naming.NamingException

Resources