I am on a team that is interested in using ui:include to embed external resources in a HTML document. While investigating how to do this, I came across this post: JSF Facelets how to include external html?
BalusC clarifies that is the wrong tool for embedding external resources in a HTML document and suggested using iframes instead. My question is: why is it the wrong tool?
The team I'm on is especially concerned about security. The content is all going to be our own, but there is a concern about cross-site scripting when communicating between iframes. I've read that there are security benefits to using iframes, as well.
Since the answer likely depends on the use case, I will describe mine:
We're using a docking framework called wcdocker (http://docker.webcabin.org/), which allows panels to be added as divs (planning to use ui:include) or via iframes.
From what I've read/experienced so far, my main concern is that you would have to load the entire page for a given panel, even if the user might not actually open it. There will be multiple dockers, and each will have about 50 panels that can be opened. I am concerned that the client will be overwhelmed, compared to a simple link that may/may not be opened in the given docker.
My second concern is with conflicts if the user attempts to open the same panel twice (same ID tags, omnifaces socket conflicts where the backing bean declares a PushContext for a viewscoped recipient, etc.). I have read workarounds for some of this, sounds like a headache...
Their main concern is regarding communication between panels and cross-site scripting attacks. They believe the user's panel communication should be done directly on the client side, so that the server does not have to be hit at all. I believe the user's panel communication should be done on the server side via a custom publish/subscribe approach (not via JMS) where panel A publishes to a custom Java "topic" object and panel B subscribes to that topic.
For context, there will be a maximum of 50 users at a time, and the web application will be fairly complex.
After a lot of research, there is at least one issue with my question: our content will not be "external" at all. It will be content that resides on the same server as the main application.
Anyway, it seems that at least one concern with iframes is having too many view states. This thread is the most relevant to that problem: JSF multiple views limit. There is a limit to the number of views (15): (ViewExpiredException after upgrade to jsf2)
You can increase that limit in the web.xml file, but it may be difficult to identify the right number for the problem described above.
In another thread, BalusC indicates that ui:include is the best way to put an xhtml inside another xhtml (How to include another XHTML in XHTML using JSF 2.0 Facelets?). However, ui:include does not appear to be ideal for dynamic content. With wcdocker, a panel may be added/removed at any time. It may be worth using jquery's load method as an alternative. See this thread for more information, even though it's for PHP's ui:include: Best way of loading/including content? (jQuery's load() vs. PHP's include())
For anyone interested in using wcdocker in a JSF project while avoiding iframes, this code is a good starting point:
myDocker.registerPanelType('My Panel', {
onCreate: function (myPanel) {
var $mydiv = $('<div id="div1"></div>');
myPanel.layout().addItem($mydiv, 0, 1).css('text-align', 'right').stretch('1%', '');
myPanel.on(wcDocker.EVENT.LOADED, function() {
$("#div1").load("thepage.xhtml");
});
}
});
Finally, you may still run into an issue with conflicting id's, particularly if you load the same page twice. This thread may help you to resolve that concern, and it may even be wise to determine ID by a url parameter: Avoiding duplicate ids when reusing facelets compositions in the same naming container
Related
I want to have Web Components hosted by one site, which another site cannot access the inner DOM or Javascript of. Exactly like with iframes, but which can be rendered inside the HTML better, for example sizing to incorporate their content etc.
There have been many discussions about this but in 2019 when I ask this, is anything implemented to do this?
EDIT: Let me be totally clear - I want the JS for the component to be served from our servers, requests to our server to be done from the component’s JS, render stuff in the component, but not let the enclosing site get it or put a trojan horse in the component. I am fine w the encloing site providing CSS but no HTML or JS. Can this be done?
How would it communicate with the component, analogous to postMessage?
Finally, is it possible for the COMPONENTS JS to access the outer containing website’s DOM and thereby find other components and communicate? This last one ain’t possible with iframes on another domain.
Simple answer: No.
Web Components Do not isolate JS. Just DOM and CSS.
But you can put all of your JS within your class, or in an ES6 Module, or in an IIFE and that would isolate it.
But I doubt that Web Components will ever be a 100% replacement for <iframe>. Nor do I think they were meant to be such.
I would not be surprised if the <iframe> were to become deprecated and eventually removed from browsers.
UPDATE
Keeping ALL of the JS code inside your component's class or inside an IIFE will somewhat protect the code. The HTML and CSS are already sand-boxed inside the component. If your code was in an IIFE or in an ES6 module then other code would have to have access to the source file and be able to modify it in order to change it.
Communication from the outside with the component is done by the outside code calling functions of the component or setting properties and attributes of the component.
Communication from the component to the outside is traditionally done by dispatching events. Talking directly from one component to another is a messy option and really should be avoided. It is up to the parent code to listen to events from all its children and then call functions or set properties/attributes on other children.
If you use shadowDOM then the enclosing site can only change the CSS of your components if you make certain aspects of the CSS available to them. This is done either with CSS Varaibles or by using <slot> to allow the enclosing app to place their own HTML/CSS inside your component. This could open you up to some things you may not want though.
The code that is in the class, or in an IIFE can always access anything in the DOM. Remember that JS is not sand-boxed and can do anything any other JS can do. But it is more difficult, though maybe not impossible, for the enclosing app to make changes to your component classes. Make sure your classes are frozen to prevent sub-classing.
One other thing to know is that if you have someone else loading their website from their server and then loading your component files from your server then you may have CORS problems. Especially if your code tries to load data using XHR/Fetch, then you may have CORS issues.
I have a Java-EE application that works with JSF (ManagedBean, ManagedProperty, ect ...) and Spring framework. I need to be able to retrieve data via a javascript form sent from an external website. I have opened the rights to authorize the CORS (Cross Origin or Cross Domain).
I would like to know what is the best way to grab an external form with JSF so that it is processed by my ManagedBean.
To make my question more explicit I made a diagram
==============
EDIT
The application works with JSF, I'm looking for a way to retrieve data (from a Javascript form on an external site) in a ManagedBean under JSF. I tried to retrieve this data by creating a Java-EE standard servlet and using the doPost ... methods of HttpServlet. But this solution does not work (this was the subject of my previous question on S.O). Several people told me that in a web application do not mix Java-EE standard and JSF, it is either Servlet or JSF. I made a diagram (above) explaining quickly what I am trying to do.
To recap: I would like to retrieve data from an external website (via a Javascript form) in the ManagedBean of my application.
==============
I've already tried with a standard Java-EE servlet but it's not the right way. Indeed, with a standard servlet I can recover the data from the form but I can not access the ManagedBean. I must therefore have abandoned this hypothesis.
I did not find a similar question about Stackoverflow, If necessary I can give more indications.
Thank you for your help.
I'm working on a JSF page that needs to have the corporate privacy policy updated. Rather than copy-and-paste the new text, I'd prefer to have the PrimeFaces dialog that displays it link to the privacy policy elsewhere. So, I'm doing this:
<p:dialog id="dlgPrivacyPolicy">
<ui:include src="https://cdn.mycompany.com/privacy/en-us/privacy.htm"/>
</p:dialog>
The problem is, the HTML on that page is slightly malformed; there's a <meta> tag that isn't closed. This causes my JSF page to fail to compile.
I could track down whoever maintains that page and ask them to correct it, but that's a band-aid. If any more malformed HTML shows up on that page, it will crash mine. And having my page fail to load because the privacy policy didn't close a tag just isn't acceptable.
Is there a safe way for me to insert potentially malformed HTML into my page? Or am I stick with copying and pasting if I really want to avoid that issue?
If you don't want xhtml compilation problem, you should not include the malformed page in server side but in client side, for example by running ajax request on it and include it by using innerHtml attribute of the dlgPrivacyPolicy div.
Using JQuery :
$.ajax({
url: "https://cdn.mycompany.com/privacy/en-us/privacy.htm"
})
.done(function( html ) {
$( "#dlgPrivacyPolicy " ).html( html );
});
Considering your requirements (mentioned in your question and comments) I'd suggest to use jsoup: You can fetch the html content server-side, sanitize it and then use the sanitized content on your page. The sanitizing step is completely up to you (and jsoup's great capabilities) which can include removing unused/unsafe parts of the page (i.e. headers, css etc) as required.
I'm afraid that including a complete HTML page verbatim is always going to be painful. There's the risk of malformed HTML, or the page might do funny things like overwrite CSS styles, pollute global Javscript scope or whatever.
I think the only clean, maintainable solution will be to agree on some kind of (web) service that provides the privacy policy in a well-defined format (HTML, XHTML, whatever) suitable for inclusion elsewhere. This also makes sure the provider of the privacy policy does not suddenly decide to change the URL, or include a popup or similar. The important point is that the service is an official service with agreed-upon rules.
If you cannot get that service, you'll have to find workarounds. The best I can think of would be to filter the policy through some tolerant HTML parser on your side to fix it (at runtime, or as part of the build). Then you can also fix things like over-eager CSS rules or bad Javascript, as applicable.
(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.
i have a jsf application in which i have three frames,one for the header,one for side navigation and the other is the mainframe.I have built this in the spring framework.
I have a problem that when the HttpSession object gets timed out the apllication gets forwarded to the Login page(which is correct,and is the starting page of the app) but within the mainframe so i have a nested application.btw i am running this app in websphere and i can set the HttpSession timeout variable to a very high value so that this problem will occur less,but this is not a solution.
Any ideas on how i can get around this problem.
iFrames are really a bad thing!
What I suggest is to use the Facelets library, which allow you to easily create templates of pages. In your case, you will be able to create the three differents parts (header, navigation side and main page).
Once created, the result will be a single HTML page (i.e. no frames).
This way, you will not encounter your problem anymore.
You have several articles that explains the main features of Facelets, including the templating.