JSFカスタムタグとしてキャプチャコンポーネントをビルドしたアプリケーションで問題が発生しました。
私が使用しているJavaEE6Webアプリケーションでは、JSF 2.1 + Jboss Richfaces 4.2.3 + EJB 3.1 + JPA 2.0 + PrettyFaces 3.3.3
次のJSF2カスタムタグがあります。
<tag>
<tag-name>captcha</tag-name>
<source>tags/captcha.xhtml</source>
</tag>
accountEdit.xhtmlという名前のXHTMLページに、キャプチャが表示されています。
<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>
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>
私のweb.xmlで、実行時にキャプチャを生成する要求を処理するCaptchaServletを構成しました。
<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>
私のCaptchaServletの実装:
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();
}
}
Glassfish 3.1.1でこのアプリを実行すると、レンダリング中にサーブレットのdoGet()メソッドが呼び出されます
レンダリングするHttpServletdoGet()メソッドの場合:
<h:graphicImage id="capImg" value="#{facesContext.externalContext.requestContextPath}/../captcha.jpg" />
doGet()はGoogle Chromeに対して1回だけレンダリングされるため、正しくレンダリングされます。
FirefoxおよびIEの場合、doGet()はキャプチャキーを2回更新しますが、ページにペイントされたキャプチャ画像は更新しません。
誰かがこれを修正する方法と、Chromeで他のブラウザとは異なる動作をする理由を知っている人がいたら教えてください。
前もって感謝します!