Monday, September 29, 2014

How do I configure Red Hat JBoss Fuse to send an Email when specific logging event occurs?

In the post I will describe how to configure Fuse ESB to automatically send emails when certain logging events occur. This technique uses Log4j’s SMTPAppender.

Log4j can be configured to push email notification immediately when an ERROR occurs inside the ESB.
The configuration of the SMTPAppender within Fuse is not particularly straight forward. There are some gotchas that I have attempted to point out here. Perhaps future versions of Fuse will make it easier to configure this.

These instructions are written based on Fuse version 6.0.0.redhat-024 available for download in platform independent form here (download zip file):
http://repo.fusesource.com/nexus/content/groups/public/org/jboss/fuse/jboss-fuse/6.0.0.redhat-024/

Or, assuming you have maven installed, the following command will download the installation .zip file, and put the file into your local maven repository:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:get -Dartifact=org.jboss.fuse:jboss-fuse:6.0.0.redhat-024:zip

Some of the complications with getting this to work are reported in the following bug report:
https://issues.apache.org/jira/i#browse/KARAF-3067

My research indicates that you must apply the configuration to a “fresh” installation of Fuse. If you have an existing installation of Fuse, you must clear the bundle cache (i.e. completely remove the ‘data’ directory), then make the necessary configuration changes before starting Fuse for the first time. This is annoying if you have an existing installation and merely wish to add the feature to an existing installation.
Here are the steps I took to enable SMTPAppender on a fresh install of Fuse. Before starting Fuse for the first time, I applied the following steps:

1)      Added configuration for the SMTP Appender (as shown below) into [jboss-fuse-6.0]/etc /org.ops4j.pax.logging.cfg. Be sure to back up the file first. See updated configuration below:
           # Root logger

log4j.rootLogger=INFO, out, osgi:VmLogAppender, mail



# SMTP appender

log4j.appender.mail=org.apache.log4j.net.SMTPAppender

log4j.appender.mail.layout=org.apache.log4j.PatternLayout

log4j.appender.mail.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n

log4j.appender.mail.SMTPPort=25

log4j.appender.mail.SMTPProtocol=smtp

log4j.appender.mail.Subject=JBoss Fuse 6.0 Error Log Message

log4j.appender.mail.SendOnClose=false

log4j.appender.mail.SMTPHost = mailrelay.mycompany.com

log4j.appender.mail.From=username@host1.mycompany.com

log4j.appender.mail.To=lcurry@mycompany.com

#log4j.appender.mail.Threshold=INFO

log4j.appender.mail.SMTPDebug=true

#log4j.appender.mail.SMTPPassword=********

#log4j.appender.mail.SMTPUsername=user@gmail.com

log4j.appender.mail.BufferSize=512

2)      In the  [jboss-fuse-6.0]/etc/jre.properties file I needed to comment out the javax.activation;version="1.1".

This ‘jre.properties’ file allow you to define in Fuse ESB which packages should be provided by the JRE and which can be provided by application bundles. To customize this you can tune the ‘jre.properties’ file. So, you can update this file to prevent JRE’s package ‘javax.activation’ from being exported.

Again make a backup of ‘jre.properties’ before modifying.

Now modify the file as indicated below: Note there are two occurences of ‘javax.activation’ (for JRE 1.6 and 1.7) and you should comment out both.

# Standard package set.  Note that:

#   - javax.transaction* is exported with a mandatory attribute

jre-1.6= \

 javax.accessibility, \

# javax.activation;version="1.1", \

 javax.activity, \

 javax.annotation;version="1.1", \

 javax.annotation.processing;version="1.1", \

 javax.crypto, \

 javax.crypto.interfaces, \

 javax.crypto.spec, \



# Standard package set.  Note that:

#   - javax.transaction* is exported with a mandatory attribute

jre-1.7= \

 javax.accessibility, \

# javax.activation;version="1.1", \

 javax.activity, \

 javax.annotation;version="1.1", \

 javax.annotation.processing;version="1.1", \

 javax.crypto, \

 javax.crypto.interfaces, \

 javax.crypto.spec, \

 javax.imageio, \

3)      Because (previous step) will block the JRE’s version of the package ‘javax.activation’ from being exported, we can force a different version of this package to be used by Fuse.  To do this, copy the following JAR to [jboss-fuse-6.0]/lib/endorsed
          org.apache.servicemix.specs.activation-api-1.1-2.0.0.redhat-60024.jar

You can retrieve the JAR file from the following public maven repository:
http://repo.fusesource.com/nexus/content/groups/public/org/apache/servicemix/specs/org.apache.servicemix.specs.activation-api-1.1/2.0.0.redhat-60024/

Or, assuming you have maven installed, the following command will download the JAR file into your local maven repository:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:get -Dartifact=org.apache.servicemix.specs:org.apache.servicemix.specs.activation-api-1.1:2.0.0.redhat-60024

Note:  The org.apache.servicemix.specs.activator-2.0.0.redhat-60024.jar should be in the [jboss-fuse-6.0]/lib directory, and should already be there by default.

4)      The Log4J SMTPAppender requires a mail bundle be deployed into Fuse. Therefore we must add a mail bundle to Fuse. The recommended way to do this is to configure Fuse so that the bundle is deployed on start-up. Define your own custom feature with a start level low enough to take precendence. I picked up this trick up from KARAF-3067.  This ensure supported version of javax.mail API is installed and used. 
            I created a feature called ‘javax.mail’.  The feature descriptor is called ‘javax.mail-1.0.0.redhat-60024-features.xml.’

<features>

<feature name="javax.mail" version="1.4.5">

   <bundle start-level="7">mvn:javax.mail/mail/1.4.5</bundle>

</feature>

</features>

Copy above feature descriptor to a location where Fuse can find it. Create a directory ‘local-repo’ in the root installation folder. Fuse will look there by default for maven dependencies. The complete path to the location where I copied the descriptor was as follows: [jboss-fuse-6.0]/ local-repo/com/mycompany/features/javax.mail/1.0.0.redhat-60024

The name of the feature descriptor file in that directory was:
javax.mail-1.0.0.redhat-60024-features.xml

Remember, the actual name of the feature descriptor file and the location where it is copied matter (a lot). The location must match the standard well-known maven directory location based on groupId/artifactId/version coordinates.
5)      Add the custom feature ‘javax.mail’ to the set of features that Fuse installs at startup.
So once I have the feature descriptor file in the correct location where Fuse can find it, I will add the feature to the list of features that get installed at Fuse startup. To do this add the feature to the file ‘[jboss-fuse-6.0]/etc/org.apache.karaf.features.cfg’ .  Make a backup of this file, and below shows the necessary additions to this file.

#

# Comma separated list of features repositories to register by default

#

featuresRepositories=\

        mvn:org.apache.karaf.assemblies.features/standard/2.3.0.redhat-60024/xml/features,\

        mvn:org.apache.karaf.assemblies.features/enterprise/2.3.0.redhat-60024/xml/features,\

        mvn:org.apache.cxf.karaf/apache-cxf/2.6.0.redhat-60024/xml/features,\

        mvn:org.apache.camel.karaf/apache-camel/2.10.0.redhat-60024/xml/features,\

        mvn:org.apache.activemq/activemq-karaf/5.8.0.redhat-60024/xml/features,\

        mvn:org.apache.servicemix.nmr/apache-servicemix-nmr/1.6.0.redhat-60024/xml/features,\

        mvn:org.fusesource.fabric/fuse-fabric/7.2.0.redhat-024/xml/features,\

        mvn:org.jboss.fuse/jboss-fuse/6.0.0.redhat-024/xml/features,\

        mvn:org.fusesource.patch/patch-features/7.2.0.redhat-024/xml/features,\

        mvn:com.mycompany.features/javax.mail/1.0.0.redhat-60024/xml/features

 
#

# Comma separated list of features to install at startup

#

featuresBoot=javax.mail,jasypt-encryption,config,management,fabric-boot-commands,fabric-bundle,fabric-maven-proxy,patch,activemq,mq-fabric,camel,camel-cxf,camel-jms,activemq-camel,camel-blueprint,camel-csv,camel-ftp,camel-bindy,camel-jdbc,camel-exec,camel-jasypt,camel-saxon,camel-snmp,camel-ognl,camel-routebox,camel-script,camel-spring-javaconfig,camel-jaxb,camel-jetty,camel-jmx,camel-mail,camel-paxlogging,camel-rmi,war

Note the addition of the feature URL in the ‘featuresRepositories’ property and also the additional feature ‘javax.mail’ added to the front of the ‘featuresBoot’ list.

6)      Finally, after configuring everything -  I start Fuse. The first time I start Fuse after making the configuration changes described above, I got an ERROR that looked something like this:

14:25:46,185 | ERROR | s4j.pax.logging) | configadmin                      | 5 - org.apache.felix.configadm

in - 1.4.0.redhat-60024 | [org.osgi.service.log.LogService, org.knopflerfish.service.log.LogService, org.op

s4j.pax.logging.PaxLoggingService, org.osgi.service.cm.ManagedService, id=9, bundle=3/mvn:org.ops4j.pax.log

ging/pax-logging-service/1.7.0]: Unexpected problem updating configuration org.ops4j.pax.logging

java.lang.NoClassDefFoundError: javax/mail/MessagingException

        at java.lang.Class.getDeclaredConstructors0(Native Method)

        at java.lang.Class.privateGetDeclaredConstructors(Class.java:2532)

        at java.lang.Class.getConstructor0(Class.java:2842)

        at java.lang.Class.newInstance(Class.java:345)

        at org.apache.log4j.helpers.OptionConverter.instantiateByClassName(OptionConverter.java:336)

        at org.apache.log4j.helpers.OptionConverter.instantiateByKey(OptionConverter.java:123)

        at org.apache.log4j.PaxLoggingConfigurator.parseAppender(PaxLoggingConfigurator.java:97)

        at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:735)

        at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:615)

        at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:502)

        at org.apache.log4j.PaxLoggingConfigurator.doConfigure(PaxLoggingConfigurator.java:72)

        at org.ops4j.pax.logging.service.internal.PaxLoggingServiceImpl.updated PaxLoggingServiceImpl.java:

214)

I had to shut down and restart Fuse. The second start seemed to do the trick. At that point I can see the debug logging for SMTP (only from the Fuse console.) If the container is properly configured, and when you start Fuse (the second time) you will see some logging at the Fuse console that indicates the SMTPAppender is operational (per setting   log4j.appender.mail.SMTPDebug=true):

Note: I only saw debug output for log4j SMTP (based on   log4j.appender.mail.SMTPDebug=true) only if I started Fuse in foreground using './fuse' rather than starting Fuse in background with './start'.

7)      To test the email notification, deliberately cause an error in Fuse. For example, you could bogus spring file into the deploy directory (purposely include invalid XML so that the ESB gets an ERROR.)  You should see debug in the Fuse console indicating an email being sent. Or you may see an error of some sort indicating further configuration required for SMTP to work properly.

 

No comments:

Post a Comment