1

I have a strange effect on my JSF2/richfaces 4 project. I use a viewscoped bean and a datascroller to view some data from my backing bean. The bean is viewscoped and to pass the figureId parameter I fire the preRenderView event.

<f:metadata>
    <f:viewParam name="figureId" value="#{pointEdit.figureId}" >
        <f:convertNumber pattern="###" />
    </f:viewParam>
    <f:event type="preRenderView" listener="#{pointEdit.init}" />
</f:metadata>

Displays fine, but when I click on the second site of the datascroller I get a nullponter exception for this line: <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

My Bean:

@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 :-(

Before I imported my new data it worked fine on my test figures. Why is my figureId GET Parameter not found in the init function? With my testdata (5 figures) I never had a problem with this.

UPDATE:

<!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> &nbsp;
                            </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>
mkuff
  • 1,620
  • 6
  • 27
  • 39
  • PS: The first data can be loaded successfully! So it looses the figureId when scrolling the pages. – mkuff Sep 14 '11 at 14:57

2 Answers2

2

You need to either pass that parameter as <f:param> in the command link so that it retains in the subsequent request:

<h:commandLink>
    <f:param name="figureId" value="#{pointEdit.figureId}" />
</h:commandLink>

or to check in the init() if FacesContext#isPostback() equals to false before proceeding (so that it only runs on a fresh new GET request, not in the subsequent postbacks as the bean is view scoped and the properties are already been set anyway):

public void init() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // ...
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks a lot for the quick answer! The datascroller does a post, but i do not understand why the ViewScoped bean forgets the figureId from the first run. When i enter the init() method for the first time figureId is set successfully. After the post it is not initialized, but due to the viewscope the value should be the same like from the first method call. Maybe i have an understanding problem for this scope. :-/ – mkuff Sep 14 '11 at 15:57
  • It does not forget the `figureId`. It has **received** an empty/null `figureId`. The `` runs on every request, not on first request only. – BalusC Sep 14 '11 at 15:59
  • Ah now i get it. Thank you very much! – mkuff Sep 14 '11 at 16:05
  • I checked my bean today with a breakpoint in the init() method and all properties are null. when i first enter the site i get the figure id and all seems correct. when i scroll one page further it seems that i get a new bean. even the pointlist queried the first time is empty. :-( – mkuff Sep 15 '11 at 11:19
  • Another interesting point is that when i change the scope to session it works. :-/ – mkuff Sep 15 '11 at 11:24
  • So the bean is recreated? That can happen when something has failed in partial view state saving or you're returning non-null from action methods. Are you using `binding` anywhere in the view? Are you using JSTL ``, ``, etc tags anywhere in the view? You should return `null` or `void` from action methods and you could try disabling partial state saving in `web.xml`. – BalusC Sep 15 '11 at 12:06
  • No Binding, and no of the JSTLs. All action methods are voids. Partial state disabling you described (http://stackoverflow.com/questions/6914662/jsf-2-0-viewscoped-life-cycle) didn't work either. It is quite strange that it is a specific figure which makes the problems. My old examples work like a charm. Anything else i could check? – mkuff Sep 15 '11 at 13:11
  • Shall i post the whole page & bean? – mkuff Sep 15 '11 at 13:13
  • I start to recall that `` has some specific problems similar to this. Try removing it, just to test. I'll look for any references in the meanwhile. – BalusC Sep 15 '11 at 13:14
  • When i remove it i get the whole list which works on the first refresh. But many things in my other rich:Panels do not work propertly. Very strange, but maybe i overloaded the page. – mkuff Sep 15 '11 at 13:24
  • I have another theory. The new images (figure) are larger and the entity contains it as byte[]. Can that be the problem? That the viewstate is too large? – mkuff Sep 15 '11 at 14:11
  • The view state does not contain the model values. Your key problem is after all that the view scoped bean get trashed and recreated upon every datascroller link call. This is not normal. I suggest to create a brand new simple test page with a small 1-column table and a simple view scoped bean with `List` as test data and see if you can still reproduce this (bean get recreated). If that is the case, I'd report a bug to the RichFaces guys along with the testcase. – BalusC Sep 15 '11 at 14:14
  • Ok then i'll test this again tomorrow to be sure and file the bug. Thank you so much for your support! – mkuff Sep 15 '11 at 14:49
0

My new test images where 5 times larger then the images i got 4 testing. In my ViewScoped bean i had the figure as property so the whole byte[] had to be serialized. After removing this design flaw it works again and also explains why the new images cause troubles!

mkuff
  • 1,620
  • 6
  • 27
  • 39