How to refresh the meta tags in h:head? - jsf-2

In jsf2 when I have PROJECT_STAGE = Production my h:head part is not refreshed. When I change it to Development, then everything works fine. How to force the head part for being refreshed?
The h:head is in template.xhtml.
template.xhtml:
<h:head>
<meta name="description" content="#{metaBean.metaDescription}" />
<meta name="keywords" content="#{metaBean.metaKeywords}" />
</h:head>
web.xml
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<!-- <param-value>Development</param-value>-->
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>0</param-value>
</context-param>
...Or How to make dynamic meta description in other way?
Thank you

You can use meta filter like this
public class HtmlMetaFilter implements Filter {
private List<String> metaNames = null;
private List<String> metaValues = null;
private int metaSize = 0;
#Override
public void destroy() {
// logger.info("html meta filter destroyed.");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
for(int i = 0; i < metaSize; i++) {
res.setHeader(metaNames.get(i), metaValues.get(i));
}
chain.doFilter(request, res);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
metaNames = Configuration.getInstance().getList("//configuration/web-app/html-meta/name");
metaValues = Configuration.getInstance().getList("//configuration/web-app/html-meta/value");
if(metaNames != null && metaValues != null) {
metaSize = Math.min(metaNames.size(), metaValues.size());
}
// logger.info("html meta filter initialized.");
}
}
If you want to change it dynamically, then you need to set the different data in init method from your bean file.

I've found answer on this post: title in h:head rendered before render response phase?
It's enough to use event preRenderView and prepare necessary values in it.

Related

RequestDispatcher return me PWC6199: Generated servlet error

Hello when I try to use requestDispatcher it does not forward the URL. I retrieve this strange error
PWC6199: Generated servlet error:
source value 1.5 is obsolete and will be removed in a future release
PWC6199: Generated servlet error:
target value 1.5 is obsolete and will be removed in a future release
PWC6199: Generated servlet error:
To suppress warnings about obsolete options, use -Xlint:-options.
I tried with sendredirect without success. What is wrong ?
My simple servlet MyServletSennesal is :
'import com.senesal.moustac.Utilisateur;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;<
public class MyServletSennesal extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
System.out.println("Je suis dans la servlet sennesal");
HttpSession unesession = request.getSession(true);
String prenom = request.getParameter("txtprenom");
String nom = request.getParameter("txtnom");
Utilisateur usn = new Utilisateur(prenom, nom);
unesession.setAttribute("utilisateur", usn);
System.out.println("le User est ----->"+usn);
System.out.println("La session est ----->" +unesession);
String myurl="/WEB-INF/PageError.jsp";
RequestDispatcher rd;
if(unesession!=null){
myurl="/WEB-INF/bienvenue.jsp";
System.out.println("Premiere conditionnelle");
System.out.println("L'url --->" +myurl);
//getServletContext().getRequestDispatcher(myurl);
rd= request.getRequestDispatcher(myurl);
rd.forward(request, response);
//response.sendRedirect(myurl);
}else{
System.out.println("Seconde conditionnelle");
//getServletContext().getRequestDispatcher(myurl).include(request, response);
rd= request.getRequestDispatcher(myurl);
rd.forward(request, response);
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* #return a String containing servlet description
*/
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
My Web.xml
'<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>`
My Bienvenue.jsp file
'<%#page import="com.senesal.moustac.Utilisateur"%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Bienvue</title>
</head>
<body>
<%
Utilisateur usr =(Utilisateur) session.getAttribute("utilisateur");
System.out.println("On est dans la JSP bienvenu");
System.out.println("Utilisateur ---->" +usr);
if (usr!=null){%>
<h1>Hello Bienvenu</h1>
<%} else {
System.out.println("probleme dans la jsp");
response.sendRedirect("PageError.jsp");
}%>
<% }%>
</body>
</html>'
MyPageError.jsp
'<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Page Error</title>
</head>
<body>
<p>Une anomalie s'est produite </p>
<p>Retournez au départ</p>
</body>
</html>'
My class User aka Utilisateur
'package com.senesal.moustac;
public class Utilisateur {
private String strprenom;
private String strnom;
public Utilisateur() {
}
public Utilisateur(String strprenom, String strnom) {
this.strprenom = strprenom;
this.strnom = strnom;
}
public String getStrprenom() {
return strprenom;
}
public void setStrprenom(String strprenom) {
this.strprenom = strprenom;
}
public String getStrnom() {
return strnom;
}
public void setStrnom(String strnom) {
this.strnom = strnom;
}
#Override
public String toString() {
String strchaine = this.getStrprenom()+", "+this.getStrnom();
return strchaine;
}
}'
My project structure
Sorry for the image I did it non clickable because I don't know your politic regarding the imagehostigs websites. I prefer to avoid problem, if you don't have problem with Flickr notice me, and I will be set this link clickable.
https www flickr _com_photos_ 44522526# N06_34997725050 _ in_ dateposted-public

Swagger interacting with Resteasy not listing content api

We're trying to have Swagger interact with our resteasy app so that the api will list out on the swagger page. We're using annotations in the Java resources and not a yaml/json file. We want the content to be 'dynamic' or come directly from the resource pages.
When we bring up the swagger page, we get the message 'fetching resource list: //10.155.63.136/nodeMgmt'. When I render the page using firebug, I see that the page itself (index.html) is being 'fed in' to the content.
I think I'm pretty close but am missing one or two small things. I used the example as a guide to what I did: https://github.com/mrj365/RestEasy-3.09-Spring-3.2.5-Swagger2.0
Again, the issue is that the content from the resteasy api is not being fed into the swagger ui. The url in my case is https://10.155.63.92/nodeMgmt/index.html
We're using JBoss 6.4, NO Spring, Resteasy 3.0.7, Swagger jaxrs 1.5.9.
Any help is really appreciated.
Index.html
<script type="text/javascript">
$(function () {
window.swaggerUi = new SwaggerUi({
url: "/nodeMgmt",
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
onComplete: function(swaggerApi, swaggerUi){
log("Loaded SwaggerUI");
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none"
});
web.xml
<!-- Auto scan REST service -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/nodes</param-value>
</context-param>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>com.sonus.unity.sonusbaserestservice.utils.ApiOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/index.html</url-pattern>
</filter-mapping>
<!-- if you are using Spring, Seam or EJB as your component model, remove the ResourceMethodSecurityInterceptor -->
<context-param>
<param-name>resteasy.resource.method-interceptors</param-name>
<param-value>
org.jboss.resteasy.core.ResourceMethodSecurityInterceptor
</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.sonus.ems.nodemgmt.web.NodeMgmtApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/nodes/*</url-pattern>
</servlet-mapping>
application.java
#ApplicationPath("")
public class NodeMgmtApplication extends SonusBaseRestApplication {
private static final Logger log = Logger.getLogger(NodeMgmtApplication.class);
/**
* Constructor
*/
public NodeMgmtApplication() {
super();
try {
//TODO Swagger
// Used for defining swagger
BeanConfig beanConfig = new BeanConfig();
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setVersion("1.5.9");
beanConfig.setBasePath("/nodeMgmt");
beanConfig.setResourcePackage("com.sonus.ems.nodemgmt.web");
//beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
addService(new NodeMgmtAuthorizationFilter());
addService(new NodeMgmtRestService());
// Swagger
addService(new ApiListingResource());
addService(new SwaggerSerializers());
} catch (Exception e) {
log.error("NodeAdminApplication: Could not instantiate singletons " + e);
}
}
resource.java
#Path("/")
#Api(value = "/", description = "Node operations", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
public class NodeMgmtRestService {
private static final Logger log = Logger.getLogger(NodeMgmtRestService.class);
private static final String NODES = "nodes";
private static final String ID = "id";
NodeMgmtServiceProvider nodeMgmtServiceProvider = new NodeMgmtServiceProvider();
Service nodeMgmtService;
#GET
#Path("/{version}")
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Get all nodes", notes = "Returns a list of node", response = String.class, responseContainer="List")
public Response getNodes(
#ApiParam(value = "Version of api (1.0)", required = true) #PathParam("version") String version,
#ApiParam(value = "Filter by ", required = true) #QueryParam("filterParam") String filterParam,
#ApiParam(value = "Filter value ", required = true) #QueryParam("filterValue") String filterValue) {
List<Node> nodeList = new ArrayList<Node>();
List<Object> nodeJsonList = new ArrayList<Object>();
Map<String, List<Object>> nodeJsonMap = new HashMap<String, List<Object>>();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> responseId = new HashMap<String, String>();
JsonNodeDao jsonNodeDao = new JsonNodeDao();
Swagger API key
public class ApiOriginFilter implements Filter {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
// Add access to the header
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS");
res.addHeader("Access-Control-Allow-Headers", "Content-Type, api_key, Authorization");
//res.addHeader("Access-Control-Allow-Headers", "Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date, Content-Type, api_key, Authorization, X-Atmosphere-Transport, x-requested-with, Total-Count, Total-Pages, Error-Message, *");
//res.addHeader("Access-Control-Request-Headers", "Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date, Content-Type, api_key, Authorization, X-Atmosphere-Transport, x-requested-with, Total-Count, Total-Pages, Error-Message, *");
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}

JSF 2 Captcha using <h:graphicImage rendering twice for Servlet generated image value working only for Chrome

I have an issue in my application using where I have a Captcha component built as a JSF Custom Tag:
in my JavaEE 6 webapp I use:
JSF 2.1 + Jboss Richfaces 4.2.3 + EJB 3.1 + JPA 2.0 + PrettyFaces 3.3.3
I have a JSF2 custom tag that is:
<tag>
<tag-name>captcha</tag-name>
<source>tags/captcha.xhtml</source>
</tag>
in my XHTML page called accountEdit.xhtml I have the captcha being displayed:
<ui:fragment rendered="#{customerMB.screenComponent.pageName eq 'create'}">
<div class="form_row">
<label class="contact"><strong>#{msg.captcha}:</strong>
</label>
<atl:captcha></atl:captcha>
</div>
</ui:fragment>
in captcha.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<table border="0">
<tr>
<td>
<h:graphicImage id="capImg" value="#{facesContext.externalContext.requestContextPath}/../captcha.jpg" />
</td>
<td><a4j:commandButton id="resetCaptcha" value="#{msg.changeImage}" immediate="true" action="#{userMB.resetCaptcha}" >
<a4j:ajax render="capImg" execute="#this" />
</a4j:commandButton></td>
</tr>
<tr>
<td><h:inputText value="#{userMB.captchaComponent.captchaInputText}" /></td>
</tr>
</table>
</ui:composition>
in my web.xml I have configured a CaptchaServlet that handles the request for generating a captcha during runtime:
<servlet>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>com.myapp.web.common.servlet.CaptchaServlet</servlet-class>
<init-param>
<description>passing height</description>
<param-name>height</param-name>
<param-value>30</param-value>
</init-param>
<init-param>
<description>passing width</description>
<param-name>width</param-name>
<param-value>120</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/captcha.jpg</url-pattern>
</servlet-mapping>
My CaptchaServlet implementation:
public class CaptchaServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 6105436133454099605L;
private int height = 0;
private int width = 0;
public static final String CAPTCHA_KEY = "captcha_key_name";
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
height = Integer
.parseInt(getServletConfig().getInitParameter("height"));
width = Integer.parseInt(getServletConfig().getInitParameter("width"));
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse response)
throws IOException, ServletException {
// Expire response
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Max-Age", 0);
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = image.createGraphics();
Hashtable<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();
Random r = new Random();
String token = Long.toString(Math.abs(r.nextLong()), 36);
String ch = token.substring(0, 6);
Color c = new Color(0.6662f, 0.4569f, 0.3232f);
GradientPaint gp = new GradientPaint(30, 30, c, 15, 25, Color.white,
true);
graphics2D.setPaint(gp);
Font font = new Font("Verdana", Font.CENTER_BASELINE, 26);
graphics2D.setFont(font);
graphics2D.drawString(ch, 2, 20);
graphics2D.dispose();
HttpSession session = req.getSession(true);
session.setAttribute(CAPTCHA_KEY, ch);
OutputStream outputStream = response.getOutputStream();
ImageIO.write(image, "jpeg", outputStream);
outputStream.close();
}
}
When I run this app on Glassfish 3.1.1
when the Servlet's doGet() method is called while rendering
for the HttpServlet doGet() method that renders:
<h:graphicImage id="capImg" value="#{facesContext.externalContext.requestContextPath}/../captcha.jpg" />
doGet() renders only once for Google Chrome, thus rendering correctly.
For Firefox and IE doGet() renders twice updating the Captcha Key but not updating the painted Captcha Image on the page.
If anyone might know what could be a fix for this and why it has this behavior for Chrome different from other browsers please let me.
Thanks in advance!
The browser is caching the response. Your attempt to avoid this is incomplete and incorrect:
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Max-Age", 0);
Please refer How to control web page caching, across all browsers? for the proper set:
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
Further, to make it more robust, add a query string with the current timestamp in millis to the image URL. Here's an example provided that you've a java.util.Date instance as managed bean with the name now:
<h:graphicImage id="capImg" value="#{request.contextPath}/../captcha.jpg?#{now.time}" />
(please note that I also simplified the way to get the request context path, I only don't understand how it's useful if you go to domain root by ../ anyway)
I found a solution for this, is not the optimal solution but it works, here it goes:
captcha.xhtml
<table border="0">
<tr>
<td>
<h:graphicImage url="#{request.contextPath}/../jcaptcha"/>
</td>
<td>
<input type='text' name='j_captcha_response' value='' />
</td>
</tr>
</table>
CaptchaServlet doGet method:
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
byte[] captchaChallengeAsJpeg = null;
// the output stream to render the captcha image as jpeg into
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
//the same id must be used to validate the response, the session id is a good candidate!
String captchaId = httpServletRequest.getSession().getId();
// call the ImageCaptchaService getChallenge method
BufferedImage challenge =
CaptchaServiceSingleton.getImageChallengeForID(captchaId,
httpServletRequest.getLocale());
// a jpeg encoder
JPEGImageEncoder jpegEncoder =
JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (CaptchaServiceException e) {
httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
// flush it in the response
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream =
httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}
created CaptchaServiceRequestSingleton.java
package com.myapp.web.common.listener;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Locale;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;
public class CaptchaServiceSingleton {
private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService();
private static final int MAX_CACHE_SIZE = 200;
private static HashMap<String, BufferedImage> captchaImgCache = new HashMap<String, BufferedImage>();
public static ImageCaptchaService getInstance(){
return instance;
}
public static BufferedImage getImageChallengeForID(String id, Locale locale) {
if (captchaImgCache.containsKey(id)) {
return captchaImgCache.get(id);
} else {
BufferedImage bImage = instance.getImageChallengeForID(id, locale);
// if limit reached reset captcha cache
if (captchaImgCache.size() > MAX_CACHE_SIZE) {
captchaImgCache = new HashMap<String, BufferedImage>();
}
captchaImgCache.put(id, bImage);
return bImage;
}
}
public static void resetImageChallengeForID(String id) {
if (captchaImgCache.containsKey(id)) {
captchaImgCache.remove(id);
}
}
}
when clicking on "Create Account" button Captcha is reset:
CustomerMB.openCreateCustomerAccount():
public String openCreateCustomerAccount() {
customerAccountEditVO = new CustomerAccountVO();
screenComponent.setPageName(NameConstants.CREATE);
getUserMB().resetCaptcha();
return null;
}
in UserMB.resetCaptcha():
public String resetCaptcha() {
CaptchaServiceSingleton.resetImageChallengeForID(JSFUtil.getRequest().getRequestedSessionId());
return null;
}
Perhaps it's not the perfect solution but at least it's working for all Browsers.

JSF h:commandLink not work with filter

I create simple login system for my jsf project.
In project I create filter to check user login status.
If login, continue to requested page.
If not login or session is destroy, redirect to login page
My problem is, if I apply filter then all of h:commandLink not process anything after clicked. But when I remove filter, everything work well.
I try to use h:commandButton with fileter, then everthing work correctly.
How can I fixed this problem?
I research for a long time, but not found any solution.
Please help me!
Filter code:
#WebFilter(filterName = "AuthenticationFilter", urlPatterns = {"*.htm"}, dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
public class AuthenticationFilter implements Filter {
// The filter configuration object we are associated with. If
// this value is null, this filter instance is not currently
// configured.
private FilterConfig filterConfig = null;
#Inject
private AuthenticationManager authenticationManager;
public AuthenticationFilter() {
}
/**
* #param request The servlet request we are processing
* #param response The servlet response we are creating
* #param chain The filter chain we are processing
*
* #exception IOException if an input/output error occurs
* #exception ServletException if a servlet error occurs
*/
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Throwable problem = null;
try {
HttpServletRequest req = (HttpServletRequest) request;
String requestUrl = req.getRequestURI();
String contextPath = req.getContextPath();
if(contextPath.equals("/")){
contextPath = "";
}
String jsfUrl = requestUrl.replaceFirst(contextPath, "");
if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
chain.doFilter(request, response);
}
else {
String redirectPath = contextPath+"/login.htm";
((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
}
}
catch (Throwable t) {
// If an exception is thrown somewhere down the filter chain,
// we still want to execute our after processing, and then
// rethrow the problem after that.
problem = t;
}
// If there was a problem, we want to rethrow it if it is
// a known type, otherwise log it.
if (problem != null) {
if (problem instanceof ServletException) {
throw (ServletException) problem;
}
if (problem instanceof IOException) {
throw (IOException) problem;
}
sendProcessingError(problem, response);
}
}
/**
* Return the filter configuration object for this filter.
*/
public FilterConfig getFilterConfig() {
return (this.filterConfig);
}
/**
* Set the filter configuration object for this filter.
*
* #param filterConfig The filter configuration object
*/
public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
if (filterConfig != null) {
}
}
}
Jsf code:
<h:body>
<f:view contentType="text/html" locale="#{authenticationManager.languageCode}">
<div class="header">
<h:form id="topForm" prependId="false">
<div class="logo">
<h1><img src="#{facesContext.externalContext.requestContextPath}/resources/images/login-logo2.png" width="220" height="64"/></h1>
</div>
<ul class="navTop">
<li>
<span class="pictograms">f</span>#{authenticationManager.currentUser.firstName} #{authenticationManager.currentUser.lastName}
</li>
<li>
<span class="pictograms">m</span>Messages
</li>
<li class="logout">
<h:commandButton action="#{authenticationManager.logout()}" value="aaaaaaa" style="color:#fff;" />
<h:commandLink action="#{authenticationManager.logout()}" value="#{label.Logout}"/>
<h:commandLink immediate="true" action="#{authenticationManager.logout}" id="logoutLink">
<span class="pictograms">E</span>***This link is not work correctly***
</h:commandLink>
</li>
</ul>
<ui:insert name="mainmenu"/>
</h:form>
</div>
Your concrete problem is caused because the serving of the JSF default resource jsf.js has been blocked by the filter. This resource is mandatory for functioning of JSF command links and JSF ajax requests (plain command buttons without ajax will just work).
You need to exclude JSF resources from the authentication check. You can do that by just checking if the request URI starts after the webapp context path with ResourceHandler.RESOURCE_IDENTIFIER (which has a value of /javax.faces.resource).
So, basically:
HttpServletRequest req = (HttpServletRequest) request;
if (req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
chain.doFilter(request, response); // Let it continue.
return;
}
Checking the file extensions is clumsy and does not sufficiently cover all possible resource requests.
After research, I didn't found any solution.
So I guest to many possible ways, and found the explanation about this.
I filter everything with filter pattern "*.htm", then every request like .js.htm, .css.htm, .gif.htm, .jpg.htm will redirected to login.htm page.
The point is redirect .js.htm to login page instead of right file.
So the important library like jsf.js.htm was redirect to login.htm, this is the main cause to make h:commandLink work not correctly.
Hop this will help someone, like me.
try {
HttpServletRequest req = (HttpServletRequest) request;
String requestUrl = req.getRequestURI();
if(requestUrl.endsWith(".js.htm")
|| requestUrl.endsWith(".css.htm")
|| requestUrl.endsWith(".gif.htm")
|| requestUrl.endsWith(".png.htm")
|| requestUrl.endsWith(".jpg.htm")
|| requestUrl.endsWith(".jpeg.htm")){
chain.doFilter(request, response);
}
else{
String contextPath = req.getContextPath();
if(contextPath.equals("/")){
contextPath = "";
}
String jsfUrl = requestUrl.replaceFirst(contextPath, "");
if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
chain.doFilter(request, response);
}
else {
String redirectPath = contextPath+"/login.htm";
((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
}
}
}

<p:graphicImage> not rendering image

I have a JSF page where I want to show a image. The image is stored in the database as a blob.
The entity looks like this:
#Entity
public class Player
{
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
#Lob
private byte[] pictureData;
#Transient
private StreamedContent streamedPicture;
public StreamedContent getStreamedPicture()
{
if (streamedPicture == null && pictureData != null)
{
try
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(pictureData);
streamedPicture = new DefaultStreamedContent(
new ByteArrayInputStream(
os.toByteArray()),
"image/png");
}
catch (FileNotFoundException e)
{}
catch (IOException e)
{}
}
return streamedPicture;
}
}
The JSF page is this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<body>
<ui:repeat var="player" value="#{playerbean.cachedPlayers}">
<h:outputText value="#{player.id}" />
<p:graphicImage value="#{player.streamedPicture}" rendered="#{player.streamedPicture != null}"/>
</ui:repeat>
</body>
</html>
And the bean I call looks like this:
#ManagedBean(name = "playerbean")
#SessionScoped
public class PlayerBean
implements Serializable
{
#EJB
private PlayerManager playerManager;
private List<Player> cachedPlayers;
public List<Player> getCachedPlayers()
{
if (cachedPlayers == null)
{
cachedPlayers = playerManager.getAll();
}
return cachedPlayers;
}
}
While debugging I set a breakpoint in PrimeResourceHandler in the method handleResourceRequest(). The code of the PrimeResourceHandler I'm looking at contains this:
try {
String dynamicContentEL = (String) session.get(dynamicContentId);
ELContext eLContext = context.getELContext();
ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class);
StreamedContent content = (StreamedContent) ve.getValue(eLContext);
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType(content.getContentType());
byte[] buffer = new byte[2048];
int length;
InputStream inputStream = content.getStream();
while ((length = (inputStream.read(buffer))) >= 0) {
response.getOutputStream().write(buffer, 0, length);
}
response.setStatus(200);
response.getOutputStream().flush();
context.responseComplete();
} catch(Exception e) {
logger.log(Level.SEVERE, "Error in streaming dynamic resource.");
} finally {
session.remove(dynamicContentId);
}
When passing the line StreamedContent content = (StreamedContent) ve.getValue(eLContext); content appears to be null. This of course causes a NullPointerException. However in the JSF page I told the element not to render if the value is null.
The <p:graphicImage> component cannot have a value attribute that points to a managed property within a SessionScoped bean. The value must be set to a RequestScoped bean.
This is because an HTTP request for an image/jpeg content type HTTP response is inherently stateless. The browser will make the initial request for the JSF page content, then for every HTML <img> tag that is rendered it will make seperate requests to the dynamically generated url of each <img> tag to fetch these. Fetching an image in a stateful context doesn't really make sense.

Resources