2009-09-20

How to suspend / resume WLI 8.1 EventGenerators programmatically ?

 

You sometimes may have to programmatically pause your EventGenerator (EG) consumption.

And this, for various reasons, such as pausing all processes while one specific is running, or coding your own administration application.

BEA | Oracle doesn't come with a simple way of doing so. And the reason is obvious : theoretically, you don't have to manipulate those objects,

through another way as the WLI console.

However, this post will help you to do so.

 

First way : JMX

 

Since JMX wasn't officially finished while WLI 8.1 was released, BEA chose to implement its own version.

I quote : "Prior to 9.0, WebLogic Server used its own JMX implementation based on the JMX 1.0 specification."

As a result, it's not fun to juggle between the official JMX and the BEA implementation.

 

Second way : Using the official but not-normally-callable API

 

As you may have guessed, we are going to use the WLI console functions since those suspend & resume functions are already used there.

If you take a look at your WLS 8.1 installation directory, you will find the WLI console WAR in the directory WLS_HOME \ weblogic81 \ integration \ lib \ console.

If you open this WAR, you will see some interesting classes, such as EventGeneratorUtils and so on.

But these are only classes, available in the WEB-INF directory of the WAR, thus no easy way to know the dependencies between them.

The best solution would be to have a JAR.

Well, if you have created a WLI domain, you will find exactly what you need !

Let's assume we have an administration server whose name is "AdminServer" (pretty good name, huh ? :) )

Then check in the extract directory, the directory corresponding to the WLI Console :

DOMAIN_HOME \ AdminServer \ .wlnotdelete \ extract \ AdminServer_WLI Console_wliconsole \ jarfiles

And you should see something like that :

 

image

 

Two directories in which you have a directory called "jarfiles". There's an interesting file "_wl_cls_gen.jar".

It contains all the classes used for the WLI Console, and then all the classes used for managing EG lifecycles.

Just add this Jar & Log4J in your IDE classpath project and you're good to go.

 

To go straightforward, here is the class I wrote :

 

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.MBeanException;

import org.apache.log4j.Logger;

import com.bea.wli.oam.eventgenerators.EventGeneratorUtils;
import com.bea.wli.oam.eventgenerators.EventGeneratorWrapper;
import com.bea.wli.oam.eventgenerators.file.FileEventGeneratorHelper;
import com.bea.wli.oam.eventgenerators.jms.JmsEventGeneratorHelper;
import com.bea.wli.oam.eventgenerators.timer.TimerEventGeneratorHelper;

/**
* @author mbutton
*
*/
public class EGManager {

    private transient Logger logger = Logger.getLogger(getClass());

    public static final String TIMER_EG = "TIMER";

    public static final String JMS_EG = "JMS";

    public static final String FILE_EG = "FILE";

    private static Map timerEG;

    private static Map jmsEG;

    private static Map fileEG;

    /**
     * Constructor that initialises the maps representing the declared EGs.
     * @throws EGManagerException
     */
    public EGManager() throws EGManagerException {
        try {
            indexTimerEventGenerators();
            indexJMSEventGenerators();
            indexFileEventGenerators();
        } catch (MBeanException e) {
            logger.error("Problème lors de l'indexation des EventGenerators", e);
            throw new EGManagerException("Problème lors de l'initialisation : les EventGenerators n'ont pu être récupérés.");
        }
    }

    /**
     * (non-javadoc) Indexes the TIMER EG family
     *
     * @throws MBeanException
     */
    private void indexTimerEventGenerators() throws MBeanException {
        List timerEGs = TimerEventGeneratorHelper.getAllTimerEventGenerators();
        timerEG = indexEventGenerators(timerEGs);
    }

    /**
     * (non-javadoc) Indexes the FILE EG family
     *
     * @throws MBeanException
     */
    private void indexFileEventGenerators() throws MBeanException {
        List fileEGs = FileEventGeneratorHelper.getAllFileEventGenerators();
        fileEG = indexEventGenerators(fileEGs);
    }

    /**
     * (non-javadoc) Indexes the JMS EG family
     *
     * @throws MBeanException
     */
    private void indexJMSEventGenerators() throws MBeanException {
        List jmsEGs = JmsEventGeneratorHelper.getAllJmsEventGenerators();
        jmsEG = indexEventGenerators(jmsEGs);
    }

    /**
     * (non-javadoc) Indexes a List with the EG name as a key and the
     * EventGeneratorWrapper as the object.
     *
     * @param eventGenerators
     *            the EG list to be indexed
     * @return a Map containing the indexed information.
     */
    private Map indexEventGenerators(List eventGenerators) {
        Map indexedEG = new HashMap();
        int size = (eventGenerators != null) ? eventGenerators.size() : 0;
        EventGeneratorWrapper currentEGWrapper = null;
        for (int i = 0; i < size; i++) {
            currentEGWrapper = (EventGeneratorWrapper) eventGenerators.get(i);
            indexedEG.put(currentEGWrapper.getName(), currentEGWrapper);
        }
        return indexedEG;
    }

    /**
     * Method used to suspend a running EventGenerator
     *
     * @param eventGeneratorType
     *            the type (File, JMS, ...) of the EG
     * @param eventGeneratorName
     *            the EG name as it appears through the WLI console
     * @throws EGManagerException
     */
    public void suspendEventGenerator(String eventGeneratorType, String eventGeneratorName) throws EGManagerException {
        checkEventGeneratorType(eventGeneratorType);

        EventGeneratorWrapper eg = getEventGeneratorWrapper(eventGeneratorType, eventGeneratorName);
        if (eg != null) {
            try {
                EventGeneratorUtils.suspendGenerator(eg);
            } catch (Exception e) {
                logger.error("Impossible d'arrêter l'EventGenerator " + eventGeneratorName, e);
                throw new EGManagerException("Impossible d'arrêter l'EventGenerator " + eventGeneratorName);
            }
        } else {
            throw new EGManagerException("L'event Generator de type " + eventGeneratorType + " et de nom " + eventGeneratorName + " n'a pas été trouvé.");
        }
    }

    /**
     * Method used to resume a suspended EventGenerator
     *
     * @param eventGeneratorType
     *            the type (File, JMS, ...) of the EG
     * @param eventGeneratorName
     *            the EG name as it appears through the WLI console
     * @throws EGManagerException
     */
    public void resumeEventGenerator(String eventGeneratorType, String eventGeneratorName) throws EGManagerException {
        checkEventGeneratorType(eventGeneratorType);

        EventGeneratorWrapper eg = getEventGeneratorWrapper(eventGeneratorType, eventGeneratorName);
        if (eg != null) {
            try {
                EventGeneratorUtils.resumeGenerator(eg);
            } catch (Exception e) {
                logger.error("Impossible de relancer l'EventGenerator " + eventGeneratorName, e);
                throw new EGManagerException("Impossible de relancer l'EventGenerator " + eventGeneratorName);
            }
        } else {
            throw new EGManagerException("L'event Generator de type " + eventGeneratorType + " et de nom " + eventGeneratorName + " n'a pas été trouvé.");
        }

    }

    /**
     * (non-javadoc) From the indexed EG list, it returns the
     * EventGeneratorWrapper matching the EventGenerator looked for.
     *
     * @param eventGeneratorType
     *            the type (File, JMS, ...) of the EG
     * @param eventGeneratorName
     *            the EG name as it appears through the WLI console
     * @return the matching EventGeneratorWrapper
     */
    private EventGeneratorWrapper getEventGeneratorWrapper(String eventGeneratorType, String eventGeneratorName) {
        EventGeneratorWrapper result = null;
        if (TIMER_EG.equals(eventGeneratorType)) {
            result = (EventGeneratorWrapper) timerEG.get(eventGeneratorName);
        } else if (JMS_EG.equals(eventGeneratorType)) {
            result = (EventGeneratorWrapper) jmsEG.get(eventGeneratorName);
        } else if (FILE_EG.equals(eventGeneratorType)) {
            result = (EventGeneratorWrapper) fileEG.get(eventGeneratorName);
        }
        return result;
    }

    /**
     * (non-javadoc) Method used to check that the given EventGenerator type is
     * correct.
     *
     * @param eventGeneratorType
     *            the type (File, JMS, ...) of the EG
     */
    private void checkEventGeneratorType(String eventGeneratorType) {
        if (eventGeneratorType == null
                || eventGeneratorType.equals("")
                || (!eventGeneratorType.equalsIgnoreCase(TIMER_EG) && !eventGeneratorType.equalsIgnoreCase(JMS_EG) && !eventGeneratorType
                        .equalsIgnoreCase(FILE_EG))) {
            throw new IllegalArgumentException("Le type de l'EventGenerator '" + eventGeneratorType + "' n'est pas correct.");
        }
    }

