Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-1291

GroovyMBean doesn't support the use of overloaded MBean operations

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Critical
    • Resolution: Fixed
    • 1.0-JSR-5
    • 1.0-JSR-6
    • None
    • None
    • WinXp.
      JDk150_06

    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); }

      }

      Attachments

        1. GroovyMBean.java
          13 kB
          Steve Button

        Issue Links

          Activity

            People

              guillaume Guillaume Sauthier
              buttso Steve Button
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: