Wednesday, October 26, 2016

Monitoring Artemis on JBoss EAP 7 with Hawtio

In case you want to use Hawtio on JBoss EAP 7 to monitor the Apache ActiveMQ Artemis message broker, you can follow these steps


  • Download hawtio 1.4.66 from https://oss.sonatype.org/content/repositories/public/io/hawt/hawtio-no-slf4j/1.4.66/hawtio-no-slf4j-1.4.66.war
  • Copy hawtio-no-slf4j-1.4.66.war to JBOSS_HOME/standalone/deployments/hawtio.war 
  • Build the Hawtio Artemis Plugin

git clone https://github.com/rh-messaging/artemis-hawtio/
cd artemis-hawtio
mvn clean install

  • Copy artemis/target/artemis-plugin-1.0.0-SNAPSHOT.war to JBOSS_HOME/standalone/deployments/artemis-plugin.war
  • Execute the following commands via the JBoss CLI

/subsystem=messaging-activemq/server=default:write-attribute(name=jmx-management-enabled, value=true)
/subsystem=messaging-activemq/server=default:write-attribute(name=statistics-enabled,value=true)

Now you navigate to http://<JBoss-Management-IP>:8080/hawtio and watch Hawtio in action.

Below you can find example when pushing Artemis to it's limits, using a custom dashboard to show queue statistics:

Monday, June 29, 2015

Connecting jvisualvm to JBoss EAP 6.2 on Windows

In case you want to use jvisualvm to connect up to JBoss EAP 6.2 on Windows, you can use the following script (which should be placed into JBOSS_HOME/bin as jvisualvm.bat):
@echo off  
rem -------------------------------------------------------------------------  
rem jvisualvm script for Windows  
rem -------------------------------------------------------------------------  
rem  
rem A script for running jvisualvm with the remoting-jmx libraries on the classpath.  
  
rem $Id$  
  
@if not "%ECHO%" == ""  echo %ECHO%  
@if "%OS%" == "Windows_NT" setlocal  
  
if "x%JAVA_HOME%" =="x" (  
    echo JAVA_HOME environment variable has not been set - please set and re-run!  
    goto :EOF  
)  
  
if "%OS%" == "Windows_NT" (  
  set "DIRNAME=%~dp0%"  
) else (  
  set DIRNAME=.\  
)  
  
pushd %DIRNAME%..  
set "RESOLVED_JBOSS_HOME=%CD%"  
popd  
  
if "x%JBOSS_HOME%" == "x" (  
  set "JBOSS_HOME=%RESOLVED_JBOSS_HOME%"  
)  
  
pushd "%JBOSS_HOME%"  
set "SANITIZED_JBOSS_HOME=%CD%"  
popd  
  
if "%RESOLVED_JBOSS_HOME%" NEQ "%SANITIZED_JBOSS_HOME%" (  
    echo WARNING JBOSS_HOME may be pointing to a different installation - unpredictable results may occur.  
)  
  
set DIRNAME=  
  
if "%OS%" == "Windows_NT" (  
  set "PROGNAME=%~nx0%"  
) else (  
  set "PROGNAME=jdr.bat"  
)  
  
rem Setup JBoss specific properties  
if "x%JAVA_HOME%" == "x" (  
  echo JAVA_HOME is not set. Unable to locate the jars needed to run jconsole.  
  goto END  
)  
  
rem Find jboss-modules.jar, or we can't continue  
if exist "%JBOSS_HOME%\jboss-modules.jar" (  
    set "RUNJAR=%JBOSS_HOME%\jboss-modules.jar"  
) else (  
  echo Could not locate "%JBOSS_HOME%\jboss-modules.jar".  
  echo Please check that you are in the bin directory when running this script.  
  goto END  
)  
  
rem Setup The Classpath  
set CLASSPATH=%JBOSS_HOME%\bin\client\jboss-cli-client.jar  
  
  
"%JAVA_HOME%\bin\jvisualvm.exe" "-cp:a" "%CLASSPATH%"  
  
:END  
goto :EOF  
:EOF 

Now inside jvisualvm you can connect to JBoss EAP 6 using JMX and a URL of the form service:jmx:remoting-jmx://<host>:<native-management-port>

See also "How to connect to JBoss EAP 6 using JConsole" (https://access.redhat.com/solutions/149973)

Thursday, April 9, 2015

Creating a JMS Bridge with XA on JBoss EAP 6.3

In case you want to create a JMS Bridge supporting XA on JBoss EAP 6.3 here are some hints on how to achieve this. I'm using HornetQ and ActiveMQ (with resource-adapter version 5.11.1) througout the example with queue A and C residing on ActiveMQ and a queue B on HornetQ, messages will be bridged from queue A to B to C.

In standalone configuration file add the following admin-object to the resource-adapter configuration for ActiveMQ:
<admin-object class-name="org.apache.activemq.ActiveMQXAConnectionFactory" jndi-name="java:/AMQXAConnectionFactory" enabled="true" use-java-context="true" pool-name="AMQXAConnectionFactory">
     <config-property name="brokerURL">
                                failover:(tcp://localhost:61616)?jms.rmIdFromConnectionId=true&amp;maxReconnectAttempts=0&amp;jms.xaAckMode=2&amp;jms.userName=admin&amp;jms.password=redhat
      </config-property>
 </admin-object>
You also need to do a modification to the ra.xml of the ActiveMQ resource-adapter consisting of adding the following:

<adminobject>
          <adminobject-interface>javax.jms.XAConnectionFactory</adminobject-interface>
          <adminobject-class>org.apache.activemq.ActiveMQXAConnectionFactory</adminobject-class>
          <config-property>
            <config-property-name>brokerURL</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
          </config-property>
</adminobject>

In the messaging subsystem add the following after hornetq-server:

<jms-bridge name="activemq-hornetq">
     <source>
           <connection-factory name="AMQXAConnectionFactory"/>
           <destination name="queue/queueA"/>
      </source>
      <target>
            <connection-factory name="XAConnectionFactory"/>
            <destination name="queue/queueB"/>
       </target>
       <quality-of-service>ONCE_AND_ONLY_ONCE</quality-of-service>
       <failure-retry-interval>1000</failure-retry-interval>
       <max-retries>-1</max-retries>
       <max-batch-size>1</max-batch-size>
       <max-batch-time>100</max-batch-time>
</jms-bridge>
<jms-bridge name="hornetq-activemq">
       <source>
             <connection-factory name="XAConnectionFactory"/>
             <destination name="queue/queueB"/>
       </source>
       <target>
             <connection-factory name="AMQXAConnectionFactory"/>
             <destination name="queue/queueC"/>
       </target>
       <quality-of-service>ONCE_AND_ONLY_ONCE</quality-of-service>
       <failure-retry-interval>1000</failure-retry-interval>
       <max-retries>-1</max-retries>
       <max-batch-size>1</max-batch-size><max-batch-time>100</max-batch-time>
 </jms-bridge>

Now your JMS bridge is ready to operate!

Tuesday, December 2, 2014

Deploying Hawtio on JBoss EAP 6

In this article I describe how to successfully deploy Hawtio on JBoss EAP.

You would need

  • JBoss EAP 6 (I have used JBoss EAP 6.2 which can be downloaded from here) 
  • Hawtio Web-Application (the version 1.4.37 can be obtained from here)

Before actually deploying Hawtio you would need to do some small changes on hawtio-no-slf4j-1.4.37.war.

  • To WEB-INF/lib/guava-15.0.jar add META-INF/beans.xml with the following content
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:weld="http://jboss.org/schema/weld/beans"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd
                           http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">
 <weld:scan>
   <weld:exclude name="com.google.**"/>
 </weld:scan>
</beans>
        as otherwise the application will not deploy successfully and will report the
        following error
21:15:28,074 INFO  [org.jboss.weld.deployer] (MSC service thread 1-3) JBAS016005: Starting Services for CDI deployment: hawtio-no-slf4j-1.4.37.war
21:15:28,091 INFO  [org.jboss.weld.deployer] (MSC service thread 1-4) JBAS016008: Starting weld service for deployment hawtio-no-slf4j-1.4.37.war
21:15:29,659 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-7) MSC000001: Failed to start service jboss.deployment.unit."hawtio-no-slf4j-1.4.37.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."hawtio-no-slf4j-1.4.37.war".WeldStartService: Failed to start service
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1767) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_55]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_55]
        at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_55]
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[parameter 1] of [constructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)]
        at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:312)
        at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
        at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:144)
        at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:164)
        at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:383)
        at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:368)
        at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:379)
        at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:64)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]
        ... 3 more

21:15:29,877 ERROR [org.jboss.as.server] (HttpManagementService-threads - 3) JBAS015870: Deploy of deployment "hawtio-no-slf4j-1.4.37.war" was rolled back with the following failure message:
{"JBAS014671: Failed services" => {"jboss.deployment.unit.\"hawtio-no-slf4j-1.4.37.war\".WeldStartService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"hawtio-no-slf4j-1.4.37.war\".WeldStartService: Failed to start service
    Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[parameter 1] of [constructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)]"}}
21:15:29,898 INFO  [org.jboss.weld.deployer] (MSC service thread 1-2) JBAS016009: Stopping weld service for deployment hawtio-no-slf4j-1.4.37.war
21:15:30,003 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment hawtio-no-slf4j-1.4.37.war (runtime-name: hawtio-no-slf4j-1.4.37.war) in 128ms
  • Add WEB-INF/jboss-web.xml as follows
<jboss-web>
  <context-root>/hawtio</context-root>
</jboss-web>
  •  Add WEB-INF/jboss-deployment-structure.xml as follows
<?xml version="1.0"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.apache.log4j"/>
      <module name="org.slf4j"/>
      <module name="org.slf4j.impl"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>

  • Remove WEB-INF/classes/log4j.properties
Now you can deploy hawtio-no-slf4j-1.4.37.war to JBoss EAP 6

Tuesday, November 25, 2014

Using ELK's JMX Plugin to gather JBoss EAP metrics

In this short blog post I outline how to use the ELK (ElasticSearch/LogStash/Kibana) stack to gather data via JMX from JBoss EAP 6.

Ingredients:

- ElasticSearch 1.4.0
- Logstash 1.4.2
- Kibana 3.1.2
- JBoss EAP 6.2

After having gone throught the downloading and installation process first we need to extract some libs out of the modules for JBoss EAP 6.2 that are needed for getting remote JMX calls to work.

In elastic-search-1.4.0/vendor/bundle/jruby/1.9/gems/jmx4r-0.1.4/lib create a file jboss_remoting.rb

module JMX
  module JBoss
    java_import java.lang.System

    class JBossRemoting

      sep = System.get_property 'file.separator'
      home = System.get_property 'jboss.home'

      if home != nil
        modulebase = [home, 'modules','system','layers','base','org','jboss'].join(sep)

        libs = [
          ['remoting-jmx','main'],
          ['remoting3','main'],
          ['logging','main'],
          ['xnio','main'],
          ['xnio','nio','main'],
          ['sasl','main'],
          ['marshalling','main'],
          ['marshalling','river','main'],
          ['as','cli','main'],
          ['staxmapper','main'],
          ['as','protocol','main'],
          ['dmr','main'],
          ['as','controller-client','main'],
          ['threads','main']
        ]

        for index in 0 ... libs.size
          Dir[modulebase + sep + libs[index].join(sep) + sep + "*.jar"].each {|file| require file }
        end
      end
    end
  end
end

In elastic-search-1.4.0/vendor/bundle/jruby/1.9/gems/jmx4r-0.1.4/lib/jmx4r.rb after

    require 'jruby'

            add
    require 'jboss_remoting'
    In logstash-1.4.2/config/logstash.conf I created the following configuration

    input {
    jmx{
        path => "logstash-1.4.2/jmx"
        polling_frequency => 30
        type => "jmx"
        nb_thread => 4
      }
    }

    output {
      elasticsearch { host => localhost }
    }

    and in logstash-1.4.2/jmx/jmx.conf I configured

    {
      // JBoss Remoting JMX URL
      "url" : "service:jmx:remoting-jmx://localhost:9999",
      //username to connect to jmx
      "username" : "<your-user>",
      //password to connect to jmx
      "password": "<your-password>",
      "alias" : "jmx.instance1.elasticsearch",
      //List of JMX metrics to retrieve
      "queries" : [
        {
          "object_name" : "java.lang:type=Memory",
          "attributes" : [ "HeapMemoryUsage", "NonHeapMemoryUsage" ],
          "object_alias" : "Memory"
        }, {
          "object_name" : "java.lang:type=Runtime",
          "attributes" : [ "Uptime", "StartTime" ],
          "object_alias" : "Runtime"
        }, {
          "object_name" : "java.lang:type=Threading",
          "attributes" : [ "ThreadCount", "TotalStartedThreadCount", "DaemonThreadCount", "PeakThreadCount" ],
          "object_alias" : "Threading"
        }, {
          "object_name" : "java.lang:type=OperatingSystem",
          "attributes" : [ "OpenFileDescriptorCount", "FreePhysicalMemorySize", "CommittedVirtualMemorySize", "FreeSwapSpaceSize", "ProcessCpuLoad", "ProcessCpuTime", "SystemCpuLoad", "TotalPhysicalMemorySize", "TotalSwapSpaceSize", "SystemLoadAverage" ],
          "object_alias" : "OperatingSystem"
        } ]
    }

    As the original JMX input plugin only supports configuration via host and port you need to apply the pull request 141 (https://github.com/elasticsearch/logstash-contrib/pull/141) to your local installation, i.e. by downloading https://raw.githubusercontent.com/jcordes73/logstash-contrib/master/lib/logstash/inputs/jmx.rb and save it to logstash-1.4.2/lib/logstash/inputs

    Now you need to setup a JBoss management user via jboss-eap-6.2/bin/add-user.sh to reflect the username and password defined in jmx.conf above.

    Because of a change in behaviour in regards to security you need to add the following configuration to elasticsearch-1.4.0/config/elasticsearch.yml

    http.cors.enabled: true
    http.cors.allow-origin: "*"
    and also change http.enabled to true.

    We need to set some environment variables so that the JBoss Remoting libraries can be found from an existing JBoss EAP installation:

    JBOSS_HOME=/opt/jboss-eap-6.2
    export JBOSS_HOME
    JAVA_OPTS="-Djboss.home=$JBOSS_HOME"
    export JAVA_OPTS
    Now you can start ElasticSearch via elasticsearch-1.4.0/bin/elasticsearch and logstash via logstash-1.4.2/bin/logstash -f logstash-1.4.2/config/logstash.conf.

    To finally see your JMX data via Kibana, open kibana-3.1.2/index.html with your favourite web-browser.

    Tuesday, November 11, 2014

    Hawtio authentication with LDAP on JBoss Fuse

    Finally here is the second part on Hawtio authentication with LDAP, this time on JBoss Fuse / A-MQ 6.1

    • Create a file named ldap-auth.xml and copy it into the deploy folder (you need to adjust the LDAP settings according to your structure)
    <?xml version="1.0" encoding="UTF-8"?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0" xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
    <ext:property-placeholder placeholder-prefix="${" placeholder-suffix="}"/>
    <jaas:config name="karaf" rank="2">
    <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required">
    connection.url=ldap://<LDAP-IP>:389
    connection.username=cn=Manager,dc=redhat,dc=com
    connection.password=redhat
    user.base.dn=ou=User,ou=ActiveMQ,dc=activemq,dc=redhat,dc=com
    user.filter=(uid=%u)
    user.search.subtree=true
    role.base.dn=ou=User,ou=ActiveMQ,dc=activemq,dc=redhat,dc=com
    role.filter=(uid=%u)
    role.name.attribute=uid
    role.search.subtree=true
    authentication=simple
    </jaas:module>
    </jaas:config>
    </blueprint> 
     (see also https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_A-MQ/6.1/html-single/Security_Guide/index.html#JAASAuth-LDAPLoginModule)

    •  In etc/system.properties add
    hawtio.authenticationEnabled=true
    hawtio.realm=karaf
    hawtio.role=admin
    hawtio.rolePrincipalClasses=org.apache.karaf.jaas.boot.principal.RolePrincipal,org.apache.karaf.jaas.modules.RolePrincipal,org.apache.karaf.jaas.boot.principal.GroupPrincipal

    (see https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.1/html-single/Security_Guide/#WebConsole))

    HornetQ-ActiveMQ Bridge

    In case you need a messaging bridge between HornetQ on JBoss EAP and ActiveMQ on JBoss Fuse / A-MQ then the projects on Github at https://github.com/jcordes73/messaging-bridges maybe what you are after.

    There I'm featuring

    • JBoss Fuse / A-MQ 6.1
    • JBoss EAP 6.x (at least 6.1.1 required)
    • ActiveMQ on JBoss Fuse / A-MQ
    • HornetQ on JBoss EAP 6
    • ActiveMQ RAR Adapter on JBoss EAP 6
    • SSL for JBoss Fuse / A-MQ <--> JBoss EAP communication
    • XA
    The bridge comes in two flavours

    • Running on JBoss EAP
    • Running on JBoss Fuse / A-MQ