0

簡単な要約:

プロジェクト: リストをフィルタリングして外部コンポーネントを更新できる複合コンポーネント

問題: myfaces 2.1.10 は動作しますが、mojarra 2.2.1 は動作しませんが、jsf 2.2 を使用したい

複合コンポーネントfilteredList.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:composite="http://java.sun.com/jsf/composite" xmlns:ui="http://java.sun.com/jsf/facelets">
  <composite:interface>
    <composite:attribute name="label" required="false" default="filter" type="java.lang.String" />
    <composite:attribute name="filter" required="true" type="java.lang.String" />
    <composite:attribute name="list" required="true" type="java.util.List" />
    <composite:attribute name="valueMask" required="false" type="" />
    <composite:attribute name="outputId" required="false" type="java.lang.String" />
    <composite:attribute name="height" required="false" default="128" type="java.lang.Integer" />
    <composite:attribute name="width" required="false" default="128" type="java.lang.Integer" />
    <composite:attribute name="destinationId" required="false" type="java.lang.String" />
    <composite:attribute name="rowClasses" required="false" type="java.lang.String" />
    <composite:attribute name="hoverClass" required="false" default="" type="java.lang.String" />
    <composite:attribute name="innerCellClasses" required="false" default="" type="java.lang.String" />
    <composite:attribute name="repeatClassOdd" required="false" default="" type="java.lang.String" />
    <composite:attribute name="repeatClassEven" required="false" default="" type="java.lang.String" />
  </composite:interface>
  <composite:implementation>
    <h:outputStylesheet name="css/elements.css" />
    <h:panelGrid columns="2">
      <h:outputText value="#{composite.attrs.label}" />
      <h:inputText id="filterfield" value="#{composite.attrs.filter}">
        <f:ajax event="keyup" render="table" />
      </h:inputText>
    </h:panelGrid>
    <div id="box#{cc.clientId}" style="overflow: auto">
      <h:dataTable id="table" value="#{composite.attrs.list}" var="elem" rowClasses="#{composite.attrs.rowClasses}">
        <h:column>
          <div id="choose#{elem.id}" style="cursor: pointer" class="#{composite.attrs.hoverClass}">
            <h:outputText value="#{elem.html}" rendered="#{elem.renderHtml}" />
            <h:dataTable value="#{elem.list}" var="l" rendered="#{elem.renderDatatable}" rowClasses="#{composite.attrs.innerCellClasses}">
              <h:column>
                <h:outputText value="#{l}" />
              </h:column>
            </h:dataTable>
            <ui:repeat value="#{elem.list}" var="l" varStatus="index" rendered="#{elem.renderRepeat}" columnClasses="#{composite.attrs.innerCellClasses}">
              <div class="#{index.odd ? composite.attrs.repeatClassOdd : composite.attrs.repeatClassEven}" style="display: inline">
                <h:outputText value="#{l}" />
              </div>
            </ui:repeat>
          </div>
          <ui:fragment rendered="#{composite.attrs.destinationId != null}">
            <script type="text/javascript">
              $(document).ready(function(){
                $("[id='choose#{elem.id}']").click(function(){
                  $("[id='#{composite.attrs.destinationId}']").val("#{elem.id}");
                  <ui:fragment rendered="#{cc.attrs.valueMask != null}">
                    $("[id='#{composite.attrs.outputId}']").text("#{composite.attrs.valueMask.getMask(elem.id)}");
                  </ui:fragment>
                  $("[id='#{composite.attrs.destinationId}']").trigger('change');
                });
              });
            </script>
          </ui:fragment>
        </h:column>
      </h:dataTable>
    </div>
    <script type="text/javascript">
      $(document).ready(function(){
        $("[id='box#{composite.clientId}']").height(#{composite.attrs.height}).width(#{composite.attrs.width});
      });
    </script>
  </composite:implementation>
</ui:composition>

このコンポーネントの使用法:

<mycomponent:filteredList valueMask="#{testAction.valueMask}" label="label.filter" list="#{testAction.listFilter.list}" filter="#{testAction.listFilter.filter}" height="128" width="384" rowClasses="odd,even" hoverClass="hoverClass" inputfieldClasses="stayontop,stayontop" repeatClassOdd="oddy"
        repeatClassEven="eveny" />

使用クラス TestFilter:

public class TestFilter implements FilterInterface
{
  private String filter;

  @Override
  public List<ListFilterElem> doFilter(List<ListFilterElem> unfilteredList)
  {
    if (filter == null || filter.trim().equals(""))
    {
      return unfilteredList;
    }
    else
    {
      String[] s = filter.split("\\s+");
      Set<ListFilterElem> filtered = new LinkedHashSet<ListFilterElem>();
      for (String f : s)
      {
        for (ListFilterElem e : unfilteredList)
        {
          if (e.containsIgnoreCase(f))
          {
            filtered.add(e);
          }
        }
      }
      return new ArrayList<ListFilterElem>(filtered);
    }
  }

  @Override
  public String getFilter()
  {
    return filter;
  }

  @Override
  public void setFilter(String filter)
  {
    this.filter = filter;
  }
}

使用クラス TestListFilterElem:

public class TestListFilterElem implements ListFilterElem
{
  private Integer id;
  private List<String> subList;

  public TestListFilterElem(Integer id, List<String> subList)
  {
    this.id = id;
    this.subList = subList;
  }

  @Override
  public String getHtml()
  {
    StringBuilder buf = new StringBuilder();
    for (String s : subList)
    {
      buf.append(s);
      buf.append(" ");
    }
    return buf.toString();
  }

  @Override
  public Integer getId()
  {
    return id;
  }

  @Override
  public Boolean containsIgnoreCase(String needle)
  {
    return getHtml().toLowerCase().contains(needle.toLowerCase());
  }

  @Override
  public List<String> getList()
  {
    return subList;
  }

  @Override
  public Boolean getRenderDatatable()
  {
    return false;
  }

  @Override
  public Boolean getRenderHtml()
  {
    return false;
  }

  @Override
  public Boolean getRenderRepeat()
  {
    return true;
  }
}

使用クラス ListFilter:

public class ListFilter
{
  private List<ListFilterElem> list;
  private FilterInterface filterInterface;

  public ListFilter(FilterInterface filterInterface)
  {
    this.filterInterface = filterInterface;
    list = new ArrayList<ListFilterElem>();
  }

  public void addListElem(ListFilterElem elem)
  {
    list.add(elem);
  }

  public void addListElems(List<ListFilterElem> elems)
  {
    list.addAll(elems);
  }

  public List<ListFilterElem> getList()
  {
    return filterInterface.doFilter(list);
  }

  public void setFilter(String filter)
  {
    filterInterface.setFilter(filter);
  }

  public String getFilter()
  {
    return filterInterface.getFilter();
  }
}

使用クラス マスク:

public class Mask implements MaskInterface
{
  private Integer ensureInteger(Object o) throws Exception
  {
    if (o == null)
    {
      return null;
    }
    else if (o instanceof Integer)
    {
      return (Integer) o;
    }
    else if (o instanceof String)
    {
      return new Integer((String) o);
    }
    else
    {
      throw new Exception("cannot convert " + o.getClass() + " to Integer");
    }
  }

  @Override
  public String getMask(Object o)
  {
    try
    {
      switch (ensureInteger(o))
      {
        case 1: return "first line";
        case 2: return "second line";
        case 3: return "third line";
        default: return "unknown";
      }
    }
    catch (Exception e)
    {
      return e.getMessage();
    }
  }
}

使用クラス ValueMask:

public class ValueMask
{
  private MaskInterface maskInterface;

  public ValueMask(MaskInterface maskInterface)
  {
    this.maskInterface = maskInterface;
  }

  public String getMask(Object o)
  {
    return maskInterface.getMask(o);
  }
}

使用クラス TestAction:

@ManagedBean
@SessionScoped
public class TestAction
{
  private ListFilter listFilter;
  private String variable;

  public ListFilter getListFilter()
  {
    if (listFilter == null)
    {
      listFilter = new ListFilter(new TestFilter());
      listFilter.addListElem(new TestListFilterElem(1, Arrays.asList(new String[]{"this", "is", "the", "first", "list"})));
      listFilter.addListElem(new TestListFilterElem(2, Arrays.asList(new String[]{"second", "list"})));
      listFilter.addListElem(new TestListFilterElem(3, Arrays.asList(new String[]{"(brackets", "(in", "(brackets)))"})));
    }
    return listFilter;
  }

  public ValueMask getValueMask()
  {
    return new ValueMask(new Mask());
  }
}

mojarra の Maven 依存関係:

<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-api</artifactId>
  <version>2.2.1</version>
</dependency>
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-impl</artifactId>
  <version>2.2.1</version>
</dependency>

myfaces の Maven 依存関係:

<dependency>
  <groupId>org.apache.myfaces.core</groupId>
  <artifactId>myfaces-api</artifactId>
  <version>2.1.10</version>
</dependency>
<dependency>
  <groupId>org.apache.myfaces.core</groupId>
  <artifactId>myfaces-impl</artifactId>
  <version>2.1.10</version>
</dependency>

mojarra を使用している場合のスタックトレース:

SEVERE: Servlet.service() for servlet [FacesServlet] in context with path [/TestJsfComponents] threw exception [null] with root cause
java.lang.NullPointerException
  at java.util.Hashtable.put(Hashtable.java:542)
  at java.beans.FeatureDescriptor.setValue(FeatureDescriptor.java:194)
  at com.sun.faces.facelets.tag.composite.AttributeHandler$CCAttributePropertyDescriptor.getValue(AttributeHandler.java:210)
  at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler$CompositeComponentMetaRuleset$CompositeMetadataTarget.getPropertyType(CompositeComponentTagHandler.java:464)
  at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler$CompositeComponentRule.applyRule(CompositeComponentTagHandler.java:540)
  at com.sun.faces.facelets.tag.MetaRulesetImpl.finish(MetaRulesetImpl.java:173)
  at javax.faces.view.facelets.MetaTagHandler.setAttributes(MetaTagHandler.java:127)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.setAttributes(DelegatingMetaTagHandler.java:102)
  at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.setAttributes(CompositeComponentTagHandler.java:245)
  at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.applyNextHandler(CompositeComponentTagHandler.java:181)
  at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
  at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
  at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
  at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
  at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
  at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
  at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
  at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93)
  at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:87)
  at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:161)
  at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:980)
  at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:99)
  at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
  at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
  at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
  at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
  at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
  at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
  at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:722)

質問:

myfaces を使用すると、コンポーネントがレンダリングされて機能します (要素をフィルタリングすると、その場で ajax によってリストが削減されます)、mojarra を使用する場合 (mojarra が 2.2.1 で myfaces が 2.1.10 であっても)、コンポーネントは機能しません。上記のスタックトレースによりレンダリングされます。

これはなぜですか?この複合コンポーネントでmojarraを機能させるにはどうすればよいですか?

注釈:

この使用法 (フィルター クラスなど) の複雑さは、後で別の複合コンポーネントでこのコンポーネントを使用するためです。そのため、上記のインターフェイスと実装が必要です。

4

1 に答える 1

0

しばらくして、私は問題を見つけました:

<composite:attribute name="valueMask" required="false" type="" />

属性タイプが空です。myfaces はこれを許し、mojarra は許さないようです。このようなエラーには、より良いスタックトレース (メッセージ) を使用したいと思います。

それにもかかわらず、型を削除することで問題は解決しました (私の場合、必要な完全修飾クラスを型に与えました)。

于 2013-08-05T08:24:03.523 に答える