I have this use case in a JSF application.
Supposed in a JSF web application, I have a button that calls an external service that returns a complete HTML response then how can I show that HTML response to my users browsers?
The sequence of events are like this.
In user browser, my application is displayed. A button is there that user can click.
Clicking the button will call an external service. The external service will return information about a certain HTML tags. The HTML is complete with both head/body and with javascript. Currently the service can be implemented thru REST service or a plain DB call then
How can I display that HTML tag in my user browser?
Is this possible to write non-JSF output in a JSF web application?
Just to add, I think my problem is how to write an HTML in my backing bean and write it back to the users browser.
Just write it outright to the HTTP response body whereafter you instruct JSF that the response is manually completed. The principle is not much different from How to provide a file download from a JSF backing bean?, except that you need to set content disposition to inline (which is already the default anyway).
public void writeHtmlResponse() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.setResponseContentType("text/html;charset=UTF-8");
ec.setResponseCharacterEncoding("UTF-8");
ec.getResponseOutputStream().write(html.getBytes("UTF-8"));
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
Related
I'm trying to create a localized JSF web application which allows user to select a language via dropdown. When language is selected, I simulate a redirect to the same page but with URL parameter:
window.location.replace(urlToMyApp + '?locale=DE');
Next, I read 'locale' parameter in application's web filter and write it in a cookie with the same name:
String localeValue = httpRequest.getParameter("locale");
Cookie cookie = new Cookie("locale", localeValue);
cookie.setMaxAge(-1);
cookie.setDomain(cookieDomain);
cookie.setPath(cookiePath);
httpResponse.addCookie(cookie);
Now when I try to read that cookie in request bean init method, cookie is not available. If I select another language via dropdown (EN for example), previously selected language (DE) is read in init method.
I assume that cookie written in filter is not available before next "request - response" cycle, can someone confirm that?
If that's true I'm asking for an idea to translate my application immediately after selecting another language.
Just one thing that I think I need to mention - language dropdown is not part of my application. It's part of some kind of framework for several applications to be included (like portal).
I assume that cookie written in filter is not available before next "request - response" cycle, can someone confirm that?
That's correct.
You've added the new cookie to the response, not to the request. So any attempt to read it from the same request won't work. The cookie will only be available in the request if the browser has actually sent it. But it can only do that if it has obtained the cookie data from a previous response.
If that's true I'm asking for an idea to translate my application immediately after selecting another language.
If the request scoped bean is managed by CDI #Named, then just inject it in the filter and set the locale over there.
#Inject
private Bean bean;
public void doFilter(...) {
// ...
bean.setLocale(locale);
// ...
}
Else if it's not managed by CDI, but by the since JSF 2.3 deprecated #ManagedBean, then manually instantiate it and put it in request scope so that JSF will just reuse the same bean.
public void doFilter(...) {
// ...
Bean bean = new Bean();
bean.init(); // If necessary.
bean.setLocale(locale);
request.setAttribute("bean", bean); // "bean" is managed bean name.
// ...
}
See also:
Get JSF managed bean by name in any Servlet related class
Localization in JSF, how to remember selected locale per session instead of per request/view
I'm writing a JSF web application who follow the next steps:
Read a number from an input text
Look for the number in a legacy system
Generate a message and send It to a websocket
Get the response from the websocket
Store the result in a database
All of these steps must be executed in a single event, all of these tasks are executed in a backing bean, the problem is to execute the javascript to call the websocket and use this result to save it in the database.
I tried to use the RequestContext.getCurrentInstance().execute("function();"); method, but this function "Executes script after ajax request completes or on page load" and I need to get the result to store it into the database and execute other operations.
The question is, How and where can I handle these calls?
NOTE:
I can see the following options, but I'm not sure how to implement them:
Handle the calls using Javascript instead of backing bean, following the next tasks:
from Javascript call a backing bean method to look the number and get the response.
from Javascript get the result of the backing bean and send it to the websocket.
from javascript receive the response from the websocket and call another backing bean to store the result into the database.
Found a way to call a javascript function from the backing bean before the ajax request completes.
Call the WebSocket in the Backing bean instead of using Javascript.
I hope you can help me, Thanks.
----EDIT-----
The websocket is running in localhost, in this way the web page handle a device in a local machine, so it must be executed in the Javascript side and the 3rd option is not possible.
an option could be the following:
your xhtml should have 3 forms:
"User inputText/number form"
"websocket-Request Form" (hidden form/input)
"websocket response Data Form" (hidden form)
now you follow these steps:
A user submits input to your Bean (via ajax or commandActions ...etc)
bean-methode reads/validates that submitted data, then update value in form#2
Javascript/Jquery should listen on form#2/inputhidden value changed( then sends a wensocket request)
after recieving websocket response, update value inside form#3 and do autosubmit. now submitting this form calls an action methode in your bean which saves data to DB.
I have a simple request for Xpages app. I have calculator like page where user enters some data and after submission (button action with full submit e,g, 'Export to PDF' button) app should create PDF and return back to browser. Everything is actualy working fine for me except that this works first time only. It returns PDF back to browser but then browser page stops working ... buttons or ajax partial refreshes dont work anymore. I understand its related to fact that browser submits data to server and expects payload come back but instead I'm sedning PDF file but how to handle it different way? I need the page submit because I'm managing the viewState for page that is necessery for me when rendering PDF content ... Any idea how to solve it properly?
Here is my code I'm using for sending PDF back to browser.
ExternalContext exCon = DominoAccess.getFacesContext().getExternalContext();
HttpServletResponse response = (HttpServletResponse)exCon.getResponse();
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/pdf");
response.setHeader("Content-disposition","attachment; filename="+fileName);
response.setHeader("Cache-Control", "no-cache");
//Get the document out to the screen
createPdf(out,html);
// Stop the page from further processing;
DominoAccess.getFacesContext().responseComplete();
Im trying to prevent users to access special pages with a phaselistener. for that reason im trying to figure out on which page they try to access.
but my problem is, i only get the page they where before. not the actual page.
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
System.out.println("test1" + fc.getViewRoot().getViewId());
}
and same here
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
String uri = request.getRequestURI();
System.out.println("uri: " + uri);
}
why is that, and how do i get the pagename the user is trying to access? Not that one that they required one step before, or better the page they are coming from.
It is one step behind because that is the way sequence of HTTP POST request behaves. When you are navigating in JSF application via command buttons each request goes as a post request.
Since you are protecting some resources make sure they are accessed via HTTP GET than you will get exact view id, this can be achieved as
User directly hits the url from address bar of browser.
After a post of jsf app redirect it to the resource instead of simple JSF navigation. POST-REDIRECT-GET pattern falls into this have a look here.
If you are showing some messages after each POST, you might need Flash map for that, which is new feature in JSF2, if you are on JSF1.x hard luck, you can implement flash if you want to.
To conclude catch the view ids on HTTP GET request.
Hope this helps...
Is there a way to keep a page's session active without resorting to sending the state to the client? I'm not able to set the STATE_SAVING_METHOD to client and I'd prefer to not use the a4j:keepalive.
I've tried using a simple hidden iframe that submits to the Bean in question but it invalidates the main page.
I am using JSF 1.2 and myfaces.
This is to get around a ViewExpiredException on a page that does not require the user to log in. The majority of the existing site requires the user to log in.
Implement an ajax poll as a "heartbeat" to keep the session alive. At its simplest you can achieve this as follows with help of a little jQuery to avoid boilerplate code of 100 lines to get it to work across all different browsers the world is aware of:
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(document).ready(function() {
setInterval(function() {
$.get("${pageContext.request.contextPath}/poll");
}, ${(pageContext.session.maxInactiveInterval - 10) * 1000});
});
</script>
The ${pageContext.session.maxInactiveInterval} prints the remaining seconds the session has yet to live according to the server side configuration (which is by the way controllable by <session-timeout> in web.xml) and is been deducted with 10 seconds, just to be on time before it automatically expires, and converted to milliseconds so that it suits what setInterval() expects.
The $.get() sends an ajax GET request on the given URL. For the above example, you need to map a servlet on the URL pattern of /poll and does basically the following in the doGet() method:
request.getSession(); // Keep session alive.
That should be it.
BalusC's answer helped me to meet this requirement in my app, but since I'm using PrimeFaces, I wanted to share how BalusC's answer inspired the code i'm using to do this.
xhtml page
<p:poll listener="#{pf_usersController.keepUserSessionAlive()}"
interval="#{session.maxInactiveInterval - 10}" />
bean
public void keepUserSessionAlive() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
request.getSession();
}
as always, thank you, BalusC!
EDIT: An enduser put this to the test this morning, and it is working great! my app usually forces session timeout 15 minutes after full page refresh (redirect to sessionExpired.xhtml via meta refresh based on session.maxInactiveInterval and session timeout value in web.xml); if user is on one page doing a bunch of AJAX requests, session will timeout, since AJAX != full page refresh, but this code allowed enduser to 'keep session alive' while enduser was on payroll page in the app, and session stayed alive for 1 to 2 hours! :)