How can I list included source files of a page? - jsf

I am trying to list all jsf files that are included (e.g. via ui:include) in the current page. I was hoping that I can find that information somehow on each UIComponent so that I just had to iterate over all UIComponents on that page and add the source file to a set but I can't find anything that would give me the source file.
Any ideas?

Kukeltje's suggestion to check out BalusC's (who else?) post Obtaining Facelets templates/files from an external filesystem or database was the answer.
So in order to list all includes for the page that is being loaded use the following:
As I am using JSF 2.1 here is my solution:
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.faces.FacesException;
import javax.faces.view.facelets.ResourceResolver;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
public class FacesResourceResolver extends ResourceResolver {
private ResourceResolver parent;
public FacesResourceResolver(ResourceResolver parent) {
this.parent = parent;
}
private static final Log log = Logging
.getLog(FacesResourceResolver.class);
#Override
public URL resolveUrl(String path) {
URL url = parent.resolveUrl(path);
log.info("Resource #0", path);
return url;
}
}
And add the following to web.xml
<context-param>
<param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
<param-value>com.locuslive.odyssey.developer.FacesResourceResolver</param-value>
</context-param>

Related

Display image from a out side project directory using primefaces

i am new to primefaces and i am doing a project where i need to display multiple images from outside of a project directory. Lets think i have a folder called image in my C directory and there is multiple subfolder inside my image folder. I need to display all the images inside from a specific subfolder using p:gallery of primefaces.
i have checked some example using but i am not finding any output from it. please help me to solve it.
i have used following cooding
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/images/*")
public class ImageServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try
{
String filename = request.getPathInfo().substring(1);
System.out.println("path is"+filename);
File file = new File("D:/images/", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + filename + "\"");
System.out.println("out put path"+file.toPath());
Files.copy(file.toPath(), response.getOutputStream());
}
catch(Exception e)
{
System.out.println("Exception is"+e.toString());
}
}
}
and my page i have written
<h:graphicImage value="/images/filename.ext" />
but i am getting following exception
path isfilename.ext
out put path
D:\images\filename.ext
Exception is
java.nio.file.NoSuchFileException: D:\images\filename.ext
please give any suggetion
here you can find a complete FileServlet class (yours is missing a couple of major things).
After you've modified FileServlet.java to fit for your purpose you should use
<p:graphicImage height="???" width="???"rendered="???" value="yout/path/#{image}" cache="????" />
in your page

JSF - Updating a JSF datatable on page refresh

I have a datatable on my JSF page, which gets filled dynamically on page load thanks to BalusC and Odelya.
But now when I try to refresh the JSF page to retrieve the updated data from database, I don't get the updated data in the Datatable.
I have already gone through the following link but couldn't understand the nuances..!
JSF datatable refresh on page load
Is your bean scope configured as a Session?
Have you tried to change its scope to Request?
Don't forget to close your connection after filling your resultset, which has to be a CachedRowSet
Here is an example from Core JavaServer Faces book:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.enterprise.context.RequestScoped;
import javax.sql.DataSource;
import javax.sql.rowset.CachedRowSet;
#ManagedBean
#RequestScoped
public class CustomerBean {
#Resource(name = "jdbc/mydb")
private DataSource ds;
public ResultSet getAll() throws SQLException {
Connection conn = ds.getConnection();
try {
Statement stmt = conn.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM Customers");
CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl();
crs.populate(result);
return crs;
} finally {
conn.close();
}
}
}
'#RequestScoped' should be added to refresh your bean File to get the new data.

Proper place to put initialization code in JSF?

Where is the proper 'place' in JSF to put initialisation snippet that follows, in order to get it executed just one time when the server starts?
1. ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
2. HttpSession sesion = (HttpSession)extContext.getSession(true);
3. String parA = extContext.getInitParameter("parA");
4. String parB = someCalculations(parA);
5. sesion.setAttribute("parB", parB);
Basically I want to read a parameter parA from web.xml context-param section, do some transformations, and include it in session (as new parB parameter).
PostConstructApplicationEvent and eager=true techniques doesn't works because session is null at this point (line 4).
ServletContextListener technique doesn't works because FacesContext isn't available.
Thanks!
There are no sessions at application start time; this requirement is impossible to meet.
I interpret your requirements as:
perform an expensive application-scope calculation
inject this application-scope result into other scopes
The JSF way to do this is via managed beans. Here is an application-scope bean to perform the one-time transformation of the context parameter:
package foo;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
#ManagedBean
#ApplicationScoped
public class SomeCalculationsBean {
#ManagedProperty("#{initParam.paraA}")
private String paraA;
private String someCalculation;
public String getParaA() {
return paraA;
}
public void setParaA(String paraA) {
this.paraA = paraA;
this.someCalculation = //do some transformation
}
public String getSomeCalculation() {
return someCalculation;
}
}
This value can then be injected into other scopes as you need it:
package foo;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class SomeSessionBean {
#ManagedProperty("#{someCalculationsBean.someCalculation}")
private String paraB;
public String getParaB() {
return paraB;
}
public void setParaB(String paraB) {
this.paraB = paraB;
}
}
Code untested. This implementation assumes JSF annotation support but you can do the same thing with faces-config.xml bean configuration.

JSF 2.0: How to override base renderers with custom ones?

I am trying to override renderer for h:selectBooleanCheckbox (for the reasons explained here):
However, I find it impossible to register my renderer. I have tried declaring it in my faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.SelectBoolean</component-family>
<renderer-type>javax.faces.Checkbox</renderer-type>
<renderer-class>com.myapp.CustomCheckboxRenderer</renderer-class>
</renderer>
</render-kit>
The values I grabbed from:
component-family: javax.faces.component.html.HtmlSelectBooleanCheckbox
renderer-type: javax.faces.component.html.SelectBooleanCheckboxTag
But it doesn't work.
I also tried verbosely declaring the RenderKit:
<description>Custom renderers</description>
<render-kit-id>???</render-kit-id>
<render-kit-class>com.sun.faces.renderkit.RenderKitImpl</render-kit-class>
But as you can see, I don't really know where to grab value for render-kit-id or if the render-kit-class is correct anyway.
Inside Mojarra package there is file jsf-ri-runtime.xml but it doesn't declare the renderers. It only declares a RenderKitFactory, under which I don't directly find anything of interest.
Pointers?
Your initial <renderer> declaration looks fine, so I tried it here.
package com.myapp;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import com.sun.faces.renderkit.html_basic.CheckboxRenderer;
public class CustomCheckboxRenderer extends CheckboxRenderer {
public CustomCheckboxRenderer() {
System.out.println("CustomCheckboxRenderer <init>");
}
#Override
public void decode(FacesContext context, UIComponent component) {
System.out.println("CustomCheckboxRenderer decode()");
super.decode(context, component);
}
#Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
System.out.println("CustomCheckboxRenderer encodeBegin()");
super.encodeBegin(context, component);
}
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
System.out.println("CustomCheckboxRenderer encodeEnd()");
super.encodeEnd(context, component);
}
}
It works fine. All get printed to stdout. Your problem lies somewhere else. I was using Mojarra 2.0.3 on Tomcat 7.0.5.
I add renderers to my faces-config.xml like so:
<faces-config>
<!--elided-->
<render-kit>
<render-kit-id>HTML_BASIC</render-kit-id>
<renderer>
<display-name>MyRenderer</display-name>
<component-family>javax.faces.Output</component-family>
<renderer-type>foo.MyRenderer</renderer-type>
<renderer-class>foo.MyRenderer</renderer-class>
<!-- TODO: attributes for tooling -->
You don't need to (and shouldn't) declare a new render kit class in this scenario.

Embedding a link (or other html) in a JSF message

I want to embed a link in a JSF message, is this possible?
When I try it, the rendered html of the h:messages tag escapes the html characters. I tried setting the escape attribute of the h:messages tag to false, but that didn't help.
Unfortunately, this is not possible in the standard JSF implementation. The component and the renderer doesn't officially support this attribute. You can however homegrow a renderer which handles this.
Since this is a pretty common requirement/wish, I thought to take a look what's all possible.
First some background information: JSF by default uses ResponseWriter#writeText() to write the tag body, which escapes HTML by default. We'd like to let it use ResponseWriter#write() instead like as with <h:outputText escape="false" />. We'd like to extend the MessagesRenderer of the standard JSF implementation and override the encodeEnd() method accordingly. But since the MessagesRenderer#encodeEnd() contains pretty a lot of code (~180 lines) which we prefer not to copypaste to just change one or two lines after all, I found it better to replace the ResponseWriter with a custom implementation with help of ResponseWriterWrapper wherein the writeText() is been overriden to handle the escaping.
So, I ended up with this:
package com.example;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ResponseWriterWrapper;
import javax.faces.render.FacesRenderer;
import com.sun.faces.renderkit.html_basic.MessagesRenderer;
#FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages")
public class EscapableMessagesRenderer extends MessagesRenderer {
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
final ResponseWriter originalResponseWriter = context.getResponseWriter();
try {
context.setResponseWriter(new ResponseWriterWrapper() {
#Override
public ResponseWriter getWrapped() {
return originalResponseWriter;
}
#Override
public void writeText(Object text, UIComponent component, String property) throws IOException {
String string = String.valueOf(text);
String escape = (String) component.getAttributes().get("escape");
if (escape != null && !Boolean.valueOf(escape)) {
super.write(string);
} else {
super.writeText(string, component, property);
}
}
});
super.encodeEnd(context, component); // Now, render it!
} finally {
context.setResponseWriter(originalResponseWriter); // Restore original writer.
}
}
}
In spite of the #FacesRenderer annotation, it get overriden by the default MessagesRenderer implementation. I suspect here a bug, so I reported issue 1748. To get it to work anyway, we have to fall back to the faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.Messages</component-family>
<renderer-type>javax.faces.Messages</renderer-type>
<renderer-class>com.example.EscapableMessagesRenderer</renderer-class>
</renderer>
</render-kit>
Then, to trigger it, just do:
<h:messages escape="false" />
And it works! :)
Note: the above affects <h:messages> only. To do the same for <h:message>, just do the same, but replace anywhere "Messages" by "Message" (component family, renderer type and classnames).
The escape="false" attributed you need is provided by the OmniFaces <o:messages> component. The OmniFaces utility library is available for JSF 2.
I posted this solution mentioned by #BalusC's comment as an answer since this is the most straightforward solution.

Resources