    /**
     * @author mbutton
     * Exception used to raise an error while manipulating EventGeneratorWrappers to the front layer.
     */
    public class EGManagerException extends Exception {

        private static final long serialVersionUID = 1L;

        /**
         * Constructor
         * @param message
         */
        public EGManagerException(String message) {
            super(message);
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        EGManager egm;
        try {
            egm = new EGManager();
            egm.suspendEventGenerator(EGManager.TIMER_EG, "TimerSampleEG");
        } catch (EGManagerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

 

There you go !

To sum up, you have two methods on the EGManager : suspendEventGenerator & resumeEventGenerator.

Both take a EventGenerator type as the first parameter and the name of the EventGenerator as a second argument.

This class was designed only for Timer EG, JMS EG & File EG. But you may add other types and translate the French messages :)

 

But there is one limitation to that implementation. Actually, those objects are sensed to be called during a proper session via the WLI Console.

It means you have to be logged on.

In my case, we were creating another console, then I just had to secure my WebApp and everything went ok after that.

To do so, let's check my other post "Reminder on how to quickly secure a web app on WebLogic Server".

 

Update : I also had to call these methods from WLI processes. The solution I chose was to add the following annotation to each process that had to manipulate EG.

 

* @common:security run-as="weblogic"

 

Of course, "weblogic" has to be a valid principal.

For instance, in a real-world example :

 

/**
* @jpd:process process::
* <process name="PlayWithEventGenerators">
*   <clientRequest name="Client Request" method="clientRequest"/>
*   <perform name="Do The Business" method="perform"/>
* </process>::
* @common:security run-as="weblogic"
*/
public class PlayWithEventGenerators implements com.bea.jpd.ProcessDefinition
{ [...] }

 

 

Reminder on how to quickly secure a web application on WebLogic Server

 

This post is not about a highly technical subject, but I guess it's nice to have it explained in a few words, for beginners,

and have the real stuff at a glance for experimented users who just want a reminder.

 

Actually, note the security has nothing to do with your code !

All this aspect relies on configuration + the login page and the error page (JSPs).

Here's what you have to do.

 

Assume you have a webapp called "MyWebApp".

In the WEB-INF directory, you'll have a web.xml and, if you want to deploy it on WebLogic server, another XML file : weblogic.xml.

 

image

 

Note : Here's presented the authentication through a html form.

In blue, the important stuff.

 

Web.xml :

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
    <display-name>MyWebApp</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>All</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>webuser</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/login_failed.jsp</form-error-page>
        </form-login-config>
    </login-config>

    <security-role>
        <role-name>webuser</role-name>
    </security-role>
</web-app>

 

Weblogic.xml :

 

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/920/weblogic-web-app.xsd">
    <weblogic-version>10.0</weblogic-version>
    <context-root>TestInterface</context-root>
    <security-role-assignment>
        <role-name>webuser</role-name>
        <principal-name>Administrators</principal-name>

    </security-role-assignment>
    <jsp-descriptor>
        <page-check-seconds>-1</page-check-seconds>
    </jsp-descriptor>
    <container-descriptor>
        <session-monitoring-enabled>true</session-monitoring-enabled>
    </container-descriptor>
</weblogic-web-app>

 

Login.jsp :

 

<html>
  <head>
    <title>Security WebApp login page</title>
  </head>
  <body>
  <blockquote>
  <h2>Please enter your username and password:</h2>
  <p>
  <form method="POST" action="j_security_check">
  <table border=1>
    <tr>
      <td>Username:</td>
      <td><input type="text" name="j_username"></td>
    </tr>
    <tr>
      <td>Password:</td>
      <td><input type="password" name="j_password"></td>
    </tr>
    <tr>
      <td colspan=2 align=right><input type=submit value="Submit"></td>
    </tr>
  </table>
  </form>
  </blockquote>
  </body>
</html>

 

login_failed.jsp :

 

<%@ page
    language="java"
    contentType="text/html;charset=UTF-8"
%><%
response.setStatus(200); // To prevent IE from catching the response with its own error page
%>
<html>
    <head>
        <title>Security WebApp login error page</title>
    </head>
    <body bgcolor="#cccccc">
        <blockquote>
            <h2>Vous n'êtes pas autorisé à accéder à l'application.</h2>
        </blockquote>
    </body>
</html>

 

If you want to know more, take a look at the official documentation.