Feeling trapped?

... In this entry I'm going to outline how you could use the Java DMK 5.1 to send an SNMP trap from within an application deployed in Sun's AppServer. So if you're feeling trapped, come and learn with me how you can send them from within a deployed Web Application ...

If you're not familiar with SNMP, I'd suggest that you first start by reading [Simple Is Not Easy] which provides a brief introduction about SNMP - and some links to other materials.

Although I am going to use the Java DMK for this demonstration - the principal aspect of this talk will be to lead you through the small configuration steps that you need to perform to make this happen. As a consequence - I believe you could use this talk to achieve the same thing with your favorite Java SNMP library.

For this demo I'm going to use several things:

  • First, I'm going to use the NetBeans 5.0 + Sun AppServer bundle. This bundle contains the NetBeans 5.0 IDE and the Sun Java System Application Server Platform Edition 8.2.
  • Then, I'm going to use the Java DMK 5.1, for its SNMP API and easymanager contribution.

In the course of this demo we're going to:

  • Write a small WebService that sends an SNMP trap, using the Java DMK 5.1 SNMP API. This is just for the purpose of being able to trigger the emission of a dummy trap. I am not suggesting that using a WebService to send a trap is something that could be useful :-)
  • Configure the Sun AppServer in order to allow that WebService to send traps.
  • Deploy the WebService in the AppServer.
  • Use NetBeans to create and invoke a WebService client for our small WebService.
  • Use the Java DMK 5.1 easymanger contribution to receive the emitted trap.

But before we launch into the demo, let me stress a few things:

A few days ago, I was blogging about traps in SNMP. Readers who are not familiar with traps in SNMP are kindly invited to read this entry first. If you have read this entry - you should now be convinced that you will, at some point, need a MIB definition. Writing a MIB definition for a trap is something that we will not address here. For the sake of the example we will simply assume that the MIB definition exists. Indeed the goal of this exercise is not to give you a course into designing an SNMP Notification system - but rather to show you what steps are necessary in order to make the plumbing work.

Installing Things Which Are Not Yet Installed...

First, let's install everything.

If you haven't installed NetBeans and Sun's AppServer now is a good time to do so. The NetBeans IDE 5.0 Quick Start Guide for J2EE Applications will lead you through the necessary initial environment set up steps. If you have already NetBeans and Sun AppServer installed then fine, don't touch anything ;-)

When this is done, you may want to install the Java DMK 5.1. You can install it there: ${com.sun.aas.installRoot}/lib/ (where ${com.sun.aas.installRoot} is the directory where you installed the Sun AppServer), or at the proposed default location, or if it's already installed elsewhere simply leave it be.

Setting AS_JDMK_HOME in Sun App Server configuration env file

The first thing you need to do is to update the App Server configuration env file. Depending on the platform you're running on the name and syntax of the file may vary - but you will not have any difficulty to find it out. The configuration env file is located under ${com.sun.aas.installRoot}/config.
Usually, it's the only file in the config directory. On Solaris, it's called asenv.conf. On Windows - I think it's called asenv.bat.

Load the file in your favorite editor and look for AS_JDMK_HOME. You will need to set the value of that variable to point to the directory that contains the lib/ directory in which jdmkrt.jar is located. This will be something like:

   AS_JDMK_HOME=/opt/SUNAppserver/lib/SUNWjdmk/5.1 or 
   AS_JDMK_HOME=C:\\Sun\\AppServer\\lib\\SUNWjdmk\\5.1 or 
   AS_JDMK_HOME=/opt/SUNWjdmk/5.1,
                

well you get the idea.

The important thing is that after you're done $AS_JDMK_HOME/lib/jdmkrt.jar should point to jdmkrt.jar.

Finding App Server policy file

The second thing to do is to grant the Java DMK jars the permissions it needs to start the SNMP Adaptor Server. The easiest way to do so is to grant it all permissions ;-). To grant all permission to the Java DMK jar, you will need to edit the server.policy file.

The server.policy file is in your App Server domain instance config directory. Usually it's ${com.sun.aas.installRoot}/domains/domain1/config. If however, you've created your own domain when installing the AppServer with the NetBeans wizard, it may be located elsewhere.

To make it sure, simply start the AppServer with NetBeans, [Runtime->Servers->Sun Java System Application Server], then ask to 'View Server Log' by right clicking on the Sun AppServer node, and when the server has started, ask to 'View Admin Console'.

Alternatively you can open the server's admin console in your Web browser:
right click on the Sun AppServer node to open its properties - the connection tab shows the port you should be using to connect to the admin console.

In the admin console, if you click on 'Application Server' in the left frame, you will see the following information displayed:

The displayed Configuration Directory is the directory that contains your server.policy file.

Setting up the AppServer policy file

Edit the AppServer policy file and add the following block of lines:

// Grant all permissions to Java DMK 5.1 jars:
grant codeBase "file:${com.sun.aas.jdmkHome}/lib/-" {
	permission java.security.AllPermission;
};
                

Updating the AppServer classpath

Now the third thing you need to do is to update the App Server classpath in order to add the Java DMK 5.1 jdmkrt.jar.

The easiest way to do that is to log in on the App Server through the Admin Console as previously shown. Then click on 'Application Server' at the top of the left frame. Then go to "JVM Settings"->"Path Settings" and add

${com.sun.aas.jdmkHome}/lib/jdmkrt.jar

in the "Classpath Suffix" field:

Well that's about it for the configuration. What remains to do is to code and deploy our small application in order to validate that the configuration was correctly set up.

Creating the TrapEmitter Web Service

This is a piece of cake. In NetBeans create a new EJB Module project called 'TrapEmitter'. Select the TrapEmitter project and right click to get the contextual popup menu. Using the popup menu choose [New->File/Folder], and then choose to create a Web Service. Name it 'TrapEmitter'. Choose a package name and click on 'Finish'.
You may not know it yet but you've just created a WebService.

Now in the 'TrapEmitter' project open the 'Web Services' node and select the 'TrapEmitter' service:

Right click on the 'TrapEmitter' node and choose to add an operation. Name it 'startServer' and give it an int parameter called 'localPort'. The operation will return a String

Then repeat the steps above in order to add a corresponding 'stopServer' operation. The operation will have no parameter and will return a String.

Finally, add a 'sendTrap' operation that returns String and has three parameters: String remoteHost, int remotePort, and String trapOid.

That's it, we only need now to provide the code for those operations.

Coding the TrapEmitter operations

Double click on the 'TrapEmitter->Web Services->TrapEmitter' node. NetBeans will open the 'TrapEmitterBean.java' file in the editor window:

Now here is what you need to add: First, add a static variable for the SnmpAdaptorServer:

    // We will use the Java DMK SnmpV3AdaptorServer to send traps:
    //
    private static volatile SnmpV3AdaptorServer server = null;
                

Then fill in the code for the three WebServices methods we have defined:

    /\*\*
     \* Web service operation
     \*/
    public String startServer(int localPort) 
        throws java.rmi.RemoteException {

        final int portNb = localPort;
        final Logger LOG = Logger.getLogger("com.sun.jdmk.examples.misc");

        LOG.info("operation startServer called");
        if (server == null) {
            server =
                new SnmpV3AdaptorServer(portNb);
                LOG.info("SnmpV3AdaptorServer created with "+ portNb);
        }
        if (!server.isActive()) {
            LOG.info("Starting Server with "+server.getPort());
            server.start();
            LOG.info("Called SnmpV3AdaptorServer.start()");
        }
        LOG.info("Waiting for SnmpV3AdaptorServer to start...");
        server.waitState(CommunicatorServer.ONLINE,5000);
        if (!server.isActive()) {
            LOG.info("Server didn't start");
            throw new RuntimeException("Failed to start server");
        }
        LOG.info("Server started at: "+server.getHost()+":"+server.getPort());
        return server.toString()+": "+server.getHost()+
               ":"+server.getPort();
    }
                

    /\*\*
     \* Web service operation
     \*/
    public String stopServer() 
        throws java.rmi.RemoteException {

        final Logger LOG = Logger.getLogger("com.sun.jdmk.examples.misc");
 
        if (server == null) return "No server - request ignored";
        try {
            if (server.isActive()) {
                LOG.fine("Stopping server");
                server.stop();
            }
            LOG.fine("Waiting for server to stop");
            server.waitState(CommunicatorServer.OFFLINE,5000);
            if (server.isActive())
                LOG.fine("Couldn't stop server: still active");
            else server = null;
        } catch (Exception x) {
            LOG.fine("Couldn't stop server: "+x);
        }
   
        return ((server==null)?"server stopped":"failed to stop");
    }
                

    /\*\*
     \* Web service operation
     \*/
    public String sendTrap(String remoteHost, int remotePort, String trapOid) 
        throws java.rmi.RemoteException {

        final Logger LOG = Logger.getLogger("com.sun.jdmk.examples.misc");
        LOG.info("operation sendTrap called");

        if (server == null) {
            LOG.info("SnmpV3AdaptorServer not created! ");
            throw new RuntimeException("SnmpV3AdaptorServer not created! ");
        }
        if (!server.isActive()) {
            LOG.info("SnmpV3AdaptorServer not started "+server.getPort());
            throw new RuntimeException("SnmpV3AdaptorServer not started! ");
        }
        LOG.info("Server started at: "+server.getHost()+":"+server.getPort());
        try {
            LOG.info("Sending trap to "+remoteHost+":"+remotePort);
            final SnmpPeer peer = new SnmpPeer(remoteHost,remotePort);
            final SnmpParameters params = new SnmpParameters();
            params.setRdCommunity("public");
            params.setInformCommunity("public");
            params.setWrCommunity("public");
            peer.setParams(params);
            if (trapOid==null) trapOid = "sun.0.1";
            server.snmpV2Trap(peer,new SnmpOid(trapOid),new SnmpVarBindList(),
                              new SnmpTimeticks(server.getSysUpTime()));
            LOG.info("Trap sent");
        } catch (Exception x) {
            throw new RuntimeException("Failed to send trap: "+x,x);
        }        
        return "trap sent to "+remoteHost+":"+remotePort;
    }
                

Fixing Imports

Now you should be seeing lots of lines underlined in red in the code you've just pasted. This is because we need to add the appropriate Java DMK imports. But before we can do that we need to tell NetBeans that our little TrapEmitter project is using Java DMK. Just select the TrapEmitter project, right click to open the popup menu, and choose 'Properties'.
In the project's properties window select 'Libraries' then click on 'Add Jar/Folder' and navigate to select the jdmkrt.jar. Once the jar is added, make sure to unselect the 'Package' checkbox displayed next to it. Since Java DMK is already in our AppServer classpath, we don't want to package it again into our war. Then you can close the project's properties window.

When this is done, use NetBeans 'Fix Import' action to generate all the necessary import clauses in the TrapEmitterBean.java file. Now all the underlined syntax errors that were previously detected by the editor should have disappeared.

What remains to do is to deploy our webservice, invoke it, and check that we can receive traps.

Deploying the WebService

Before deploying the WebService, make sure the Sun AppServer is started. If it's already started, you may want to restart it once: we modified its Classpath earlier in this lab, and classpath modification are only taken into account after a restart. If it's not started, well just start it.

You can do all of this from NetBeans' Runtime tab.

Wait until the server has started, then go back to the project's tab, select the TrapEmitter project, right-click to get the popup, and choose 'Deploy Project'. When the project is deployed, go and have a look to the Sun AppServer output - you should be seeing a trace like this:

The URL displayed EJB Web Service Endpoint [TrapEmitter] listening at address [http://curcuma:8104/webservice/TrapEmitter] is the URL at which you will be able to access your WebService. We're going to use that right now.

Creating a WebService client

First, create a new Web->Web Application project called 'TrapEmitterClient'. Select the newly created project, right click to get the popup, and choose to create a New->File/Folder->Web Services->Web Service Client.
In the windows that pops up, provide the TrapEmitter's WSDL URL. This is the URL that was displayed in the AppServer log when we deployed the TrapEmitter module, with ?WSDL appended at the end.
Click on "Retrieve WSDL", choose a package name, choose to let the IDE generate the client static stubs and then click on 'Finish'.

Now you should be seeing a 'TrapEmitter' Web Service Reference under your TrapEmitterClient application node in NetBeans' project tree:

Starting the SnmpV3AdaptorServer

To start the SnmpV3AdaptorServer, simply invoke the startServer method by double clicking on the Web Service Client 'startServer' node. In the window that pops up, choose a random port number for the method parameter value (well something with 4 digits, like 9654) and click on "Submit".
If the method succeeds it should display something like:

                com.sun.management.comm.SnmpV3AdaptorServer@940710: curcuma:9654

If it fails, then here are some hints:

  • If you can see 'ClassNotFoundException' appearing somewhere:
    you have probably misspecified the jdmkrt.jar in the AppServer classpath.
    Check all paths and spelling
  • If you can see 'SecurityException' appearing somewhere, or if you see something like this:
[#|2006-05-04T09:56:47.065+0200|WARNING|sun-appserver-pe8.1_02|com.sun.jdmk.misc|_ThreadID=14;|Couldn't find JDMK install dir|#]
                

    in the appserver log: you have probably misspecified the permissions in the server.policy file, or you have included jdmkrt.jar in your TrapEmitter.war.

    Another common reason for failure is if the port number you have chosen was already taken, or if you choose a port number that requires super-user priviledges, like e.g. 161.

Now that we have started the SnmpV3AdaptorServer, let's see if we can send a trap.

Looking for an Easy Manager?

In the Java DMK install, under SUNWjdmk/5.1/contributions - you will find an easymanager directory. Copy it to somewhere where you have write permissions.

From NetBeans IDE, choose to create a New Java Project With Existing Sources. Choose to name your project 'easymanager' and select the easymanager directory you've just created. Click on 'Next' and select the 'src' subdirectory as source folder. Click on 'Finish'.

Now edit the easymanager project's properties and add jdmkrt.jar to its library, exactcly as we did for the TrapEmitter EJB module - except that this time you won't have any 'Package' checkbox to unselect.

Now from NetBeans IDE, choose 'Run Project' for the easymanger project. You will be prompted to select the main class - there's only one choice so just accept it.

You sould now be staring fixedly at this trace:

easymanager initialized. SNMP Agent is [localhost:8085]
Start making your request:(h for help window)

If you're curious, enter 'h' and strike on return in NetBeans input line feed. Whether you're curious or not - now simply type 'trap' and strike return in NetBeans input line feed. A small window should popup:

This small window is the window where the easymanger will display trap it receives. The title of the window should display the hostname and/or IP of your machine. Just remember that name or IP, because this is where we will be sending our trap.

Sending a trap from our Web Application

Now let's go back to our Web Service Client (TrapEmitterClient) and let's double click on the sendTrap operation node. These are the parameters we must supply:

  1. remoteHost: the hostname or IP of your machine (or simply 'localhost')
  2. remotePort: '8086' - the port that was displayed in easymanager ]trace + 1
  3. trapOID: try this '1.2.3.4.5.6' - that's just a dummy OID

Then click on 'Submit'. This is what you should be seing in your easymanager trap window:

Isn't that a wonderful world?


Cheers,
Comments:

A post scriptum: I have shown how to start and stop the SnmpAdaptorServer, but you do not actually need to call SnmpAdaptorServer.start() in order to send traps. You can call SnmpAdaptorServer.snmpTrapV2() even if the SnmpAdaptorServer is not started, and it will work.

Posted by dfuchs on May 31, 2006 at 10:38 AM CEST #

hi, I would really like to know how does this function server.snmpV2Trap(..); encode the SNMPV2 Trap into a valid packet? I would like to send an SNMP Trap from my C# application. Thanks.

Posted by Cassie on July 28, 2006 at 03:37 AM CEST #

Hi Cassie,

SNMP uses BER to encode the data it sends over the wire. BER encoding of SNMP PDUs is not trivial, and I wouldn't recommend to implement it from scratch.

The first step when deciding to implement an SNMP agent, or an SNMP trap emitter, or an SNMP trap receiver, is to look for a good SNMP toolkit/library in your language of choice.

You could google for it (or resp. use your preferred internet search engine) - or have a look at www.SNMPLink.org which has a good list of SNMP resources.

You could also change your mind and write your application in Java ;-))

Hope this helps,

-- daniel

Posted by daniel on July 31, 2006 at 10:40 AM CEST #

Hi dfuchs, First of all, thanks! Next, I have created an MBean, I get my MBean Server from JBoss. I need your help here. I am trying to send an SNMP Trap via JBoss but am not able to :(. Do you suggest any simple guide which can tell me how do I send an SNMP Trap using jboss. I am interested in Configuration wrt JBoss configuration XML files and even a sample MBean with it. Thanks!

Posted by Ameya on November 28, 2006 at 09:43 AM CET #

Daniel,

Thanks for posting all this...It's very helpful!

As a newbie java programmer, I may be ignorant of what magic NetBeans does, since I'm using WebSphere, but your Fixing Imports section above indicates finding the jar files, but not the specific imports required in the source. Here they are, for other newbies who might similarly stub their toes...

import com.sun.management.comm.\*;
import com.sun.management.snmp.\*;
import com.sun.management.snmp.manager.\*;
import org.apache.log4j.\*;

Posted by anthonyr on July 12, 2009 at 10:31 PM CEST #

Well, it turns out that the arguments in the call to
server.snmpV2Trap(peer,
new SnmpOid(trapOid),
new SnmpVarBindList(),
new SnmpTimeticks(server.getSysUpTime()) );
all exist in two different packages in jdmkrt.jar, and the one you need is
com.sun.management.snmp.something rather that com.sun.jdmk.something.

Posted by Jim Rome on November 11, 2010 at 10:08 AM CET #

NetBeans 6.9.1 does not seem to generate an enterprise java bean if you select New/EJB Module.
The class signature is:
@WebService()
@Stateless()
public class TrapEmitter {

and when you get to the deploy step, it fails to deploy.
init:
deps-jar:
compile:
library-inclusion-in-archive:
Copying 1 file to /Users/jar/nbprojects/TrapEmitter/build/classes
dist-directory-deploy:
pre-run-deploy:
In-place deployment at /Users/jar/nbprojects/TrapEmitter/build/classes
deploy?path=/Users/jar/nbprojects/TrapEmitter/build/classes&name=TrapEmitter&force=true failed on GlassFish Server 3
/Users/jar/nbprojects/TrapEmitter/nbproject/build-impl.xml:569: The module has not been deployed.

Posted by Jim Rome on November 12, 2010 at 08:09 AM CET #

This does not work with the latest J2EE. Apparently you cannot have a class variable in a bean. So how do you update this tutorial for today's tools?

Posted by Jim Rome on November 16, 2010 at 10:57 AM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Daniel Fuchs blogs on Scene Builder, JMX, SNMP, Java, etc...

The views expressed on this blog are those of the author and do not necessarily reflect the views of Oracle.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today