我的JSF2 / richfaces 4项目有一个奇怪的效果。我使用viewscoped bean和datascroller来查看来自我的支持bean的一些数据。该bean是视图编组的,并且通过figureId
参数传递preRenderView
事件。
<f:metadata>
<f:viewParam name="figureId" value="#{pointEdit.figureId}" >
<f:convertNumber pattern="###" />
</f:viewParam>
<f:event type="preRenderView" listener="#{pointEdit.init}" />
</f:metadata>
显示正常,但是当我点击datascroller的第二个站点时,我得到此行的nullponter异常:<f:event type="preRenderView" listener="#{pointEdit.init}" />
。
javax.el.ELException: /pointEdit.xhtml @17,66 listener="#{pointEdit.init}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
at com.sun.faces.facelets.tag.jsf.core.DeclarativeSystemEventListener.processEvent(EventHandler.java:128)
at javax.faces.component.UIComponent$ComponentSystemEventListenerAdapter.processEvent(UIComponent.java:2477)
at javax.faces.event.SystemEvent.processListener(SystemEvent.java:106)
at com.sun.faces.application.ApplicationImpl.processListeners(ApplicationImpl.java:2102)
at .....
Caused by: java.lang.NullPointerException
at com.ebcont.gtv.ePrometheus.web.backingbean.PointEdit.init(PointEdit.java:74) // <--first access to figure
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
... 27 more
我的豆子:
@ManagedBean
@ViewScoped
public class PointEdit implements Serializable {
public void init() {
FigureService figureService = Utils.getSpringBean(FigureService.class);
figure = figureService .getById(figureId); // figureId will NOT be passed from GET
pointListToDisplay = figure.getPoints(); // nullpointer :-(
在我导入新数据之前,我的测试数据很好。 为什么在init函数中找不到我的figureId GET参数?用我的testdata(5个数字)我从来没有遇到过这个问题。
更新:
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<body>
<h:messages errorStyle="color:red" warnStyle="color:yellow" />
<rich:tabPanel switchType="client">
<rich:tab header="Punkte">
<rich:panel>
<f:facet name="header">
#{msg.pointEditDetail_figure_header }
</f:facet>
<div style="position: relative;">
<h:graphicImage url="/image?figureid=#{pointEdit.figure.id}"
style="border: solid 2px #013476;z-index: -2;">
<a4j:repeat value="#{pointEdit.points}" var="thepoi">
<h:panelGroup layout="block"
style="margin-top: -27px;top:#{thepoi.y}px; left: #{thepoi.x}px; background-image: url('images/poipin.png');background-repeat:none;width: 25px; height:27px; position:absolute; z-index: -0.9;display:none;"
styleClass="poi #{thepoi.id }">
<div style="margin-top: 27px;">
<a4j:repeat value="#{thepoi.labels}" var="poilabel">
<h:panelGroup layout="block"
styleClass="poilabel label#{thepoi.id}" style="display:none;">
<div style="color: white; z-index: 1; position: relative;">
<h:outputText value="#{poilabel.locale.isoCode}:"
style="background-image: url('images/layerbackground.png'); background-repeat: both;" />
<h:outputText value="#{poilabel.label.labelText}"
style="background-image: url('images/layerbackground.png'); background-repeat: both;"
rendered="#{not empty poilabel.label.labelText}" />
<h:outputText value="Nicht verfügbar"
style="background-image: url('images/layerbackground.png'); background-repeat: both;"
rendered="#{empty poilabel.label.labelText }" />
</div>
</h:panelGroup>
</a4j:repeat>
</div>
</h:panelGroup>
</a4j:repeat>
</h:graphicImage>
</div>
<br/>
<h:commandButton value="#{msg.pointEditDetail_show_all_button}"
onclick="$('.poi').toggle()"
rendered="#{ not empty pointEdit.points}" />
<h:button outcome="viewer.xhtml" value="#{msg.pointEditDetail_button_viewer}">
<f:param name="figureId" value="#{pointEdit.figure.id}"/>
<f:param name="zoom" value="1"/>
</h:button>
</rich:panel>
<br />
<rich:panel>
<f:facet name="header">
#{msg.pointEditDetail_points_header }
</f:facet>
<h:form>
<rich:dataTable value="#{pointEdit.points}" var="point"
id="pointtable" rows="10" rowKeyVar="rowId">
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_rowkey}
</f:facet>
#{rowId+1}
</rich:column>
<rich:column sortBy="#{point.id}" id="id"
sortOrder="#{pointEdit.pointIdOrder}">
<f:facet name="header">
<a4j:commandLink
value="#{msg.pointEditDetail_table_header_point} #{msg.pointEditDetail_table_header_id }"
render="pointtable" action="#{pointEdit.sortByPointId}" />
</f:facet>
#{point.id}
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_x}
</f:facet>
#{point.x }
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_y}
</f:facet>
#{point.y }
</rich:column>
<!-- filter (Object that extends Filter<?>), filterMethod, filterExpression -->
<rich:column filter="#{pointEdit.labelFilter}">
<f:facet name="header">
#{msg.pointEditDetail_table_header_label}
<h:inputText value="#{pointEdit.labelFilterText}">
<a4j:ajax event="change" render="pointtable" execute="@this" requestDelay="700"
ignoreDupResponses="true"/>
</h:inputText>
</f:facet>
<a4j:repeat var="pointlabel" value="#{point.labels}">
#{pointlabel.locale.isoCode}:
<h:outputText value="#{pointlabel.label.labelText}"
rendered="#{not empty pointlabel.label}" />
<h:outputText value="#{msg.pointEditDetail_not_available}"
rendered="#{empty pointlabel.label}" />
<br />
</a4j:repeat>
</rich:column>
<rich:column style="text-align:center">
<f:facet name="header">
#{msg.pointEditDetail_table_header_show_point}
</f:facet>
<h:selectBooleanCheckbox styleClass="pinchk#{point.id}"
value="false"
onchange="checkboxdrivendisplay(this,'.#{point.id }');checkboxdrivendisplay(this,'.lblchk#{point.id }');"
onmouseover="jQuery('.#{point.id }').show(); jQuery('.lblchk#{point.id }').show();"
onmouseout="checkboxdrivendisplay(this,'.#{point.id }');checkboxdrivendisplay(this,'.lblchk#{point.id }');">
</h:selectBooleanCheckbox>
</rich:column>
<rich:column style="text-align:center;">
<f:facet name="header">
#{msg.pointEditDetail_table_header_show_label}
</f:facet>
<h:selectBooleanCheckbox style="display:none"
styleClass="lblchk#{point.id}" value="false"
onclick="checkboxdrivendisplay(this,'.label#{point.id }');"
onmouseover="jQuery('.label#{point.id}').show();"
onmouseout="checkboxdrivendisplay(this,'.label#{point.id }');">
</h:selectBooleanCheckbox>
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_edit_label }
</f:facet>
<center>
<h:link outcome="labelEdit.xhtml" value="#{msg.pointEditDetail_table_edit_label}">
<f:param name="pointId" value="#{point.id}"/>
</h:link>
</center>
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_tag }
</f:facet>
<a4j:repeat var="tag" value="#{point.tags}" varStatus="index">
<h:link outcome="search.xhtml" value="#{tag.tag}">
<f:param name="tags" value="true" />
<f:param name="labels" value="false" />
<f:param name="legends" value="false" />
<f:param name="query" value="#{tag.tag}" />
</h:link>
</a4j:repeat>
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_table_header_edit_tag }
</f:facet>
<center>
<h:link outcome="tagEdit.xhtml" value="#{msg.pointEditDetail_table_edit_tag}">
<f:param name="pointId" value="#{point.id}"/>
</h:link>
</center>
</rich:column>
<f:facet name="footer">
<rich:dataScroller for="pointtable" />
</f:facet>
</rich:dataTable>
</h:form>
</rich:panel>
</rich:tab>
<rich:tab header="Daten">
<h:form>
<rich:panel id="legendpanel">
<f:facet name="header">
#{msg.pointEditDetail_legend_edit_header }
</f:facet>
<h:outputText rendered="#{not empty pointEdit.legendeStatus}"
value="#{msg.pointEditDetail_legend_edit_success}" />
<br />
<h:inputTextarea value="#{pointEdit.legende}" cols="40" rows="8"/> <br /> <br />
<a4j:commandButton value="#{msg.pointEditDetail_legend_edit_button} "
render="legendpanel legende" action="#{pointEdit.editLegend}" />
</rich:panel>
</h:form>
<br />
<h:form>
<rich:panel name="labelPanel">
<f:facet name="header">
#{msg.pointEditDetail_label_edit_header }
</f:facet>
<rich:dataTable value="#{pointEdit.labels}" var="label"
id="labelTable" rows="10">
<rich:column>
<f:facet name="header">
Id
</f:facet>
#{label.id }
</rich:column>
<rich:column>
<f:facet name="header">
#{msg.pointEditDetail_label_edit_table_header}
</f:facet>
<rich:inplaceInput value="#{label.labelText }" showControls="true" layout="block" style="width: 98%"
required="true">
<a4j:ajax event="change" render="pointtable" listener="#{pointEdit.editLabel(label.id) }" />
</rich:inplaceInput>
</rich:column>
<f:facet name="footer">
<rich:dataScroller for="labelTable" />
</f:facet>
</rich:dataTable>
</rich:panel>
</h:form>
<br />
</rich:tab>
<rich:tab header="Verknüpfen">
<ui:include src="linkFigures.xhtml" />
</rich:tab>
</rich:tabPanel>
<script type="text/javascript" src="javascript/eprometheus.js"></script>
</body>
</html>
答案 0 :(得分:2)
您需要 在命令链接中将该参数作为<f:param>
传递,以便它保留在后续请求中:
<h:commandLink>
<f:param name="figureId" value="#{pointEdit.figureId}" />
</h:commandLink>
或在继续之前检查init()
FacesContext#isPostback()
是否等于false
(以便它仅在新的新GET请求上运行,而不是随后的回发,因为bean是视图作用域,并且已经设置了属性):
public void init() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// ...
}
}
答案 1 :(得分:0)
我的新测试图像比我测试的图像大5倍。在我的ViewScoped bean中,我将数字作为属性,因此整个byte []必须被序列化。 删除此设计缺陷后,它再次起作用,并解释了为什么新图像会引起麻烦!