0

純粋な JSF 2 ページに問題があります。ページをロードすると、2 つの inputText と 1 つの select が表示されます。それぞれの右側に検証フィールドがあります。2 つの入力は必須フィールドですが、select には常に選択があるため、まったく検証されません (少なくとも検証すべきではありません)。

スクリーンショットは次のとおりです。

ここに画像の説明を入力

これは、[作成] ボタンをクリックしたときに表示されるものです。[作成] ボタンをもう一度押すと、次のポップアップが表示されます。

ここに画像の説明を入力

OK、コードなしでは何もありません。XHTML は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<!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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
  </h:head>
  <h:body>
    <h:form>
      <h:panelGrid columns="3" id="base-data-grid">
        <h:outputLabel value="Name:*" for="name-input" />
        <h:inputText value="#{testBean.name}"
                     requiredMessage="Name required!"
                     id="name-input">
          <f:validateRequired />
        </h:inputText>
        <h:message for="name-input" style="color: red;" />
        <h:outputLabel value="Code:*" for="code-input" />
        <h:inputText value="#{testBean.code}"
                     requiredMessage="Code required!"
                     id="code-input">
          <f:validateRequired />
        </h:inputText>
        <h:message for="code-input" style="color: red;" />
        <h:outputLabel value="Location:" for="location-select" />
        <h:selectOneMenu value="#{testBean.location}"
                         converter="#{testConverter}"
                         id="location-select">
          <f:selectItems value="#{testBean.locations}"
                         var="l"
                         itemValue="#{l}"
                         itemLabel="#{l.name}" />
        </h:selectOneMenu>
        <h:message for="location-select" style="color: red;" />
      </h:panelGrid>
      <h:panelGrid columns="1">
        <h:commandButton value="Create"
                           action="#{testBean.create}">
          <f:ajax execute="base-data-grid" render="base-data-grid lalala" />
        </h:commandButton>
      </h:panelGrid>
      <h:messages id="lalala" />
    </h:form>
  </h:body>

</html>

select のロケーション クラス (名前のみ):

public class Location
{
    private String name;
    public Location(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return name;
    }
}

コンバーター (CDI バージョンとして):

import javax.enterprise.context.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
@RequestScoped
public class TestConverter implements Converter
{
    private static final Logger log = LoggerFactory.getLogger(TestConverter.class);

    @Inject
    private TestBean testBean;

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String name)
    {
        log.info(getClass().getSimpleName() + ".getAsObject: " + name);

        return testBean.getLocationFor(name);
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
    {
        log.info(getClass().getSimpleName() + ".getAsString: " + obj);

        return ((Location)obj).getName();
    }
}

そしてテスト Bean:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
@SessionScoped
public class TestBean implements Serializable
{
    private static final Logger log = LoggerFactory.getLogger(TestBean.class);

    private String name;
    private String code;

    private Location location;
    private List<Location> locations;

    @PostConstruct
    public void init()
    {
        locations = new ArrayList<Location>();

        locations.add(new Location("Berlin"));
        locations.add(new Location("London"));
        locations.add(new Location("New York"));
        locations.add(new Location("Moscow"));
        locations.add(new Location("Bejing"));

        location = locations.get(2);
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getCode()
    {
        return code;
    }

    public void setCode(String code)
    {
        this.code = code;
    }

    public Location getLocation()
    {
        return location;
    }

    public void setLocation(Location location)
    {
        this.location = location;
    }

    public List<Location> getLocations()
    {
        return locations;
    }

    public void setLocations(List<Location> locations)
    {
        this.locations = locations;
    }

    public void create()
    {
        log.info("Creating new whatever...");
    }

    // for converter to mimic DB query
    public Location getLocationFor(String name)
    {
        for ( Location location : locations )
        {
            if ( location.getName().equals(name) )
            {
                return location;
            }
        }

        return null;       
    }

}

ご覧のとおり、このページで行うべきことはあまりありません。2 つの入力フィールドを検証し、select を表示して、すべてが正常に検証された場合は testBean.create を呼び出します。

ただし、検証が 1 回実行されるとすぐに、その後の [作成] ボタンをクリックするたびにその serverError が発生します。

f:selectItems または h:selectOneMenu を完全に削除すると、ページは期待どおりに機能することに注意してください。これが実際に全体をとても奇妙にしている理由です...

ここで何が起こっているのかわかりません。誰が何が悪いのか知っていますか?

ここに JBoss AS 7 テスト アプリを添付しました: https://community.jboss.org/thread/202501 (だまされた投稿、申し訳ありませんが、多くの助けが必要です)。

この非常に奇妙な IllegalStateException を見てください。JBAS server.log には何もありません...

PS: Mojarra のバージョンはもちろん 2.1.7 です (JBoss AS 7.1.1.Final に付属するもの)。

4

1 に答える 1

1

あなたの問題は、Locationシリアライズ可能にする必要があることです
(インターフェースを実装しjava.io.Serializableます)

このf:validateRequiredタグにより、必要な検証が ajax によって実行されます。

この ajax リクエストの RestoreView フェーズ中に、場所がシリアライズ可能でないため、ランタイムは InstantiationException に遭遇します。

スタックトレースを含むエラーがログに記録されない理由は正直わかりません。

于 2012-07-12T08:37:37.157 に答える