Is it possible to fire a CDI event from an MDB? This MDB is monitoring a JMS queue and then a JSF page needs to be updated.
The issue that I'm experiencing is the JSF bean has a scope (was session, but trying request) and the MDB has no scope. The JSF bean contains the controller code (updating the page) and the #Observes annotation on a method parameter. Because the MDB is not in a 'context' and has no scope, the CDI event is never triggered on the JSF Bean.
How is it even possible then to update a JSF page based on a JMS (with MDB) event?
Disclaimer, I'm pretty sure of my what I'm claiming here but not 100%.
You can't do it with just MDB and CDI events. Typically a CDI event reuses the request thread and executes events synchronously after your method was invoked. That means that it's a potential bottleneck even if it worked. The second part is that it will find observers based on the request that spawned it and not find other "users" or whatever.
You can bridge this in several different ways and with several technologies but WebSockets / the Atmosphere framework is usually a solid way to get the message out there. Note that Primefaces Push exists and is based on Atmosphere.
I had a project recently (small) where I needed a plain tomcat and I could not use WebSockets so I brewed up a solution using CDI events.
It works like this:
Instead of using event.fire(new myEvent()) I went for something more transparent, ie I wanted it to show clearly that this event will be broadcasted to all sessions. So instead I created what I called SessionEventDelegator. It has a method called putEvent(Object object) (also other methods when you need Qualifiers). When you want to send events to all sessions you simply inject that and "put" your event. Maybe I should call it load since it will get fired later ;p
Later A JSF PhaseListener calls getEvents() and get all new events since the last time it checked. A timestamp functionality is in place so that you only get new events.
Now simply iterate over found events and use BeanManager.fire to get them out.
Since the PhaseListener will only trigger when the user makes a new request I use p:poll from primefaces ensuring that it polls for new events every third second.
A cleanup algorithm makes sure that events that everyone got is removed from the queue in SessionEventDelegator.
if you want the code let me know. To lazy to paste it if it doesn't sound right to you.
In case that CDI events won't work (I am not convinced about that because spec says that non-contextual objects can't observe events, there is nothing about firing them) but simplest workaround seems to use interceptor. MDBs can have interceptors so just intercept onMessage method and fire event from the interceptor.
Yes, you can fire CDI events from MDBs. The problem is that they're only going to be observed at the application level. If you're using push technology (e.g. Websockets) you can have this ApplicationScoped object receive the event, and then push to the appropriate client based on session id in websockets.
In RichFaces library there's a4j:push component that does exactly what you need. Check out the RichFaces Push section
Related
From what I am reading, two-way binding means there are "watchers" that implement a setTimeout in JavaScript every so many milliseconds to keep the model and view inline with each other.
In one-way binding, once the view is populated, are the events that are assigned to an element what triggers syncing between model and view, thus no "watchers"? My reason for asking is I do not believe using "watchers" is wise, but this will help me verify. The browsers JS event loop seems to be sufficient for events.
(Please assume Angular, React, and Vue, if it is necessary to answer the question.)
I have read this,
One-Way or One-Time binding in Angular and Watchers
I have created a REST service for uploading files. Because of various requirements, I cannot integrate that into the JSF lifecycle. Amongst others:
JQuery handles the POST and expects a JSON response which I don't feel good doing from a bean method.
Fileupload plugin does multiple concurrent file POST s, which AFAIK is not possible (by default) JSF behaviour as event's will be queued.
I have a few options in mind, but I would like to be as intrusive as possible. The ones I have examined so far are:
Using JQuery, populate a hidden field with the location of the files and process them in the ActionListener
Same as above, but also call the ActionListener from JQuery
Store data in the session (since I can access it, from my REST service)
Use an #EJB queue service to pass the data to the bean (#Inject' service to bothbeanandREST` service)
Alternatively, is there a way to actually fetch by #ViewScoped bean given that I have the viewstate form field?
I am using MyFaces 1.1.14. I have two JSPX pages with JSF components and my managed bean is in request scope. At first page, bean constructor is getting fired and when I submit a form it is fired again. But after my app navigates to the new page, it is not getting fired. The constructor is supposed to be called, right?
The thing is that page is accessing some properties of the bean — those setters get called — no problem with that, but why is the constructor not called? When the page get loaded I need to get data from previous process (i.e from different framework). What is the problem with my understandings?
The navigation does by default not fire a new HTTP request. Instead, a different view is been used as content of the current HTTP response. Only when you navigate with a redirect by appending the <redirect/> entry to the <navigation-case>, then a new HTTP request would be created.
You should totally understand it if you're familiar with RequestDispatcher#forward() concept of the basic Servlet API which JSF is sitting on top of.
See also:
What is the difference between redirect and navigation/forward and when to use what? - Note that the code examples are targeted at JSF 2.x, but the principles apply as good on JSF 1.x.
We are developing web application using JSF. We are using rich faces on Jboss server. We have a4j command buttons , command links and a4j js functions to invoke server actions.
We have set limit render to true, render only required components. And I also set execute to "#this" . We are observing a strange behavior , All the actions associated with the form are also executed along with the button clicked, even though we have not specified the execute value to "#this". This is bringing down the performance drastically.
Is this the way JSF process POST requests or is there something else we are missing?
What you're currently describing in the question is definitely not the default behaviour of JSF nor RichFaces.
Your concrete problem is caused elsewhere. As per the comments, you seem to have created a PhaseListener for logging purposes which is re-executing the entire view for some reason. You'd need to turn off this PhaseListener or to fix its implementation.
(Using JEE6) Is it possible to have a webpage automatically update (or listen) to values from within a bean/class and display them on the JSF when these changes happen?
As KayKay mentioned you can implement some sort of polling methodology using javascript to ask the server periodically to send updates if there are any. And unless you use ajax you will have to be content with only complete page refreshes.
JSF as good as it is, sits on top of basic stateless web technology. As such unless you use Ajax or some custom code the server will only respond to a request from the client. Some libraries like icefaces have incorporated a "push" component that allows what you are looking for (from what I understand, this is a fundamental part of icefaxes). That is, to push server side changes to the client.
You have to set up a listener on your end so that your bean will be notified when a value change happens on the server (like in your backing bean which is on the server). When the change happens you can ask say, 'icefaces push' (or another library like primefaces, which you indicate you don't want to use) to send a notice to the client. The client side code (usually ajax/javascript) will process the notice and then send a request for the whole object per normal request response. That is the notice tells the client something it's interested in changed so the client can ask for an update. Aside from the notice, still request/response.
I mention icefaces push because it seems to be the favoured library for this now. But others have this as well. I don't believe the standard JSF 2.0 AJAX libraries have this.
Here are a couple of resources to look at:
(The video is a good start to get the idea of what is going on, then use the rest of the site)
http://www.icesoft.org/demos/icepush-demos.jsf
Older but I think still relevant IBM tutorial on what you want to do, using inventory changes as an example:
http://www.ibm.com/developerworks/web/library/wa-aj-dynamic/index.html
And another stack question related:
Is there a better Ajax Push for JSF 2.0 than Icefaces
Unfortunately it looks like you cannot do this with just JSF, you will have to use one of these libraries or even harder, roll your own push mechanism.
I don't know of a JSF feature to do so. I would simply do some javascript polling, using for example jquery load method to refresh the parts of the page where the values are displayed.
It would help to know what you want to do : refresh the whole page when there is a change, update somes values that are displayed from the start, or add new values to the page.