Derby
  1. Derby
  2. DERBY-3424

Add an MBean that an application can register to change the state of Derby's JMX management

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 10.4.1.3
    • Component/s: JMX
    • Labels:
      None

      Description

      JMX in Derby was originally proposed as a mechanism to configure Derby replacing or enhancing the system properties which tend to be static in nature. Thus it is somewhat ironic that jmx is enabled with a static system property derby.system.jmx.

      I propose to add a public mbean that allows the state Derby's JMX management to be changed. This bean is not automatically registered by Derby if derby.system.jmx is false, but instead can be registered by an application. I believe this could occur at any time so that JMX could be enabled on a running application, possibly by a remote client.

      This standard Mbean (o.a.d.mbeans.Management & ManagementMBean) would have these operations & attribute:

      public boolean isManagementActive();
      public void startManagement();
      public void stopManagement();

      If Derby is not booted within the jvm then the operations would be no-ops.

      If derby.system.jmx is true then Derby will itself register an mbean that implements ManagementMBean to allow dynamic control of the visibility of Derby's mbeans.

        Issue Links

          Activity

          Hide
          John H. Embretsen added a comment -

          Interesting approach. So I guess the plan is to allow remote JMX clients to enable Derby-JMX at runtime by doing something like this?

          JMXServiceURL url = new JMXServiceURL(
          "service:jmx:rmi:///jndi/rmi://" + HOSTNAME + ":" + JMXPORT +"/jmxrmi");
          JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
          MBeanServerConnection mbeanServerConn = jmxc.getMBeanServerConnection();
          ObjectName mgmtObjName = new ObjectName("org.apache.derby", "type", "Management");
          ObjectInstance mgmtObj = mbeanServerConn.createMBean("org.apache.derby.mbeans.Management", mgmtObjName);

          (and then invoke operations on that MBean).

          With the current code line, I get an

          Exception in thread "main" javax.management.ReflectionException: The MBean class could not be loaded by the default loader repository

          I assume some special handling of class loaders/loading is needed on the server-side as long as we're using the platform MBeanServer... any thoughts on this?

          An admin can probably control access to this feature by using a security policy file, but are there any specific plans within the 10.4 timeframe with regards to security & this feature?

          Show
          John H. Embretsen added a comment - Interesting approach. So I guess the plan is to allow remote JMX clients to enable Derby-JMX at runtime by doing something like this? JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://" + HOSTNAME + ":" + JMXPORT +"/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); MBeanServerConnection mbeanServerConn = jmxc.getMBeanServerConnection(); ObjectName mgmtObjName = new ObjectName("org.apache.derby", "type", "Management"); ObjectInstance mgmtObj = mbeanServerConn.createMBean("org.apache.derby.mbeans.Management", mgmtObjName); (and then invoke operations on that MBean). With the current code line, I get an Exception in thread "main" javax.management.ReflectionException: The MBean class could not be loaded by the default loader repository I assume some special handling of class loaders/loading is needed on the server-side as long as we're using the platform MBeanServer... any thoughts on this? An admin can probably control access to this feature by using a security policy file, but are there any specific plans within the 10.4 timeframe with regards to security & this feature?
          Hide
          Daniel John Debrunner added a comment -

          Thinking about security one approach may to be to add a permission specific to Derby that controls the ability to start and stop the management service. This could then be granted to a JMXPrincipal to control access to Derby's jmx monitoring.

          I've been experimenting with running derby under a security manager with jmx but haven't managed to get a remote user to log in using jconsole yet. I can log in remotely if there is no security manager, but not with a security manager. I can connect using jconsole locally (via the process id) when the security manager is enabled and see Derby's mbeans.

          Show
          Daniel John Debrunner added a comment - Thinking about security one approach may to be to add a permission specific to Derby that controls the ability to start and stop the management service. This could then be granted to a JMXPrincipal to control access to Derby's jmx monitoring. I've been experimenting with running derby under a security manager with jmx but haven't managed to get a remote user to log in using jconsole yet. I can log in remotely if there is no security manager, but not with a security manager. I can connect using jconsole locally (via the process id) when the security manager is enabled and see Derby's mbeans.
          Hide
          John H. Embretsen added a comment -

          By "log in", do you mean connect to the MBean server? (Or are you experimenting with authentication/authorization?)

          I am able to access Derby's MBeans remotely when using a custom policy file including the permissions outlined in the funcSpec attached to DERBY-1387. By specifying the following properties:

          -Dderby.system.jmx=true
          -Dcom.sun.management.jmxremote.port=8005
          -Dcom.sun.management.jmxremote.authenticate=false
          -Dcom.sun.management.jmxremote.ssl=false

          I can connect using JConsole by specifying <remoteHost>:8005 in the connection dialog, or by using the URL
          service:jmx:rmi:///jndi/rmi://<remoteHost>:8005/jmxrmi.

          Show
          John H. Embretsen added a comment - By "log in", do you mean connect to the MBean server? (Or are you experimenting with authentication/authorization?) I am able to access Derby's MBeans remotely when using a custom policy file including the permissions outlined in the funcSpec attached to DERBY-1387 . By specifying the following properties: -Dderby.system.jmx=true -Dcom.sun.management.jmxremote.port=8005 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false I can connect using JConsole by specifying <remoteHost>:8005 in the connection dialog, or by using the URL service:jmx:rmi:///jndi/rmi://<remoteHost>:8005/jmxrmi.
          Hide
          John H. Embretsen added a comment -

          Here's a summary of my current understanding of (parts of) this feature from reading the code that is committed so far.
          Please correct me if I'm wrong:

          • Derby's Management Service is booted regardless of the value of
            derby.system.jmx.
          • If the VM does not support JMX (meaning: platform management), an
            "empty" Management service is booted instead of the "real" one.
          • If the value of derby.system.jmx is true, all the current MBeans are
            registered with both the platform MBeanServer and Derby's Management
            service, and will be available to JMX clients.
          • Otherwise (derby.system.jmx is non-true), all the current MBeans except
            the ManagementMBean are "registered" with Derby's Management service,
            but are not registered with the MBeanServer, and will thus not be
            available to JMX clients.
          • To enable Derby-JMX at runtime, the JMX client has to create and
            register the ManagementMBean with the MBean server, and then invoke
            the startManagement() operation.
          • Then the MBeans "registered" with Derby's management service are also
            automatically registered with the MBean server. This currently only
            includes the VersionMBean.

          Some questions/comments:

          1) Can the Management Service (module) be stopped (I guess this means
          permanently disabled) by the user? If so, how?

          2) How may/will MBeans such as the JDBCMBean (which are normally
          registered e.g. at driver boot time) be registered if JMX management
          is disabled at startup of Derby, but enabled later by using the
          ManagementMBean?

          3) It is slightly confusing that the term "registered" is used both
          for MBeans registered with JMX (the MBean server) and for MBeans
          instantiated and stored with Derby's Management service. The code needs
          to be commented carefully in order to avoid misunderstandings. So far
          so good, but I wonder if this might become a problem when more code is
          added?

          4) In jmxUnregister(), there is a TODO item for error handling, which is
          fair enough. Is the associated comment is still valid? If so, I need
          some help understanding what "shutdown" means in this context:

          } catch (PrivilegedActionException pae) {
          // TODO - this is called on shutdown where
          // we don't really care about errors.

          Show
          John H. Embretsen added a comment - Here's a summary of my current understanding of (parts of) this feature from reading the code that is committed so far. Please correct me if I'm wrong: Derby's Management Service is booted regardless of the value of derby.system.jmx. If the VM does not support JMX (meaning: platform management), an "empty" Management service is booted instead of the "real" one. If the value of derby.system.jmx is true, all the current MBeans are registered with both the platform MBeanServer and Derby's Management service, and will be available to JMX clients. Otherwise (derby.system.jmx is non-true), all the current MBeans except the ManagementMBean are "registered" with Derby's Management service, but are not registered with the MBeanServer, and will thus not be available to JMX clients. To enable Derby-JMX at runtime, the JMX client has to create and register the ManagementMBean with the MBean server, and then invoke the startManagement() operation. Then the MBeans "registered" with Derby's management service are also automatically registered with the MBean server. This currently only includes the VersionMBean. Some questions/comments: 1) Can the Management Service (module) be stopped (I guess this means permanently disabled) by the user? If so, how? 2) How may/will MBeans such as the JDBCMBean (which are normally registered e.g. at driver boot time) be registered if JMX management is disabled at startup of Derby, but enabled later by using the ManagementMBean? 3) It is slightly confusing that the term "registered" is used both for MBeans registered with JMX (the MBean server) and for MBeans instantiated and stored with Derby's Management service. The code needs to be commented carefully in order to avoid misunderstandings. So far so good, but I wonder if this might become a problem when more code is added? 4) In jmxUnregister(), there is a TODO item for error handling, which is fair enough. Is the associated comment is still valid? If so, I need some help understanding what "shutdown" means in this context: } catch (PrivilegedActionException pae) { // TODO - this is called on shutdown where // we don't really care about errors.
          Hide
          Daniel John Debrunner added a comment -

          By log in I meant connect to the jmx of the remote jvm using jconsole. I was using jmx authentication and a security manager on the remote jvm (the one running Derby).
          Apart from the permissions in the spec additional permissions need to be granted to JMXPrincipals, this works but is very general:

          grant principal javax.management.remote.JMXPrincipal *

          { permission javax.management.MBeanPermission "*", "*"; }

          ;

          One can fine tune the MBeanPermission settings to allow only certain operations on certain beans and obviously different permissions for different users.
          Every action on an mbean implictly requires an MBeanPermission permission.

          I also discovered on the server side one can use -Djava.security.debug=access to produce a log of access permissions, which helps in setting up any policy file.

          Show
          Daniel John Debrunner added a comment - By log in I meant connect to the jmx of the remote jvm using jconsole. I was using jmx authentication and a security manager on the remote jvm (the one running Derby). Apart from the permissions in the spec additional permissions need to be granted to JMXPrincipals, this works but is very general: grant principal javax.management.remote.JMXPrincipal * { permission javax.management.MBeanPermission "*", "*"; } ; One can fine tune the MBeanPermission settings to allow only certain operations on certain beans and obviously different permissions for different users. Every action on an mbean implictly requires an MBeanPermission permission. I also discovered on the server side one can use -Djava.security.debug=access to produce a log of access permissions, which helps in setting up any policy file.
          Hide
          Daniel John Debrunner added a comment -

          > - To enable Derby-JMX at runtime, the JMX client has to create and register the ManagementMBean with the MBean server, and then invoke the startManagement() operation.

          or invoke startManagement() on the ManagementMBean if Derby registered it with the platform mbean server

          > - If the value of derby.system.jmx is true, all the current MBeans are registered with both the platform MBeanServer

          If Derby can not find the platform MBeanServer then the mbeans will no be registered with the platform MBeanServer. (e.g. Derby does not have the permission to start the platform server and it is not running).
          Also Derby may not be able to register specific beans (due to permissions) with the platform mbean server, those will remain registered with Derby's management service but not with jmx.

          > - Then the MBeans "registered" with Derby's management service are also automatically registered with the MBean server. This currently only includes the VersionMBean.

          No for the last sentence,currently the JDBC mbean will also register as well as the VersionMBean, but this is not hardcoded into Derby's management service, it's just a factor of which mbeans have been registered with Derby's management service.

          A1) No Derby's management service cannot be stopped, I don't see a use case for this.

          A2) It's in the working code, JMXManagementService maintains a collection of mbeans that have been registered with it. When its active state changes it either registers in or unregisters from the plaform mbean server the mbeans in its collection.

          A3) Please feel free to suggest a better term. Note that only in the implementation of Derby's api is there two uses, the ManagementService api has a single use, just register and unregister, the implementation can do what it wants with the beans.

          A4) I'll clean up the comment.

          Thanks for the comments.

          Show
          Daniel John Debrunner added a comment - > - To enable Derby-JMX at runtime, the JMX client has to create and register the ManagementMBean with the MBean server, and then invoke the startManagement() operation. or invoke startManagement() on the ManagementMBean if Derby registered it with the platform mbean server > - If the value of derby.system.jmx is true, all the current MBeans are registered with both the platform MBeanServer If Derby can not find the platform MBeanServer then the mbeans will no be registered with the platform MBeanServer. (e.g. Derby does not have the permission to start the platform server and it is not running). Also Derby may not be able to register specific beans (due to permissions) with the platform mbean server, those will remain registered with Derby's management service but not with jmx. > - Then the MBeans "registered" with Derby's management service are also automatically registered with the MBean server. This currently only includes the VersionMBean. No for the last sentence,currently the JDBC mbean will also register as well as the VersionMBean, but this is not hardcoded into Derby's management service, it's just a factor of which mbeans have been registered with Derby's management service. A1) No Derby's management service cannot be stopped, I don't see a use case for this. A2) It's in the working code, JMXManagementService maintains a collection of mbeans that have been registered with it. When its active state changes it either registers in or unregisters from the plaform mbean server the mbeans in its collection. A3) Please feel free to suggest a better term. Note that only in the implementation of Derby's api is there two uses, the ManagementService api has a single use, just register and unregister, the implementation can do what it wants with the beans. A4) I'll clean up the comment. Thanks for the comments.
          Hide
          John H. Embretsen added a comment -

          Thanks for the details!

          >> - Then the MBeans "registered" with Derby's management service are also automatically registered with the MBean server. This currently only includes the VersionMBean.
          >
          > No for the last sentence,currently the JDBC mbean will also register as well as the VersionMBean, but this is not hardcoded into Derby's management service, it's just a factor of which mbeans have been registered with Derby's management service.

          (see also A2))

          Ah, I think I understand this now. Even if Derby is started with JMX management disabled, the MBeans (except the ManagementMBean) are automatically registered in Derby's Management service at boot time (or whenever they are scheduled to be created) and therefore available (and registerable with the MBeanServer) once management is enabled dynamically.

          Show
          John H. Embretsen added a comment - Thanks for the details! >> - Then the MBeans "registered" with Derby's management service are also automatically registered with the MBean server. This currently only includes the VersionMBean. > > No for the last sentence,currently the JDBC mbean will also register as well as the VersionMBean, but this is not hardcoded into Derby's management service, it's just a factor of which mbeans have been registered with Derby's management service. (see also A2)) Ah, I think I understand this now. Even if Derby is started with JMX management disabled, the MBeans (except the ManagementMBean) are automatically registered in Derby's Management service at boot time (or whenever they are scheduled to be created) and therefore available (and registerable with the MBeanServer) once management is enabled dynamically.
          Hide
          Daniel John Debrunner added a comment -

          John, thanks for providing the example code to try and register the Management bean from a remote client, saved me having to figure it out!

          I found the problem was simply the class o.a.d.mbeans.Management was not being added to derby.jar.

          Here's an expanded version of your code snippet, it adds providing a user name and password for jmx and invoking the startManagement method. It also changes the domain and key properties the MBean is registered in, since the MBean is being registered by an application it should probably not be in Derby's domain.

          JMXServiceURL url = new JMXServiceURL(
          "service:jmx:rmi:///jndi/rmi://" + "localhost" + ":" + 1999 +"/jmxrmi");

          HashMap<String,String[]> env = new HashMap<String,String[]>();
          String[] credentials = new String[]

          { "username", "password" }

          ;
          env.put("jmx.remote.credentials", credentials);

          JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
          MBeanServerConnection mbeanServerConn = jmxc.getMBeanServerConnection();
          ObjectName mgmtObjName = new ObjectName("com.myapp.mydomain", "type", "DerbyManagement");
          ObjectInstance mgmtObj = mbeanServerConn.createMBean("org.apache.derby.mbeans.Management", mgmtObjName);

          mbeanServerConn.invoke(mgmtObj.getObjectName(), "startManagement", new Object[0], new String[0]);

          Just here for reference, it's hard to find examples on the web that show authentication working with JMX.

          With this I was able to create the bean from the remote client and invoke it to start Derby's JMX management even though derby.system.jmx was false initially.

          Show
          Daniel John Debrunner added a comment - John, thanks for providing the example code to try and register the Management bean from a remote client, saved me having to figure it out! I found the problem was simply the class o.a.d.mbeans.Management was not being added to derby.jar. Here's an expanded version of your code snippet, it adds providing a user name and password for jmx and invoking the startManagement method. It also changes the domain and key properties the MBean is registered in, since the MBean is being registered by an application it should probably not be in Derby's domain. JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://" + "localhost" + ":" + 1999 +"/jmxrmi"); HashMap<String,String[]> env = new HashMap<String,String[]>(); String[] credentials = new String[] { "username", "password" } ; env.put("jmx.remote.credentials", credentials); JMXConnector jmxc = JMXConnectorFactory.connect(url, env); MBeanServerConnection mbeanServerConn = jmxc.getMBeanServerConnection(); ObjectName mgmtObjName = new ObjectName("com.myapp.mydomain", "type", "DerbyManagement"); ObjectInstance mgmtObj = mbeanServerConn.createMBean("org.apache.derby.mbeans.Management", mgmtObjName); mbeanServerConn.invoke(mgmtObj.getObjectName(), "startManagement", new Object [0] , new String [0] ); Just here for reference, it's hard to find examples on the web that show authentication working with JMX. With this I was able to create the bean from the remote client and invoke it to start Derby's JMX management even though derby.system.jmx was false initially.
          Hide
          John H. Embretsen added a comment -

          The commit of rev 628943 fixed the issue with class loading. I'm glad it was as simple as that! I successfully tried enabling, disabling, re-enabling etc. of Derby's JMX management, and it seemed to work well.

          Regarding the object name of the Management MBean, it is in any case up to the client application to define which domain it wants to use. I think, however, that if we are to document an example of doing this, we could just as well use "org.apache.derby" as the domain (and "type=Management" as its only key property). Otherwise the user will see two MBeans representing the management bean, providing the same functionality (at least until DERBY-3429 is implemented).

          The javadoc for javax.management.ObjectName says:

          "a useful convention is to begin the domain name with the reverse DNS name of the organization that specifies the MBeans, followed by a period and a string whose interpretation is determined by that organization."

          I was thinking that "specifies the MBeans" means providing the code defining the MBean (interface/class), but I could be wrong. No big deal, though.

          Show
          John H. Embretsen added a comment - The commit of rev 628943 fixed the issue with class loading. I'm glad it was as simple as that! I successfully tried enabling, disabling, re-enabling etc. of Derby's JMX management, and it seemed to work well. Regarding the object name of the Management MBean, it is in any case up to the client application to define which domain it wants to use. I think, however, that if we are to document an example of doing this, we could just as well use "org.apache.derby" as the domain (and "type=Management" as its only key property). Otherwise the user will see two MBeans representing the management bean, providing the same functionality (at least until DERBY-3429 is implemented). The javadoc for javax.management.ObjectName says: "a useful convention is to begin the domain name with the reverse DNS name of the organization that specifies the MBeans, followed by a period and a string whose interpretation is determined by that organization." I was thinking that "specifies the MBeans" means providing the code defining the MBean (interface/class), but I could be wrong. No big deal, though.
          Hide
          Dibyendu Majumdar added a comment -

          Hi,

          Can the Management class be placed in o.a.d.iapi.services.monitor, instead of o.a.d.mbeans ?
          I am looking at this purely from module dependency point of view. I am trying to untangle a cyclical dependency between a.o.d.iapi.services.info, a.o.d.iapi.services.monitor, and a.o.d.mbeans. The info package depends upon mbeans. monitor package depends upon info. And because of the Management class, the mbeans package depends upon monitor.
          By moving the Management class into the monitor package, this cycle will be broken.

          Is this possible?

          Thanks

          Show
          Dibyendu Majumdar added a comment - Hi, Can the Management class be placed in o.a.d.iapi.services.monitor, instead of o.a.d.mbeans ? I am looking at this purely from module dependency point of view. I am trying to untangle a cyclical dependency between a.o.d.iapi.services.info, a.o.d.iapi.services.monitor, and a.o.d.mbeans. The info package depends upon mbeans. monitor package depends upon info. And because of the Management class, the mbeans package depends upon monitor. By moving the Management class into the monitor package, this cycle will be broken. Is this possible? Thanks
          Hide
          Daniel John Debrunner added a comment -

          The Management class (mbean) needs to remain in mbeans as it is part of the public api.

          Not sure of a solution here, one might be to move the Version mbean out of info, but it seems a logical place for it.
          Is there a list of the logical package groupings you are planning to provide, e.g. should info and monitor be in the same logical bundle?

          Show
          Daniel John Debrunner added a comment - The Management class (mbean) needs to remain in mbeans as it is part of the public api. Not sure of a solution here, one might be to move the Version mbean out of info, but it seems a logical place for it. Is there a list of the logical package groupings you are planning to provide, e.g. should info and monitor be in the same logical bundle?
          Hide
          Dibyendu Majumdar added a comment -

          Moving Version out of info would be a solution. Any reason why Version can't live in o.a.d.mbeans?

          Even if I group info/monitor into one bundle, there will still be cyclical dependency between this and mbeans unless we move Version out of info.
          At present, I am simply placing each package in its own bundle ... helps when there are complex dependencies. Do not know yet what ultimately would be best grouping of modules. Initially I wanted to group by layers - services, store, language, jdbc, network, with each layer depending on those below. Hopefully I can get to this goal once the dependencies are more manageable at the module level.

          Show
          Dibyendu Majumdar added a comment - Moving Version out of info would be a solution. Any reason why Version can't live in o.a.d.mbeans? Even if I group info/monitor into one bundle, there will still be cyclical dependency between this and mbeans unless we move Version out of info. At present, I am simply placing each package in its own bundle ... helps when there are complex dependencies. Do not know yet what ultimately would be best grouping of modules. Initially I wanted to group by layers - services, store, language, jdbc, network, with each layer depending on those below. Hopefully I can get to this goal once the dependencies are more manageable at the module level.
          Hide
          Dibyendu Majumdar added a comment -

          Actually, grouping by layer probably won't work anyway, as we would need more granularity to enable bundles to be loaded by execution environment.

          Show
          Dibyendu Majumdar added a comment - Actually, grouping by layer probably won't work anyway, as we would need more granularity to enable bundles to be loaded by execution environment.
          Hide
          Daniel John Debrunner added a comment -

          Two reasons for Version not being in mbeans:

          1) For MBeans registered by Derby we are only exposing the interface to applications, ie. interface classes in o.a.d.mbeans ending in MBean.
          The implementation class remains hidden.

          2) It would require ProductVersionHolder to be referenced from mbeans, which is not part of the public api.

          Show
          Daniel John Debrunner added a comment - Two reasons for Version not being in mbeans: 1) For MBeans registered by Derby we are only exposing the interface to applications, ie. interface classes in o.a.d.mbeans ending in MBean. The implementation class remains hidden. 2) It would require ProductVersionHolder to be referenced from mbeans, which is not part of the public api.
          Hide
          Dibyendu Majumdar added a comment -

          How about o.a.d.iapi.services.info.mbean as the package for VersionMBean?

          Show
          Dibyendu Majumdar added a comment - How about o.a.d.iapi.services.info.mbean as the package for VersionMBean?
          Hide
          Myrna van Lunteren added a comment -

          No activity has been seen on this improvement for 15 months.
          Functionality has been available since 10.4.
          I don't see a list of remaining tasks.
          Can this be closed?

          Show
          Myrna van Lunteren added a comment - No activity has been seen on this improvement for 15 months. Functionality has been available since 10.4. I don't see a list of remaining tasks. Can this be closed?

            People

            • Assignee:
              Daniel John Debrunner
              Reporter:
              Daniel John Debrunner
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development