0

JSF 2.0 でカスタム コンポーネントを作成しました。その目的は、セッション属性値を入力テキスト ボックスに表示することです。メソッドでセッション属性を作成したいHttpSessionListener sessionCreated。問題は、encodeAllメソッドがメソッドの前に呼び出されることsessionCreatedです。sessionCreatedの前に呼び出すにはどうすればよいencodeAllですか?

web.xml

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/components.taglib.xml</param-value>
</context-param>
<listener>
    <listener-class>mycomp.jsf.listener.MyListener</listener-class>
</listener>

components.taglib.xml

<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
            version="2.0">
<namespace>http://mycomp/jsf/components</namespace>
<tag>
    <tag-name>mycomp</tag-name>
    <component>
        <component-type>MyComp</component-type>
    </component>
</tag>
</facelet-taglib>

MyListener.java

public class MyListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    session.setAttribute("sessionid", session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
} 
}

MyComp.java

@FacesComponent(value = "MyComp")
public class MyComp extends UIComponentBase {
public MyComp() {
    setRendererType(null);
}
protected Class getComponentClass() {
    return this.getClass();
}
@Override
public void decode(FacesContext context) {
//some logic
}
@Override
public void encodeAll(FacesContext context) throws IOException {
    String clientId = getClientId(context) + ":token";
    HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
    String sessionId = (String) session.getAttribute("sessionid");
    if (sessionId == null || "".equals(sessionId)) {
        throw new RuntimeException("sessionid is missing!");
    }
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("input", this);
    writer.writeAttribute("type", "text", "type");
    writer.writeAttribute("name", clientId, "name");
    writer.writeAttribute("value", sessionId, "value");
    writer.endElement("input");
}
@Override
public String getFamily() {
    return null;
}
}

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:t="http://mycomp/jsf/components">
<h:head>
</h:head>
<h:body>
    <h:form>
        <t:mycomp />
    </h:form>
</h:body>
</html>
4

1 に答える 1

0

getSession(false)で置き換えgetSession(true)ます。

HttpSession session = (HttpSession) context.getExternalContext().getSession(true);

ブール値は、セッションがまだ作成されていない場合に、セッションを作成する必要があるかどうかを示します。したがって、その時点でまだ作成されていないため、メソッドを呼び出すたびにgetSession(false)を取得するリスクがあります。javadocも参照してください。nullNullPointerException


具体的な問題とは関係なく、代わりにクリーナーを使用しExternalContext#getSessionMap()ます。JSFコードに「生の」javax.servletインポートがあるということは、通常、JSFコードに臭いがあることを示しています。つまり、何かが不必要に過度に複雑に行われています。次に、純粋な JSF API を使用してより簡単な方法を探す必要があります。

交換

HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
    throw new RuntimeException("sessionid is missing!");
}

String sessionId = (String) context.getExternalContext().getSessionMap().get("sessionid");
if (sessionId == null || "".equals(sessionId)) {
    throw new RuntimeException("sessionid is missing!");
}
于 2012-04-13T13:56:29.597 に答える