I am working on some UI Components that I would like to use entirely instead of writing the XHTML.
I am perfectly happy with XHTML; however, I want to break everything up into modules as well as break the physical connection between a URL and a file in a WAR or on the filesystem. I also want it to be entirely virtual so that I have greater control over security.
Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.
This is the latest error I'm getting - I am guessing I don't have my components properly configured:
java.lang.NullPointerException
at com.sun.faces.context.FacesContextImpl.getRenderKit(FacesContextImpl.java:258)
at com.sun.faces.renderkit.RenderKitUtils.getResponseStateManager(RenderKitUtils.java:237)
at com.sun.faces.lifecycle.LifecycleImpl.reload(LifecycleImpl.java:331)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:134)
at com.walterjwhite.seamCore.servlet.filter.FacesFilter.doFilter(FacesFilter.java:97)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.webContent.servlet.filter.UploadedFileFilter.doFilter(UploadedFileFilter.java:97)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.seamCore.servlet.filter.HttpRequestMonitoringFilter.doFilter(HttpRequestMonitoringFilter.java:59)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.seamCore.servlet.filter.ContextFilter$1.process(ContextFilter.java:60)
at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:53)
at com.walterjwhite.seamCore.servlet.filter.ContextFilter.doFilter(ContextFilter.java:55)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at com.walterjwhite.seamCore.servlet.filter.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:82)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:865)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
Walter
You can definitely modify the component tree from a filter. Another technique is to build part of the page as jsf, then bind to a component such as a panel group layout & build the components inside it from a managed bean.
UIComponent parent = ...
for(...) {
parent.getChildren().add(...);
}
The physical connection between URL & file is already broken. You can use a navigation rule to point to anything you want. Not sure what you mean by entirely virtual regarding security.
This is just my opinion, but a dynamic component approach is not as extensible as jsf & metadata.
Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.
A Filter is probably not a good place to do this. If memory serves, the FacesContext is set up and torn down in the FacesServlet in core JSF (you may know better than me if Seam requires other servlets to do some lifecycle lifting). So, the context will probably not be in scope in the filter.
Providing your own ViewHandler decorator would probably be a better bet. You can extend ViewHandlerWrapper and give it a constructor that takes the decorated ViewHandler from the framework. This can be defined in your faces-config.xml. You'll find more details in the spec.
Related
I use JSF 2.3 (Mojarra 2.3.3), Trinidad (2.2.1) and its file upload component (tr:inputFile) in a web.xml-version 3.1 on a Tomcat 8.5 server.
I get following exception and no valid uploaded file (i.e. the "value"-binded bean attribute remains null):
java.io.EOFException: null
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._readLine(MultipartFormHandler.java:253) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._readLine(MultipartFormHandler.java:237) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._skipBoundary(MultipartFormHandler.java:223) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler.<init>(MultipartFormHandler.java:102) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler.<init>(MultipartFormHandler.java:75) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.upload.FileUploadConfiguratorImpl.beginRequest(FileUploadConfiguratorImpl.java:139) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl._startConfiguratorServiceRequest(GlobalConfiguratorImpl.java:763) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl.beginRequest(GlobalConfiguratorImpl.java:244) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:178) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92) [trinidad-api-2.2.1.jar:2.2.1]
(Info: The JSF 1.2 version with Trinidad 1.2.14 with web.xml-version 2.5 on Tomcat 6 or a Weblogic 10 does not have this problem.)
While searching for a solution I found that this seems to affect not only my concrete situation, but also:
ADF Faces (at least 12.x)
Trinidad 2.1
JSF 2.x in general
Wildfly (10.1)
Searching for an answer I developed a solution I want to share.
Use JSF's <h:inputFile> (since JSF 2.2) instead of <tr:inputFile>.
You may continue to use <tr:form usesUpload="true">, but see notes below.
In the backing bean you have to simply replace org.apache.myfaces.trinidad.model.UploadedFile with javax.servlet.http.Part and use getSubmittedFileName() instead of getFileName().
With this, file upload already works, but the EOFException still occurs and is logged (but ignored internally).
To prevent the needed TrinidadFilter (configured in web.xml) from processing the file upload, add your own javax.servlet.Filter (most apps will already have one, I guess) and put in its doFilter():
request.setAttribute("org.apache.myfaces.trinidadinternal.config.upload.FileUploadUtils.PROCESSED", Boolean.TRUE);
Of course, your filter must be executed before the TrinidadFilter, so either use a broader filter-mapping or place it before TrinidadFilter in your web.xml.
Additional notes:
When using <tr:form> the <h:inputFile> will output the wrong error/warning "File upload component requires a form with an enctype of multipart/form-data" via FacesMessage - but not for javax.faces.PROJECT_STAGE Production.
You may simply ignore it in development or use <h:form enctype="multipart/form-data"> instead. But note: <h:form> is a naming container and <tr:form> is not, so addressing input elements differs (hformId:inputId instead of simple inputId)
If your <tr:inputFile> is used inside a <tr:panelFormLayout>, put the <h:inputFile> inside a <tr:panelLabelAndMessage> and put the label there.
CSS styling for af|inputFile::content must also be done for input[type="file"].
See also:
https://stackoverflow.com/a/27681292/5074004
https://developer.jboss.org/thread/274824?_sscc=t
http://myfaces.10567.n7.nabble.com/Trinidad-File-upload-issue-td30231.html
Short Version:
If two JSF library jar files both include a custom renderer for the same family and type, is there any way from within the library itself (i.e. not from the containing app) of specifying which one should be used? Something like assigning a priority, with higher ones used in preference to lower ones?
Longer Version:
I'm using Primefaces in a project and trying to override the provided head renderer with my own:
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.Head</renderer-type>
<renderer-class>com.example.MyHeadRenderer</renderer-class>
</renderer>
</render-kit>
If I put that into the WEB-INF/faces-config.xml of the war file then it's all good, and my renderer gets used.
However, if I try to deploy my code as part of a library jar (my-utils.jar), with the renderer defined in META-INF/faces-config.xml, then the Primefaces one is used. This contains exactly the same definition, so I'm guessing it just depends on the order they get loaded. Indeed, renaming my library to "xx-comps.jar" works, so it would appear that JSF is loading faces-config.xml files from all jar files in alphabetical order, with later entries just overwriting earlier ones.
Is there any way of forcing the selection to my library?
So far, I have these options:
Put my renderer directly into the WEB-INF/faces-config.xml of the war.
Build a custom Primefaces jar with that one renderer definition
removed.
Rename my library and rely on some (undocumented as far as I can
see) behaviour from the JSF loader.
Add a custom renderkit which extends the standard one, and reference
that from my war WEB-INF/faces-config.xml.
The first three all work but are not ideal, as (1) and (2) require changes outside my library, and (3) just looks dodgy as hell....
The fourth is just an idea as I've never written a render kit before so not aware of the effort involved. No idea if it is practical or would work, but it is better than (1) because at least the application only references a single render kit, and does not need to be updated if/when new renderers are added. Happy to put more effort into researching this approach if it seems a reasonable solution.
Also, I'd ideally prefer to use annotations rather than XML:
#FacesRenderer(componentFamily = "javax.faces.Output", rendererType = "javax.faces.Head")
public class MyHeadRenderer extends Renderer {
...
}
Thanks
You can specify the ordering via <ordering> in faces-config.xml of the JAR.
E.g. if you want your utility library to be loaded after all others, then just do so:
<ordering>
<after>
<others />
</after>
</ordering>
If you want to force an explicit ordering, then hook on specifically PrimeFaces, which has a <name>primefaces</name> in its faces-config.xml:
<ordering>
<after>
<name>primefaces</name>
</after>
</ordering>
As described in this question I try to perform some field validation in a form on the backing bean side. For this I would like to access the violating fields to mark them.
From searching the web there seem to be two ways to do this:
store the components in the backing bean for access and use them in the JSF pages via the binding attribute.
Use standard value binding in the JSF pages and when needing access to a component from the bean, look it up via UIViewRoot.findComponent(String id)
As far as I can see both ways have drawbacks:
Component bindings blows up the backing bean with variables and getters/setters, some sites strongly discourage the use of component binding at all. In any case, a request scope is advised. On the other hand, findComponent() always traverses the tree, which may or may not be costly, right? (Plus, at the moment I can't find my component at all, but that is another problem)
Which would be the way to go? Are these interchangeable alternatives and if not, based on what criteria do you chose? Currently I just don't have enough insight to make a decent decision...
First of all, regardless of the choice, both are a poor practice. See also How does the 'binding' attribute work in JSF? When and how should it be used?
If you had to make the choice, component bindings are definitely faster and cheaper. It makes logically completely sense that a tree scan as done by UIComponent#findComponent() has its performance implications.
Indeed, the backing bean holding the component bindings must be request scoped, but you could easily inject a different scoped backing bean holding the business logic in it by #ManagedProperty.
A cleaner approach would be to use a Map as holder of all component bindings. You only need to add the following entry to faces-config.xml:
<managed-bean>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
This can just be used as
<h:inputSome binding="#{components.input1}" />
<h:inputSome binding="#{components.input2}" />
<h:inputSome binding="#{components.input3}" />
And this can be obtained in other beans as
Map<String, UIComponent> components = (Map<String, UIComponent>) externalContext.getRequestMap().get("components");
This way you don't need to worry about specifying individual properties/getters/setters. In the above example, the Map will contain three entries with keys input1, input2 and input3, each with the respective UIComponent instance as value.
Unrelated to the concrete question, there may be a much simpler solution to the concrete problem as you described in the other question than performing the validation in the action method (which is actually Bad Design). I've posted an answer over there.
I learnt how to use container authentication with JDBC realm.
I searched a lot on internet but I couldn't find anything on JSF authorization except the following article.
JSF authorization
My goal is to avoid access to protected pages using direct links and to show/hide menu items and form components based on the authenticated user privileges.
The last part can be implemented using the rendered attribute of JSF tags but before creating my own dirty and high coupled solution I wonder if there are some specific best practices or libraries that can help. in fact the number of components to be conditionally rendered is quite high and I wouldn't like to write a specific function for each of them.
Perhaps I can create for each authenticated user a map with the names (id) of all the conditionally rendered components and a single function with a String parameter (the unique name/id of the component). Is that a good idea ? What alternatives do I have ?
I wouldn't like to add to the project other general purpose frameworks such as spring for using only a small part of them (the security one).
Thanks
Filippo
With the Expression Language version in Java EE 6 you should be able to use expressions like these:
<h:inputText rendered="#{facesContext.externalContext.isUserInRole('foo')}" />
With older versions, you can create a managed bean of this form:
public class RoleMap implements Map<String, Boolean> {
public Boolean get(Object key) {
ExternalContext extCtxt = FacesContext.getCurrentInstance()
.getExternalContext();
return extCtxt.isUserInRole(key.toString());
}
//TODO: other methods; mostly throwing UnsupportedOperationException
The test can then be expression in the form:
<h:inputText rendered="#{roleMap['foo']}" />
Third party frameworks offer other options, such as the Apache Tomahawk library's visibleOnUserRole component attributes.
Take a look at Apache Shiro, a dedicated security framework (and supposedly erasier to use than Spring Security).
HI,
There are many ways to get the bean instances from the JSF context. In the following two way:
Bean bean = (Bean) request.getAttribute("beanName");
and
FacesUtils.getManagedBean("beanName");
What is the difference in above two ways. In which case we have to use either ways. Please clarify me.
Use the first if you're not inside the JSF context (aka the FacesContext), e.g. inside a servlet. The second way is unclear since FacesUtils is not part of standard JSF implementation (it's likely a homegrown or 3rd party library). But if it grabs it by the FacesContext, then it works only when you're already inside the JSF context (i.e. inside a JSF managed bean).