groovy
  1. groovy
  2. GROOVY-1291

GroovyMBean doesn't support the use of overloaded MBean operations

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.0-JSR-5
    • Fix Version/s: 1.0-JSR-6
    • Component/s: None
    • Labels:
      None
    • Environment:
      WinXp.
      JDk150_06
    • Number of attachments :
      1

      Description

      Using the GroovyMBean to access MBeans running the Oracle J2EE container (OC4J).

      Some of the MBeans have overloaded methods, such as:

      J2EEApplication::
      testDataSource(String sqlStmt)
      testDataSource(String sqlStmt, String username, String password)

      When using the GroovyMBean to access this MBean its not possible to invoke testDataSource(String sqlStmt)

      defaultApp.testDataSource("select * from sys.dual")

      This always results in an exception on the underlying MBeanServer.

      The problem is that the GroovyMBean stores a signature for each operation from its specified MBean in a HashMap, using the operation name as its key. It then later uses the method name to retrieve the signature to invoke the operation on the MBean.

      88 public GroovyMBean(MBeanServerConnection server, ObjectName name) throws JMException, IOException {
      89 this.server = server;
      90 this.name = name;
      91 this.beanInfo = server.getMBeanInfo(name);
      92
      93 MBeanOperationInfo[] operationInfos = beanInfo.getOperations();
      94 for (int i = 0; i < operationInfos.length; i++ )

      { 95 MBeanOperationInfo info = operationInfos[i]; 96 operations.put(info.getName(), createSignature(info)); 97 }

      98 }
      99

      136 public Object invokeMethod(String method, Object arguments) {
      137 String[] signature = (String[]) operations.get(method);

      Thus for overloaded operations, only the last operation found will be stored in the HashMap.

      If another variant of the operation is invoked on the GroovyMBean then an incorrect signature will be passed to the MBeanServer which results in an exception occuring on the server.

      One simple fix is to create a unique key for the operation name consisting of the name and the number of parameters and use that to store the operation name and signature for each operation

      /**

      • Construct a simple key based on the method name and the number of parameters
      • @param operation - the mbean operation name
      • @param params - the number of parameters the operation supports
      • @return simple unique identifier for a method
        */
        protected String createOperationKey(String operation, int params) { // This could be changed to support some hash of the parameter types, etc. return operation + "_" + params; }

      93 MBeanOperationInfo[] operationInfos = beanInfo.getOperations();
      94 for (int i = 0; i < operationInfos.length; i++ )

      { 95 MBeanOperationInfo info = operationInfos[i]; 96 //operations.put(info.getName(), createSignature(info)); String operationKey = createOperationKey(info.getName(),signature.length); operations.put(operationKey,signature); 97 }

      and then change invokeMethod method to construct the operationKey from the given method and paramater length.

      public Object invokeMethod(String method, Object arguments) {
      // Moved this outside the try block so we can obtain the number of parameters
      // specified in the arguments array, which is needed to find the correct method.
      Object[] argArray = null;
      if (arguments instanceof Object[])

      { argArray = (Object[]) arguments; }

      else {
      argArray = new Object[]

      {arguments}

      ;
      }
      // Locate the specific method based on the name and number of parameters
      String operationKey = createOperationKey(method,argArray.length);
      String[] signature = (String[]) operations.get(operationKey);

      if (signature != null) {
      try

      { return server.invoke(name, method, argArray, signature); }

      catch (MBeanException e)

      { throw new GroovyRuntimeException("Could not invoke method: " + method + ". Reason: " + e, e.getTargetException()); }

      catch (Exception e)

      { throw new GroovyRuntimeException("Could not invoke method: " + method + ". Reason: " + e, e); }

      }
      else

      { return super.invokeMethod(method, arguments); }

      }

        Issue Links

          Activity

          Hide
          Steve Button added a comment -

          Please note that the attachment is based on the GroovyMBean.java update which was supplied recently by Tugdual Grall. I didn't get it from CVS sorry, I'm new to this O/S stuff.

          Show
          Steve Button added a comment - Please note that the attachment is based on the GroovyMBean.java update which was supplied recently by Tugdual Grall. I didn't get it from CVS sorry, I'm new to this O/S stuff.
          Hide
          Guillaume Laforge added a comment -

          Thanks Steve for this patch.

          Show
          Guillaume Laforge added a comment - Thanks Steve for this patch.
          Guillaume Laforge made changes -
          Field Original Value New Value
          Fix Version/s 1.0-RC-1 [ 12103 ]
          Status Open [ 1 ] Closed [ 6 ]
          Resolution Fixed [ 1 ]
          Paul King made changes -
          Link This issue is superceded by GROOVY-2807 [ GROOVY-2807 ]

            People

            • Assignee:
              Guillaume Laforge
              Reporter:
              Steve Button
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: