title: Bean scope loss when using composite JSF components & action methods never being called
body: <p>I've been asked to refactor the following code, which works:</p>
  
  <pre><code>&lt;a4j:commandButton type="image"
      image="/someImage.gif"
      action="#{SomeViewController.someDeleteAction}"
      onclick="return confirm('#{msg['a.message']}');"
      render="someDataTableWithItems"&gt;
      &lt;f:setPropertyActionListener
          target="#{SomeViewModel.selectedItem}" value="#{item}" /&gt;
  &lt;/a4j:commandButton&gt;
  </code></pre>
  
  <p>..to an alternative which allowed to use a custom popup to confirm the action. This snippet is embedded into a column inside a <code>rich:dataTable</code> component. <code>#{item}</code> is a reference to the object assigned to the row where this button is (defined in the dataTable as <code>var="item"</code>).</p>
  
  <p>I decided to do a JSF composite component (first one I do) to have something I could reuse. It's based on this <a href="https://stackoverflow.com/questions/12123939/how-to-show-confirm-richfaces-popup-when-use-action-method-in-jsf-managed-bean">answer by elias</a></p>
  
  <pre><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
  
  &lt;html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich"
      xmlns:cc="http://java.sun.com/jsf/composite"&gt;
  &lt;cc:interface&gt;
      &lt;cc:attribute name="message" default="#{msg['a.default.message']}" /&gt;
      &lt;cc:attribute name="header"
          default="#{msg['a.default.header']}" /&gt;
      &lt;cc:attribute name="action" required="true"
          method-signature="java.lang.String action()" /&gt;
      &lt;cc:attribute name="actionListener" required="false"
          method-signature="java.lang.String action()" /&gt;
      &lt;cc:attribute name="value" default="Send" /&gt;
      &lt;cc:attribute name="cancelBtn" default="#{msg['a.default.cancel']}" /&gt;
      &lt;cc:attribute name="confirmBtn" default="#{msg['a.default.ok']}" /&gt;
      &lt;cc:attribute name="render" default="@form" /&gt;
      &lt;cc:attribute name="type" default="submit" /&gt;
      &lt;cc:attribute name="image" required="false"/&gt;
      &lt;cc:attribute name="tooltip" required="false" /&gt;
  &lt;/cc:interface&gt;
  &lt;cc:implementation&gt;
      &lt;a4j:commandButton type="#{cc.attrs.type}" rendered="#{empty cc.attrs.actionListener and not empty cc.attrs.image}"
          image="#{cc.attrs.image}" value="#{cc.attrs.value}"
          oncomplete="#{rich:component('somePopup')}.show()"&gt;
          &lt;rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}"&gt;
              #{cc.attrs.tooltip}
          &lt;/rich:tooltip&gt;
      &lt;/a4j:commandButton&gt;
      &lt;a4j:commandButton type="#{cc.attrs.type}" rendered="#{not empty cc.attrs.actionListener and not empty cc.attrs.image}"
          actionListener="#{cc.attrs.actionListener}"
          image="#{cc.attrs.image}" value="#{cc.attrs.value}"
          oncomplete="#{rich:component('somePopup')}.show()"&gt;
          &lt;rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}"&gt;
              #{cc.attrs.tooltip}
          &lt;/rich:tooltip&gt;
      &lt;/a4j:commandButton&gt;
      &lt;a4j:commandButton type="#{cc.attrs.type}" rendered="#{empty cc.attrs.actionListener and empty cc.attrs.image}"
          value="#{cc.attrs.value}"
          oncomplete="#{rich:component('somePopup')}.show()"&gt;
          &lt;rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}"&gt;
              #{cc.attrs.tooltip}
          &lt;/rich:tooltip&gt;
      &lt;/a4j:commandButton&gt;
      &lt;a4j:commandButton type="#{cc.attrs.type}" rendered="#{not empty cc.attrs.actionListener and empty cc.attrs.image}"
          actionListener="#{cc.attrs.actionListener}" value="#{cc.attrs.value}"
          oncomplete="#{rich:component('somePopup')}.show()"&gt;
          &lt;rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}"&gt;
              #{cc.attrs.tooltip}
          &lt;/rich:tooltip&gt;
      &lt;/a4j:commandButton&gt;
      &lt;rich:popupPanel id="somePopup"
          header="#{cc.attrs.header}" autosize="true" resizeable="false"&gt;
          &lt;p&gt;#{cc.attrs.message}&lt;/p&gt;
          &lt;a4j:commandButton action="#{SomeViewController.someDeleteAction}" &lt;!-- It should be #{cc.attrs.action} but I just put this for debug --&gt;
              value="#{cc.attrs.confirmBtn}" render="#{cc.attrs.render}"
              oncomplete="#{rich:component('somePopup')}.hide()"&gt;
              &lt;cc:insertChildren /&gt;
          &lt;/a4j:commandButton&gt;
          &lt;h:commandButton value="#{cc.attrs.cancelBtn}"
              onclick="#{rich:component('somePopup')}.hide(); return false;" /&gt;
      &lt;/rich:popupPanel&gt;
  &lt;/cc:implementation&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>..and replace the previous <code>a4j:commandButton</code> with this:</p>
  
  <pre><code>&lt;my:buttonConfirm type="image" id="someID"
      image="/someImage.gif"
      action="#{SomeViewController.someDeleteAction}"
      message="#{msg['a.confirmation.message']}"
      render="someDataTableWithItems"
      tooltip="#{msg['a.tooltip.message']}"&gt;
      &lt;f:setPropertyActionListener for="someID"
          target="#{SomeViewModel.selectedItem}" value="#{item}" /&gt;
  &lt;/my:buttonConfirm&gt;
  </code></pre>
  
  <p>The popup appears and you can cancel the action, but when confirming it, SomeViewModel is reinstantiated again, losing the previous bean in scope.</p>
  
  <p>The scope is a custom view scope got from <a href="http://comdynamics.net/blog/109/spring3-jsf2-view-scope/" rel="nofollow noreferrer">here</a></p>
  
  <p>I then changed the scope of the model to this one:</p>
  
  <pre><code>@Component("SomeViewModel")
  @ViewScoped
  </code></pre>
  
  <p>Although I tried to use <code>@ManagedBean</code> instead of <code>@Component</code>, the app gave me autowiring errors so I left <code>@Component</code>. The scope was now kept.
  I don't know whether the mix of JSF and Spring annotations on this way may have any other consequences.</p>
  
  <p>However the scope of <code>SomeViewModel</code> was now fine, the <code>f:setPropertyActionListener</code> target was never set and the action <code>#{SomeViewController.someDeleteAction}</code> was never called. I have been unable to debug this (not sure where to put breakpoints to see what happens in the middle).</p>
  
  <p>Thanks in advance for your help.</p>