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>).
Related
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.
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.
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.
I'm working on a JSF project on Weblogic 11g, and our initial design is calling for JSF Backing Beans to invoke EJB3.0 beans to perform business logic and data access calls. The #EJB annotation doesn't seem to work in my project when I try to inject the EJB reference to the backing bean. Whenever I hit the class that I am testing, the constructor for my EJB is never called and I end up with a NPE. Is it possible to inject an EJB3.0 bean into a JSF backing bean? Is there another way I should be invoking an EJB through the JSF Backing bean? What is the best practice?
I googled somewhat and this indeed seems to be a known issue with Weblogic. Lot of similar topics are kept unanswered.
I found this blog which confirms that #EJB in Weblogic only works for resources definied by web.xml, not for JSF. The blog describes also in detail a workaround using ServletContextListener which is IMO not much better than using JNDI.
I also found this OTN topic which confirms that #EJB in Weblogic started to work when EJB modules are not included in subdirectories (see the answer posted at the bottom, Feb 15, 2011 5:44 PM).
It turns out that it is a Weblogic specific issue when deploying anything using JSF and EJB. I found this post on the Oracle forums that explains how to get the #EJB injection working in JSF Managed Beans using Weblogic 11g:
EJB3.0 Injection into JSF Managed beans
UPDATE:
After spinning my wheels for too long, I have to give up trying to inject an EJB into a JSF ManagedBean on Weblogic 11g. Seems to work fine in Tomcat. Maybe the EJB3 and JSF implementation will be better in 12G...
To make it work you need to follow two steps:
Deploy jsf-2.0.war as LIBRARY, you can find it /ORACLE_HOME/wlserver_10.3/common/deployable-libraries
In your web project, add the reference to the jsf-2.0.war library in WEB-INF/weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.3</wls:weblogic-version>
<wls:context-root>your_context_app</wls:context-root>
<wls:library-ref>
<wls:library-name>jsf</wls:library-name>
<wls:specification-version>2.0</wls:specification-version>
<wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
<wls:exact-match>true</wls:exact-match>
</wls:library-ref>
</wls:weblogic-web-app>
I have successfully tested this in weblogic 10.3.3 and 10.3.5. If somehow this does not work, try to deploy the application as part of EAR file.
So here is the beat! There is a simple way to fix this.
Open up jsf-2.0.war under ...wlserver_10.3\common\deployable-libraries
Navigate to WEB-INF/lib and save wls.jsf.di.jar JAR somewhere
Place wls.jsf.di.jar JAR under lib folder of your WAR application.
Deploy
all should work now just by adding #EJB to property in your #ManagedBean.
There is an alternative for the #EJB annotation in order to get your local EJB bean accessible in your JSF ManagedBean web application. Considering that you have your EJB classes and your WAR packaged in the same EAR file, do the following:
configure your ejb-jar.xml to tell the weblogic expose the EJB beans to the external components;
<enterprise-beans>
<session>
<ejb-name>MyEJBBean</ejb-name>
<business-local>com.app.MyEJBBeanLocalInterface</business-local>
<ejb-class>com.app.MyEJBBeanLocalImpl</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<local>com.app.MyEJBBeanLocalInterface</local>
</ejb-local-ref>
</session>
<enterprise-beans>
Insert in the web.xml of your web application a reference to the EJB throught the ejb-link name. The ejb-ref-name is name visible for the JSF managed beans.
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.app.MyEJBBeanLocalInterface</local>
<ejb-link>MyEJBBean</ejb-link>
</ejb-local-ref>
In your JSF Managed Bean call the EJB Bean through JNDI lookup as the following:
try {
Context context = new InitialContext();
MyEJBBeanLocalInterface myEJBBean =
context.lookup("java:comp/env/ejb/MyEJBBeanLocal");
} catch (NamingException e) {
e.printStackTrace();
}
In my case I was using the Weblogic 10.3.6 (11g), JSF 2.0 and EJB 3.0 with JPA (Eclipselink)
I'm writing an application using Seam 2.2.x which will be deployed on JBoss 5.1. I have an EJB module with all of the business logic en EJB's. However, I'd also like to have statless session EJBs in the web module to act as action classes. Is this possible? Do I need to perform any additional configuration to get this working? I have an interface I've defined:
#Local
public interface ContentItemSearchAction extends Serializable {
...
}
...and an implementing class...
#Name("contentItemSearchAction")
#AutoCreate
#Stateless
public class ContentItemSearchActionBean implements ContentItemSearchAction {
...
}
However, when I try to access the EJB in one of my JSF views, I get the following exception:
Caused by javax.naming.NameNotFoundException with message: "ContentItemSearchActionBean not bound"
Has anyone seen this before? What am I missing? Why is the EJB in my WAR module not being picked up?
EJBs do not go into WAR files. They're packaged into JARs, which go into the EAR along with the WAR.
The EJBs need not be in the WAR to be visible from your web tier.