4 Replies Latest reply on Oct 12, 2015 11:43 AM by ehugonnet

    How to find out WildFly version number from JVM agent?

    xmoravec

      Hello,

       

      Is there any way to find out the version number of WildFly 9 and 10 from a JVM agent? I tried adding the org.jboss.as.version module JAR on the AS bootclasspath and the idea was that I would be able to retrieve the version number from the org.jboss.as.version.Version class, however this approach fails because of a NPE that occurs in the static initializer of the Version class. It is thrown on this line:

       

      InputStream stream = Version.class.getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");

       

      The "problem" with JVM agents is that they are loaded by the JVM bootstrap classloader and therefore Version.class.getClassLoader() may, as per the Java spec, return null. My Oracle JDK 7 on Windows indeed returns null.

       

      What worked well in older JBoss releases (JBoss 7 Community, JBoss 6 EAP) was that these releases exposed the JBoss AS runtime info including the version number through the "jboss.system:type=Server" or "jboss.as:management-root=server" MBeans. This approach no longer works with WildFly 9 and 10 because these MBeans are exported and I did not find any alternative MBean that would contain this information.

       

      If possible I would like to avoid iterating through all MANIFEST.MF files on the bootclasspath and looking for the version number there. Is there any better way?

       

      Thank you,

      Jan

        • 1. Re: How to find out WildFly version number from JVM agent?
          jamezp

          You could use a management operation to determine the version. Something like:

          static void listRunningVerssion() throws Exception {
              try (ModelControllerClient client = ModelControllerClient.Factory.create("localhost", 9990)) {
                  final ModelNode op = Operations.createReadResourceOperation(new ModelNode().setEmptyList());
                  final ModelNode result = client.execute(op);
                  if (Operations.isSuccessfulOutcome(result)) {
                      final ModelNode model = Operations.readResult(result);
                      final String productName;
                      if (model.hasDefined("product-name")) {
                          productName = model.get("product-name").asString();
                      } else {
                          productName = "WildFly";
                      }
          
          
                      String productVersion = null;
                      if (model.hasDefined("product-version")) {
                          productVersion = model.get("product-version").asString();
                      }
          
          
                      String releaseCodename = null;
                      if (model.hasDefined("release-codename")) {
                          releaseCodename = model.get("release-codename").asString();
                      }
          
          
                      String releaseVersion = null;
                      if (model.hasDefined("release-version")) {
                          releaseVersion = model.get("release-version").asString();
                      }
          
          
                      System.out.printf("Product: %s%n", productName != null ? productName : "WildFly");
                      System.out.printf("Product Version: %s%n", productVersion);
                      System.out.printf("Codename: %s%n", releaseCodename);
                      System.out.printf("Release Version: %s%n", releaseVersion);
                  } else {
                      System.out.println(result);
                      System.out.println(Operations.getFailureDescription(result));
                  }
              }
          }
          

           

          When running WildFly 10.0.0.CR2 I get the following results:

          Product: WildFly Full
          Product Version: 10.0.0.CR2
          Codename: Kenny
          Release Version: 2.0.0.CR5
          

           

          The Release Version is the version for WildFly Core being used.

           

          --

          James R. Perkins

          • 2. Re: How to find out WildFly version number from JVM agent?
            ehugonnet

            With Wildfly 10 you have the product-info command which will return some information about your running host:

            Taking on James code :

            static void listRunningVerssion() throws Exception {
                    try (ModelControllerClient client = ModelControllerClient.Factory.create("localhost", 9990)) {
                        final ModelNode op = Operations.createOperation("product-info",new ModelNode().setEmptyList());
                        final ModelNode result = client.execute(op);
                        if (Operations.isSuccessfulOutcome(result)) {
                            final ModelNode model = Operations.readResult(result).require("summary");
                            final String productName;
                            if (model.hasDefined("product-name")) {
                                productName = model.get("product-name").asString();
                            } else {
                                productName = "WildFly";
                            }
               
               
                            String productVersion = null;
                            if (model.hasDefined("product-version")) {
                                productVersion = model.get("product-version").asString();
                            }
                         
                            System.out.printf("Product: %s%n", productName != null ? productName : "WildFly");
                            System.out.printf("Product Version: %s%n", productVersion);
                        } else {
                            System.out.println(result);
                            System.out.println(Operations.getFailureDescription(result));
                        }
                    }
                }
            
            

            You can have more informations on the target server :

            [standalone@localhost:9990 /] :product-info()

            {

                "outcome" => "success",

                "result" => [{"summary" => {

                    "host-name" => "localhost",

                    "instance-identifier" => "8f704bd3-9eac-436a-b6d1-56434eab4363",

                    "product-name" => "WildFly Full",

                    "product-version" => "10.0.0.CR3-SNAPSHOT",

                    "product-community-identifier" => "Product",

                    "product-home" => "/home/ehsavoie/dev/wildfly/wildfly/dist/target/wildfly-10.0.0.CR3-SNAPSHOT",

                    "standalone-or-domain-identifier" => "STANDALONE_SERVER",

                    "host-operating-system" => "Ubuntu 15.04",

                    "host-cpu" => {

                        "host-cpu-arch" => "amd64",

                        "host-core-count" => 4

                    },

                    "jvm" => {

                        "name" => "Java HotSpot(TM) 64-Bit Server VM",

                        "java-version" => "1.8",

                        "jvm-version" => "1.8.0_60",

                        "jvm-vendor" => "Oracle Corporation",

                        "java-home" => "/usr/lib/jvm/java-8-oracle/jre"

                    }

                }}]

            }

             

            • 3. Re: How to find out WildFly version number from JVM agent?
              xmoravec

              Thanks James and Emmanuel a lot for your quick replies.

               

              I forgot to mention that, if possible, I would like to avoid using any app server specific APIs because the agent must remain compatible with 5 other app servers and as such it cannot have any runtime dependencies on proprietary APIs (JBoss management APIs in this particular case). I could rewrite your code to use Java reflection to workaround the problem, but I am not sure if agent can access the management APIs as the management API does not seem to be on its classpath. This is the classpath of my agent on JBoss 9:

               

              [code]

              [2015-10-06 11:10:57,832] I [main] [com.quartzdesk.agent.Agent:435] - JVM Agent class class-loader:

              sun.misc.Launcher$AppClassLoader@5e3a78ad

                file:/D:/Java/wildfly-9.0.1.Final-lmc/jboss-modules.jar

                file:/D:/Java/wildfly-9.0.1.Final-lmc/modules/system/layers/base/com/quartzdesk/agent/main/quartzdesk-agent.jar

              sun.misc.Launcher$ExtClassLoader@50c8d62f

                file:/D:/Java/Jdk1.7/jre/lib/ext/access-bridge-64.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/dnsns.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/jaccess.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/localedata.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/sunec.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/sunjce_provider.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/sunmscapi.jar

                file:/D:/Java/Jdk1.7/jre/lib/ext/zipfs.jar

              [/code]

               

              I finally came up with a simple solution that obtains the app server version number from the WildFly org.jboss.as.version module's manifest.

               

              [code]

              private AppServerInfo prepareWildFlyInfo()

                {

                  AppServerInfo appServerInfo = null;

               

                  String moduleDirStr = System.getenv( "JBOSS_MODULEPATH" );

                  if ( moduleDirStr != null )

                  {

                    // find wildfly-version

                    File moduleDir = new File( moduleDirStr );

                    if ( moduleDir.exists() )

                    {

                      Collection<File> versionJars = findMatchingFiles( moduleDir, new FilenameFilter()

                      {

                        @Override

                        public boolean accept( File dir, String name )

                        {

                          // looking for wildfly-version-x.y.z.Final.jar

                          return name.startsWith( "wildfly-version-" );

                        }

                      } );

               

                      if ( versionJars.size() == 1 )

                      {

                        try

                        {

                          JarFile jarFile = new JarFile( versionJars.iterator().next() );

                          Manifest manifest = jarFile.getManifest();

                          if ( manifest != null )

                          {

                            appServerInfo = prepareWildFlyInfo( manifest );

                          }

                        }

                        catch ( IOException e )

                        {

                          // should not happen

                        }

                      }

                    }

                  }

               

                  return appServerInfo;

                }

               

               

                private AppServerInfo prepareWildFlyInfo( Manifest manifest )

                {

                  /*

                   * Implementation-Title: WildFly: Version

                   * JBossAS-Release-Version: 1.0.1.Final (for WildFly 9.0.1.Final)

                   * JBossAS-Release-Version: 2.0.0.CR1 (for WildFly 10.0.0.CR1)

                   */

                  String implementationTitle = manifest.getMainAttributes().getValue( "Implementation-Title" );

                  if ( implementationTitle != null && "WildFly: Version".equals( implementationTitle ) )

                  {

                    String releaseVersion = manifest.getMainAttributes().getValue( "JBossAS-Release-Version" );

                    if ( releaseVersion != null )

                    {

                      return new AppServerInfo()

                          .withName( "WildFly" )

                          .withVersion( releaseVersion );

                    }

                  }

               

                  return null;

                }

               

               

                /**

                 * Recursively searches for matching files in the specified directory and all of its subdirectories.

                 *

                 * @param dir    the directory where to start searching.

                 * @param filter a file name filter.

                 * @return the matching files.

                 */

                private Collection<File> findMatchingFiles( File dir, FilenameFilter filter )

                {

                  Collection<File> result = new ArrayList<File>();

                  findMatchingFiles( dir, filter, result );

                  return result;

                }

               

               

                private void findMatchingFiles( File dir, FilenameFilter filter, Collection<File> result )

                {

                  File[] files = dir.listFiles();

                  if ( files != null && files.length > 0 )

                  {

                    for ( File file : files )

                    {

                      if ( file.isDirectory() )

                      {

                        findMatchingFiles( file, filter, result );

                      }

                      else

                      {

                        if ( filter.accept( file.getParentFile(), file.getName() ) )

                        {

                          result.add( file );

                        }

                      }

                    }

                  }

                }

              [/code]

              • 4. Re: How to find out WildFly version number from JVM agent?
                ehugonnet

                Most of this code is in the wildfly-version module: look into ProductConfig in widlfy-core/wildfly-version