[英]ajax inside composite component mojarra vs myfaces (using jquery)
The project: a composite component that lets me filter a list and update an outer component 项目:一个复合组件,可让我过滤列表并更新外部组件
The problem: myfaces 2.1.10 works, mojarra 2.2.1 does not work, but I want to use jsf 2.2 问题:myfaces 2.1.10有效,mojarra 2.2.1不起作用,但我想使用jsf 2.2
<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" />
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;
}
}
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;
}
}
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();
}
}
}
public class ValueMask
{
private MaskInterface maskInterface;
public ValueMask(MaskInterface maskInterface)
{
this.maskInterface = maskInterface;
}
public String getMask(Object o)
{
return maskInterface.getMask(o);
}
}
@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());
}
}
<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>
<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>
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)
If I use myfaces, the component is rendered and working (filtering elements is reducing the list by ajax on the fly), but if I use mojarra (even mojarra is 2.2.1 and myfaces is just 2.1.10), the component is not rendered due to the stacktrace shown above. 如果我使用myfaces,则该组件可以渲染并正常工作(过滤元素通过ajax迅速减少列表),但是如果我使用mojarra(即使mojarra为2.2.1,而myfaces也仅为2.1.10),则该组件不是由于上面显示的stacktrace而呈现。
Why is this so and what can I do to make mojarra work with this composite component? 为什么会这样,我该怎么做才能使mojarra与该复合组件一起工作?
The complexity of this usage (filter classes and such) is due to using this component in another composite component later, therefore the interfaces and implementations mentioned above are necessary. 这种用法(过滤器类等)的复杂性是由于稍后在另一个复合组件中使用此组件所致,因此上述接口和实现是必需的。
After a while I found the problem: 一段时间后,我发现了问题:
<composite:attribute name="valueMask" required="false" type="" />
The attribute type is empty. 该属性类型为空。 Seems like myfaces forgives this and mojarra does not. 好像myfaces宽恕了这一点,而mojarra却没有。 I'd prefer a better stacktrace (message) for such an error. 对于这种错误,我希望使用更好的stacktrace(消息)。
Nevertheless, removing type solved the problem (in my case I gave type the full qualified class I needed). 不过,删除类型可以解决问题(在我的情况下,我为类型提供了所需的完全合格的类)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.