javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2758

Wrong PropertyNotFoundException when invoking bean method from composite component class

    Details

      Description

      There is a wrong WARNING when a bean method gets invoked from a composite component class (specified via <cc:interface componentType="">) and this bean method throws any exception. I will try to explain it step by step. I have a composiste component with an attribute

      <cc:attribute name="delete" required="true" method-signature="void f(java.lang.String)"/>
      

      I have a button in the composite component which calls an action listener delete() in the componentclass.

      <p:commandButton process="@this" update="#{cc.id}" actionListener="#{cc.delete}"/>
      

      The action listener calls another method from a bean defined in cc:attribute (s. above).

      public void delete(ActionEvent ae) {
          FacesContext fc = FacesContext.getCurrentInstance();
          ELContext elContext = fc.getELContext();
      
          Object[] params = new Object[1];
          params[0] = "someId";
      
          try {
              MethodExpression me = (MethodExpression) this.getAttributes().get("delete");
              me.invoke(elContext, params);
          } catch (Exception e) {
              // error ==> render response
              fc.renderResponse();
              return;
          }
      	
          // do something
          ...
      }
      

      The delete() method in the bean looks like as follows

      @ManagedBean
      @ViewScoped
      public class MyController implements Serializable {
      
          public void delete(String id) {
              // do something
              ...
      
              FacesMessage message = new FacesMessage("Some message", null);
              message.setSeverity(FacesMessage.SEVERITY_ERROR);
              FacesContext.getCurrentInstance().addMessage(null, message);
      
              throw new IllegalStateException("Delete operation failed");
      		
              // do something
              ...
          }
      }
      

      Now, when this method throws an exception, we get this message in the log

      com.sun.faces.facelets.el.ContextualCompositeMethodExpression invoke
      WARNING: jsf.facelets.el.method.expression.invoke.error:javax.el.PropertyNotFoundException: 
      /section/delete.xhtml @18,71 delete="#{MyController.delete}": The class 'mypackage.MyController' does not have the property 'delete'.
      

      Sure, 'delete' is not a property, this is a method . The problem is in the class ContextualCompositeMethodExpression.java. The invoke method looks like as

      public Object invoke(ELContext elContext, Object[] objects) {
      
          FacesContext ctx = (FacesContext)elContext.getContext(FacesContext.class);
          try {
              boolean pushed = pushCompositeComponent(ctx);
              try {
                  return delegate.invoke(elContext, objects);
              } finally {
                  if (pushed) {
                      popCompositeComponent(ctx);
                  }
              }
          } catch (ELException ele) {
              if (source != null) {
                  // special handling when an ELException handling. This is necessary
                  // when there are multiple levels of composite component nesting.
                  // When this happens, we need to evaluate the source expression
                  // to find and invoke the MethodExpression at the next highest
                  // nesting level.  Is there a cleaner way to detect this case?
      	    try {
                      Object fallback = source.getValue(elContext);      // <--- this line produces Exception
                      if (fallback != null && fallback instanceof MethodExpression) {
                          return ((MethodExpression) fallback).invoke(elContext, objects);
                      }
                  } catch(Exception ex) {
                      if (LOGGER.isLoggable(Level.WARNING)) {
                          LOGGER.log(Level.WARNING, "jsf.facelets.el.method.expression.invoke.error:"+ex.toString(),
                              new Object[] { source.getExpressionString() });
                      }
                  }
              }
              throw ele;
          }
      }
      

      As you can see if the bean method throws an exception, we are in the catch-block. In the catch-block, you're trying to call source.getValue(elContext) and this produces an exception and we're jumping into the nested catch-block with the warning. Why do you call getValue()?

        Issue Links

          Activity

          Hide
          ova2 added a comment -

          Just to clarify what I wanted to say with this issue: You can try to call source.getValue(elContext) of course. But please don't log the warning because source.getValue(elContext) will always fail in the case I described above. Thanks.

          Show
          ova2 added a comment - Just to clarify what I wanted to say with this issue: You can try to call source.getValue(elContext) of course. But please don't log the warning because source.getValue(elContext) will always fail in the case I described above. Thanks.
          Hide
          ova2 added a comment -

          Similar issues marked as closed:

          http://java.net/jira/browse/JAVASERVERFACES-1806
          https://java.net/jira/browse/JAVASERVERFACES-2665

          Mojarra seems to have a lot of similar places with the same concept .

          Show
          ova2 added a comment - Similar issues marked as closed: http://java.net/jira/browse/JAVASERVERFACES-1806 https://java.net/jira/browse/JAVASERVERFACES-2665 Mojarra seems to have a lot of similar places with the same concept .
          Hide
          Manfred Riem added a comment -

          Applied to 2.2 branch,

          svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2758, r=rogerk, make sure we echo the correct message in the log when using a method expression inside a composite component."
          Sending jsf-ri\src\main\java\com\sun\faces\facelets\el\ContextualCompositeMethodExpression.java
          Transmitting file data .
          Committed revision 12534.

          Show
          Manfred Riem added a comment - Applied to 2.2 branch, svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2758 , r=rogerk, make sure we echo the correct message in the log when using a method expression inside a composite component." Sending jsf-ri\src\main\java\com\sun\faces\facelets\el\ContextualCompositeMethodExpression.java Transmitting file data . Committed revision 12534.

            People

            • Assignee:
              Manfred Riem
              Reporter:
              ova2
            • Votes:
              2 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: