Tomcat5 MBeans/JMX context creation
I am currently experimenting with the Java 1.5 remote JMX/MBeans for use in our build process. In particular, I am attempting to install a new context in a running Tomcat5.18 server using an external Ant task/application, (without using the manager webapp). I found code in the admin webapp to do this, but it does not seem to configure the WebappClassLoader instances associated with the context correctly. By examining the Tomcat5 source, I was able to find a workaround that seems to function correctly, but I would like to verify it with someone who knows how the MBean API is intended to be used. Here is what the admin webapp is doing to install a new context: ObjectName host = ... ; String contextPath = /testsite ; String webappDocBase = /tmp/testsite ; String newContext = (String) mbeanServer.invoke( factory, createStandardContext, new Object [] { host.toString(), /testsite, /tmp/testsite }, new String [] { java.lang.String, java.lang.String, java.lang.String } ) ; mbeanServer.invoke( factory, createWebappLoader, new Object [] { newContext }, new String [] { java.lang.String } ) ; mbeanServer.invoke( factory, createStandardManager, new Object [] { newContext }, new String [] { java.lang.String } ) ; Accessing a JSP page or servlet in this new context results in trying to use an unstarted ClassLoader that results in a ThreadDeath exception. The following MBeans are created, (note the odd Catalina:type=Loader instance): Catalina:type=Loader,path=/testsite,host=localhost Catalina:type=NamingResources,resourcetype=Context,path=/testsite,host=local host Standalone:j2eeType=Servlet,name=CookiesDump,WebModule=//localhost/testsite, J2EEApplication=none,J2EEServer=none Standalone:j2eeType=Servlet,name=default,WebModule=//localhost/testsite,J2EE Application=none,J2EEServer=none Standalone:j2eeType=Servlet,name=jsp,WebModule=//localhost/testsite,J2EEAppl ication=none,J2EEServer=none Standalone:j2eeType=WebModule,name=//localhost/testsite,J2EEApplication=none ,J2EEServer=none Standalone:type=Cache,host=localhost,path=/testsite Standalone:type=Loader,path=/testsite,host=localhost Standalone:type=Manager,path=/testsite,host=localhost If the code above is modified to remove the call to createWebappLoader, the webapp is loaded correctly and the exported MBeans match what is available when the same webapp is loaded if deployed directly in the Tomcat5 webapps directory at startup: Catalina:type=NamingResources,resourcetype=Context,path=/testsite,host=local host Standalone:j2eeType=Servlet,name=CookiesDump,WebModule=//localhost/testsite, J2EEApplication=none,J2EEServer=none Standalone:j2eeType=Servlet,name=default,WebModule=//localhost/testsite,J2EE Application=none,J2EEServer=none Standalone:j2eeType=Servlet,name=jsp,WebModule=//localhost/testsite,J2EEAppl ication=none,J2EEServer=none Standalone:j2eeType=WebModule,name=//localhost/testsite,J2EEApplication=none ,J2EEServer=none Standalone:type=Cache,host=localhost,path=/testsite Standalone:type=Loader,path=/testsite,host=localhost Standalone:type=Manager,path=/testsite,host=localhost It seems that the invocation of the createWebappLoader operation ends up creating an extra Loader instance somehow that confuses the ClassLoader configuration for the webapp context. I verified that the createStandardContext operation does indeed construct a Loader when start() is invoked on the context container. Apparently, either the createStandardContext is not supposed to create the Loader or the createWebappLoader operation should not be used in the admin webapp... then again, I might be missing something! Can anyone clarify how the createStandardContext should be invoked? Randy Watler Finali Corporation
Re: Tomcat5 MBeans/JMX context creation
Randy Watler wrote: I am currently experimenting with the Java 1.5 remote JMX/MBeans for use in our build process. In particular, I am attempting to install a new context in a running Tomcat5.18 server using an external Ant task/application, (without using the manager webapp). I found code in the admin webapp to do this, but it does not seem to configure the WebappClassLoader instances associated with the context correctly. By examining the Tomcat5 source, I was able to find a workaround that seems to function correctly, but I would like to verify it with someone who knows how the MBean API is intended to be used. Here is what the admin webapp is doing to install a new context: ObjectName host = ... ; String contextPath = /testsite ; String webappDocBase = /tmp/testsite ; String newContext = (String) mbeanServer.invoke( factory, createStandardContext, new Object [] { host.toString(), /testsite, /tmp/testsite }, new String [] { java.lang.String, java.lang.String, java.lang.String } ) ; mbeanServer.invoke( factory, createWebappLoader, new Object [] { newContext }, new String [] { java.lang.String } ) ; mbeanServer.invoke( factory, createStandardManager, new Object [] { newContext }, new String [] { java.lang.String } ) ; Accessing a JSP page or servlet in this new context results in trying to use an unstarted ClassLoader that results in a ThreadDeath exception. The following MBeans are created, (note the odd Catalina:type=Loader instance): Catalina:type=Loader,path=/testsite,host=localhost Catalina:type=NamingResources,resourcetype=Context,path=/testsite,host=local host Standalone:j2eeType=Servlet,name=CookiesDump,WebModule=//localhost/testsite, J2EEApplication=none,J2EEServer=none Standalone:j2eeType=Servlet,name=default,WebModule=//localhost/testsite,J2EE Application=none,J2EEServer=none Standalone:j2eeType=Servlet,name=jsp,WebModule=//localhost/testsite,J2EEAppl ication=none,J2EEServer=none Standalone:j2eeType=WebModule,name=//localhost/testsite,J2EEApplication=none ,J2EEServer=none Standalone:type=Cache,host=localhost,path=/testsite Standalone:type=Loader,path=/testsite,host=localhost Standalone:type=Manager,path=/testsite,host=localhost If the code above is modified to remove the call to createWebappLoader, the webapp is loaded correctly and the exported MBeans match what is available when the same webapp is loaded if deployed directly in the Tomcat5 webapps directory at startup: Catalina:type=NamingResources,resourcetype=Context,path=/testsite,host=local host Standalone:j2eeType=Servlet,name=CookiesDump,WebModule=//localhost/testsite, J2EEApplication=none,J2EEServer=none Standalone:j2eeType=Servlet,name=default,WebModule=//localhost/testsite,J2EE Application=none,J2EEServer=none Standalone:j2eeType=Servlet,name=jsp,WebModule=//localhost/testsite,J2EEAppl ication=none,J2EEServer=none Standalone:j2eeType=WebModule,name=//localhost/testsite,J2EEApplication=none ,J2EEServer=none Standalone:type=Cache,host=localhost,path=/testsite Standalone:type=Loader,path=/testsite,host=localhost Standalone:type=Manager,path=/testsite,host=localhost It seems that the invocation of the createWebappLoader operation ends up creating an extra Loader instance somehow that confuses the ClassLoader configuration for the webapp context. I verified that the createStandardContext operation does indeed construct a Loader when start() is invoked on the context container. Apparently, either the createStandardContext is not supposed to create the Loader or the createWebappLoader operation should not be used in the admin webapp... then again, I might be missing something! Can anyone clarify how the createStandardContext should be invoked? You can look at the JBoss integration code for examples. Part of the code: String objectNameS = config.getCatalinaDomain() + :j2eeType=WebModule,name=// + ((hostName == null) ? localhost : hostName) + ctxPath + ,J2EEApplication=none,J2EEServer=none; ObjectName objectName = new ObjectName(objectNameS); server.createMBean(org.apache.commons.modeler.BaseModelMBean, objectName, new Object[]{config.getContextClassName()}, new String[]{java.lang.String}); server.setAttribute(objectName, new Attribute(docBase, url.getFile())); server.setAttribute(objectName, new Attribute (defaultWebXml, web.xml)); if (config.isUseJBossWebLoader()) { WebCtxLoader webLoader = new WebCtxLoader(loader); webLoader.setWarURL(url); server.setAttribute(objectName, new Attribute (loader, webLoader)); } else { server.setAttribute(objectName, new Attribute (parentClassLoader, loader)); } server.setAttribute(objectName, new Attribute (delegate, new
Re: Tomcat5 MBeans/JMX context creation
Remy Maucherat wrote: Randy Watler wrote: I am currently experimenting with the Java 1.5 remote JMX/MBeans for use in our build process. ... Can anyone clarify how the createStandardContext should be invoked? You can look at the JBoss integration code for examples. ... There's additional code, but this is for creating a basic context, and configuring its classloader. The Tomcat code which allows doing this is a lot more recent than the harcoded admin webapp methods, and is more JavaBean like. Remy, Note that I am using the JMX remote Out-of-the-box Java 1.5 Monitoring and Management, so some of the JBoss setup may not apply, (like the ClassLoader configuration that passes object instances). Here is what I am trying: // create context mbeanServer.createMBean( org.apache.commons.modeler.BaseModelMBean, context, new Object [] { org.apache.catalina.core.StandardContext }, new String [] { java.lang.String } ) ; mbeanServer.setAttribute( context, new Attribute( docBase, /tmp/testsite ) ) ; mbeanServer.setAttribute( context, new Attribute( path, /testsite ) ) ; // start context mbeanServer.invoke( context, start, null, null ) ; Unfortunately, the createMBean call above throws the following exception: javax.management.ReflectionException: The MBean class could not be loaded by the default loader repository at com.sun.jmx.mbeanserver.MBeanInstantiatorImpl.findClassWithDefaultLoaderRepo sitory(MBeanInstantiatorImpl.java:61) at com.sun.jmx.mbeanserver.MBeanInstantiatorImpl.instantiate(MBeanInstantiatorI mpl.java:378) at com.sun.jmx.mbeanserver.JmxMBeanServer.instantiate(JmxMBeanServer.java:1011) at com.sun.jmx.remote.security.MBeanServerAccessController.createMBean(MBeanSer verAccessController.java:167) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl. java:1418) at javax.management.remote.rmi.RMIConnectionImpl.access+100(RMIConnectionImpl.j ava:81) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMICon nectionImpl.java:1301) at java.security.AccessController.doPrivileged(Native Method) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConne ctionImpl.java:1395) at javax.management.remote.rmi.RMIConnectionImpl.createMBean(RMIConnectionImpl. java:337) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39 ) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl .java:25) at java.lang.reflect.Method.invoke(Method.java:494) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport+1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:7 01) at java.lang.Thread.run(Thread.java:566) at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteC all.java:247) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at com.sun.jmx.remote.internal.PRef.invoke(Unknown Source) at javax.management.remote.rmi.RMIConnectionImpl_Stub.createMBean(Unknown Source) at javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.createM Bean(RMIConnector.java:662) at InstallTask.execute(InstallTask.java:84) ... 1 more Caused by: java.lang.ClassNotFoundException: org.apache.commons.modeler.BaseModelMBean at com.sun.jmx.mbeanserver.ClassLoaderRepositorySupport.loadClass(ClassLoaderRe positorySupport.java:208) at com.sun.jmx.mbeanserver.ClassLoaderRepositorySupport.loadClass(ClassLoaderRe positorySupport.java:128) at com.sun.jmx.mbeanserver.MBeanInstantiatorImpl.findClassWithDefaultLoaderRepo sitory(MBeanInstantiatorImpl.java:58) at com.sun.jmx.mbeanserver.MBeanInstantiatorImpl.instantiate(MBeanInstantiatorI mpl.java:378) at com.sun.jmx.mbeanserver.JmxMBeanServer.instantiate(JmxMBeanServer.java:1011) at com.sun.jmx.remote.security.MBeanServerAccessController.createMBean(MBeanSer verAccessController.java:167) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl. java:1418) at javax.management.remote.rmi.RMIConnectionImpl.access+100(RMIConnectionImpl.j ava:81) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMICon nectionImpl.java:1301) at java.security.AccessController.doPrivileged(Native Method) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConne ctionImpl.java:1395) at