LISTING 1 CHANGES MADE TO TESTLOGPORTLET.JAVA TO ENABLE PORTLETLOG

//  the WebSphere Portlet logger
//  note that to enable this you must use :
//  org.apache.jetspeed.portlet.PortletLog=all=enabled
private org.apache.jetspeed.portlet.PortletLog logger = null;

/**
  *  Class name for tracing
  */

private String sClassName = ((Object) this).getClass().getName();

/**
 * @see org.apache.jetspeed.portlet.Portlet#init(PortletConfig)
 */
[A] public void init(PortletConfig portletConfig) throws
    UnavailableException {
		super.init(portletConfig);
		// set up the logger.
[D]		logger = portletConfig.getContext().getLog();
}

/**
 * @see org.apache.jetspeed.portlet.PortletAdapter#doView
    (PortletRequest,
 *      PortletResponse)
 */
[B] public void doView(PortletRequest request, PortletResponse
    response)
			throws PortletException, IOException {

	try {
		if (logger.isInfoEnabled()) {
[E]			logger.info(sClassName + " Entry doView()");
		}

		// Check if portlet session exists
		TestLogPortletSessionBean sessionBean = 
        getSessionBean(request);
		if (sessionBean == null) {
			response.getWriter().println("<b>NO PORTLET SESSION
           YET</b>");
			return;
		}
		// Invoke the JSP to render
		getPortletConfig().getContext().include(
				VIEW_JSP + getJspExtension(request), request,
				response);
	} catch (Throwable e) {
		if (e instanceof PortletException) {
[F]			logger.error(sClassName + " doView() Portal Exception : "
			+ ((PortletException) e).getMessage());
			throw (PortletException) e;
		}
		if (e instanceof IOException) {
[F]				logger.error(sClassName + " doView()I/O Exception :
                " + e.toString());
			throw (IOException) e;
		}
[F]		logger.error(sClassName + " doView() Exception :
           " + e.toString());
	}

	if (logger.isInfoEnabled()) {
[E]		logger.info(sClassName + " Exit doView()");
	}

}

/**
 * @see org.apache.jetspeed.portlet.event.ActionListener#action
    Performed(ActionEvent)
 */
[C] public void actionPerformed(ActionEvent event) throws
     PortletException {
	if (logger.isInfoEnabled()) {
[E]			logger.info(sClassName + " actionPerformed() called");
	}
	try {
		// ActionEvent handler
		String actionString = event.getActionString();
		PortletRequest request = event.getRequest();
		// Add action string handler here
		TestLogPortletSessionBean sessionBean = 
       getSessionBean(request);

		if (FORM_ACTION.equals(actionString)) {
			// Set form text in the session bean
			sessionBean.setFormText(request.getParameter(TEXT));
		}
	} catch (Throwable e) {
		if (e instanceof PortletException) {
[F]			logger.error(sClassName + " actionPerformed() 
              Portal Exception : "
					+ ((PortletException) e).getMessage());
			throw (PortletException) e;
		}

[F]		logger.error(sClassName + " actionPerformed() Exception : 
" + e.toString());

	}
}

LISTING 2 CHANGES TO THE DOVIEW() AND 
ACTIONPERFORMED() METHODS IN TESTLOGWPSPORTLET.JAVA

/**
 * @see org.apache.jetspeed.portlet.PortletAdapter#doView
     (PortletRequest,
 *      PortletResponse)
 */
[G] public void doView(PortletRequest request, PortletResponse
     response)
			throws PortletException, IOException {
		try {
			// entry log is limited to debug mode
			// the other choices would be TRACE_LOW, TRACE_MEDIUM, TRACE_HIGH
			if (LoggingUtils.isDebugEnabled(logger)) {
[I]			LoggingUtils.entry(logger, "doView()");

			}

			// Check if portlet session exists
			TestLogWPSPortletSessionBean sessionBean =
           getSessionBean(request);
			if (sessionBean == null) {
				response.getWriter().println("<b>NO PORTLET SESSION
              YET</b>");
				return;
			}

			// Invoke the JSP to render
			getPortletConfig().getContext().include(
					VIEW_JSP + getJspExtension(request), request, response);
		} catch (Throwable e) {
			if (e instanceof PortletException) {
				// log error is performed when the trace level is set to
				// high or all
[L]				LoggingUtils.error(logger,
					 "error in doView() throw portlet exc", e);
					  throw (PortletException) e;
			}
			if (e instanceof IOException) {
				// log error is performed when the trace level is 
              set to
				// high or all
[L]				LoggingUtils.error(logger, 
				"error in doView() throw i/o exc", e);
				throw (IOException) e;
			}
			// log error is performed when the trace level is set to
			// high or all
[L]			LoggingUtils.error(logger, "error in doView()", e);
		}
		// 
		// exit log is limited to low mode
		// the other choices would be TRACE_LOW, TRACE_MEDIUM, 
       TRACE_HIGH
		if (LoggingUtils.isDebugEnabled(logger)) {
[J]			LoggingUtils.exit(logger, "doView()");
		}

}

/**
 * @see org.apache.jetspeed..event.ActionListener#actionPerformed
    (ActionEvent)
 */
[H] public void actionPerformed(ActionEvent event) throws 
     PortletException {
		// demonstrates the use of info() method.
		// this is logged only for medium mode
		if (LoggingUtils portlet.isInfoEnabled(logger)) {
[K]			LoggingUtils.info(logger, "info in actionPerformed()");
		}
		try {
			// ActionEvent handler
			String actionString = event.getActionString();
			PortletRequest request = event.getRequest();
			// Add action string handler here
			TestLogWPSPortletSessionBean sessionBean =
           getSessionBean(request);

			if (FORM_ACTION.equals(actionString)) {
				// Set form text in the session bean
				sessionBean.setFormText(request.getParameter(TEXT));
			}
		} catch (Throwable e) {
			if (e instanceof PortletException) {
				// log error is performed when the trace level is 
              set to
				// high or all
[L]				LoggingUtils.error(logger,
					"error in actionPerformed() throw portlet exc", e);
					 throw (PortletException) e;
			}

			// log error is performed when the trace level is set to
			// high or all
[L]			LoggingUtils.error(logger, "error in 
              actionPerformed()", e);
		}
}


LISTING 3 SOURCE FOR LOGGINGUTILS.JAVA

package test_log_wps;

import com.ibm.wps.logging.Logger;

/**
 * This class has some generic logging utilities that you can use
 * in your portlet.
 * It is based on the PortletLog class found in WebSphere Portal Server except 
 * that it requires that you pass a reference to the Logger. This allows the logging
 * in the trace file to be associated with your class name, not the PortletLog.
 * Remember that the 4 layers of tracing are:
 * - low (all logging is enabled)
 * - medium
 * - high
 * - disabled (no logging)
 * The debug(), entry() and exit() methods are invoked for low mode
 * The info() and warn() methods are invoked for medium or low mode
 * The error() methods are invoked for high, medium or low mode 
 * 
 */
public abstract class LoggingUtils {

	/**
	 * Add at the beginning of your method. Enabled when trace is set to low or all 
         * level.
	 * @param logger
	 * @param text
	 */
[I]	public static void entry(com.ibm.wps.logging.Logger logger, String text) {
		if (isDebugEnabled(logger))
			logger.entry(Logger.TRACE_LOW, "entry", text);
	}
	/**
	* Add at the end of your method. Enabled when trace is set to low or all level.
	* @param logger
	* @param text
	*/
[J]	public static void exit(com.ibm.wps.logging.Logger logger, String text) {
		if (isDebugEnabled(logger))
			logger.exit(Logger.TRACE_LOW, "exit", text);
	}

	/**
	 * Is debug enabled? Enabled when trace is set to low or all level.
	 * @param logger
	 * @return
	 */
	public static boolean isDebugEnabled(com.ibm.wps.logging.Logger logger) {
		return logger.isLogging(Logger.TRACE_LOW) || 
		          logger.isLogging(Logger.TRACE_MEDIUM) || 
		          logger.isLogging(Logger.TRACE_HIGH);
	}

	/**
	 * Display a debug message.  Enabled when trace is set to low or all level.
	 * @param logger
	 * @param text
	 */
	public static void debug(com.ibm.wps.logging.Logger logger, String text) {
		if (isDebugEnabled(logger))
			logger.text(Logger.TRACE_LOW, "debug", text);
	}

	/**
	 * Display an infomational message.  Enabled when trace is set to medium or all 
     * level.
	 * @param logger
	 * @return
	 */
	public static boolean isInfoEnabled(com.ibm.wps.logging.Logger logger) {
		return logger.isLogging(Logger.TRACE_MEDIUM) || logger.isLogging(Logger.TRACE_LOW);
	}

	/**
	 * Display an information message.  Enabled when trace is set to medium or all
         * level.
	 * @param logger
	 * @param text
	 */
[K]	public static void info(com.ibm.wps.logging.Logger logger, String text) {
		if (isInfoEnabled(logger))
			logger.text(Logger.INFO, "info", text);
	}

	/**
	 * Should you display a warning message? Enabled when trace is set to medium or 
         * all level.
	 * @param logger
	 * @return
	 */
	public static boolean isWarnEnabled(com.ibm.wps.logging.Logger logger) {
		return logger.isLogging(Logger.TRACE_MEDIUM) || logger.isLogging(Logger.TRACE_LOW);
	}

	/**
	 * Display a warning message. Enabled when trace is set to medium level.
	 * @param logger
	 * @param text
	 */
	public static void warn(com.ibm.wps.logging.Logger logger, String text) {
		if (isWarnEnabled(logger))
			logger.text(Logger.WARN, "warn", text);
	}

	/**
	 * Should you display an error message?  Enabled when trace is set to high or
        * level.
	 * @param logger
	 * @return
	 */
	public static boolean isErrorEnabled(com.ibm.wps.logging.Logger logger) {
		return logger.isLogging(Logger.TRACE_HIGH);
	}

	/**
	 * Display an error message.  Enabled when trace is set to high or all level.
	 * @param logger
	 * @param text
	 */
[L]	public static void error(com.ibm.wps.logging.Logger logger, String text) {
		if (isErrorEnabled(logger))
			logger.text(Logger.ERROR, "error", text);
	}

	/**
	 * Display an error message.  Enabled when trace is set to high or all level.
	 * @param logger
	 * @param text
	 * @param cause - exception
	 */
[L]	public static void error(
		com.ibm.wps.logging.Logger logger,
		String text,
		Throwable cause) {
		if (isErrorEnabled(logger))
			logger.text(Logger.ERROR, "error", text, cause);
	}

}	

LISTING 4 CHANGES TO THE DOVIEW() AND ACTIONPERFORMED() METHODS IN TESTLOG4JPORTLET

/**
 * @see org.apache.jetspeed.portlet.PortletAdapter#doView(PortletRequest,
 *      PortletResponse)
 */
[N] public void doView(PortletRequest request, PortletResponse response)
			throws PortletException, IOException {

		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Entry doView()");
			}

			// Check if portlet session exists
			TestLog4JPortletSessionBean sessionBean = getSessionBean(request);
			if (sessionBean == null) {
				response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
				return;
			}

			// Invoke the JSP to render
			getPortletConfig().getContext().include(
					VIEW_JSP + getJspExtension(request), request, response);
		} catch (Throwable e) {
			if (e instanceof PortletException) {
				logger.error("doView() Portal Exception : "
						+ ((PortletException) e).getMessage());
				throw (PortletException) e;
			}
			if (e instanceof IOException) {

				logger.error("doView() I/O Exception : " + e.toString());
				throw (IOException) e;
			}
			logger.error("doView()Exception : " + e.toString());
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Exit doView()");
		}

}

/**
 * @see org.apache.jetspeed.portlet.event.ActionListener#actionPerformed(ActionEvent)
 */
[O]public void actionPerformed(ActionEvent event) throws PortletException {
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Entry actionPerformed()");
			}
			// ActionEvent handler
			String actionString = event.getActionString();
			PortletRequest request = event.getRequest();
			// Add action string handler here
			TestLog4JPortletSessionBean sessionBean = getSessionBean(request);

			if (FORM_ACTION.equals(actionString)) {
				// Set form text in the session bean
				sessionBean.setFormText(request.getParameter(TEXT));
			}
		} catch (Throwable e) {
			if (e instanceof PortletException) {
				logger.error("actionPerformed() Portal Exception : "
						+ ((PortletException) e).getMessage());
				throw (PortletException) e;
			}


			logger.error("actionPerformed()Exception : " + e.toString());
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Exit actionPerformed()");

LISTING 5 LOG4J.PROPERTIES FILE


#
# Default log level is set to DEBUG. 
# Levels are ERROR, INFO, DEBUG, WARN, FATAL, ALL or OFF
#
log4j.rootLogger=DEBUG, ROOT
[Q] log4j.appender.ROOT=org.apache.log4j.RollingFileAppender

#
# location of the log file
#
[P] log4j.appender.ROOT.File=mytestportlet.log

#
# Maximum file size
#
log4j.appender.ROOT.MaxFileSize=1000KB

#
# This defines the no of log files to keep. Since this is a rolling file system, after the
 number of
# files reaches this number, the oldest file is rewritten
# 
log4j.appender.ROOT.MaxBackupIndex=5

#
# Setup your own format
#
log4j.appender.ROOT.layout=org.apache.log4j.PatternLayout
#
# Format almost same as WebSphere's common log format.
#
log4j.appender.ROOT.layout.ConversionPattern=[%d] %t %c %-5p - %m%n
       }
}

LISTING 6 TESTLOG4JSTRUTS.JAVA AND EXTENSION OF WPSSTRUTSPORTLET 
TO SUPPORT LOG4J LOGGING
package com.ibm.strutsextend; import org.apache.jetspeed.portlet.PortletSettings; import org.apache.jetspeed.portlet.UnavailableException; import org.apache.jetspeed.portlet.event.PortletSettingsAttributeEvent; import org.apache.jetspeed.portlet.event.PortletSettingsAttributesListener; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import com.ibm.wps.portlets.struts.WpsStrutsPortlet; /** * This is a skeleton Struts portlet that allows you to use log4j and to * dynamically change the logging level. * */ [R]public class TestLog4JStruts extends WpsStrutsPortlet implements PortletSettingsAttributesListener { /** * Declare the logger */ private final static Logger logger = Logger .getLogger(com.ibm.strutsextend.TestLog4JStruts.class); /** * The portlet settings attribute name */ private static final String LOGGING = "Logging"; /** * The log4j properties file. If this file is absence then the file * log4j.properties will be searched from the search path used to load * classes. */ private static final String LOG_PROP_FILE = "LogPropFile"; /** * The allowed values for the Logging portlet settings. The absence of this * attribute name will set the logging to OFF. */ private static final String ERROR_ATTR = "error"; private static final String WARN_ATTR = "warn"; private static final String INFO_ATTR = "info"; private static final String DEBUG_ATTR = "debug"; private static final String FATAL_ATTR = "fatal"; private static final String ALL_ATTR = "all"; private static final String OFF_ATTR = "off"; /** * The default log file name */ private final static String DEFAULT_LOGFILE = "log4j.properties"; /** * Set up the initial logging level if the portlet setting LOGGING is * available. */ public void initConcrete(PortletSettings settings) throws UnavailableException { try { if (logger.isDebugEnabled()) { logger.debug("initConcrete()"); } super.initConcrete(settings); // set the logging setLevel(settings.getAttribute(LOGGING)); // load the specified properties file if it is available. loadPropertiesFile(settings.getAttribute(LOG_PROP_FILE)); } catch (Throwable e) { logger.error("initConcrete() Exception : " + e.toString()); } } /** * Load the properties file named propFileName. * * @param propFileName - * The properties file */ private void loadPropertiesFile(String propFileName) { try { if ((null == propFileName) || (0 == propFileName.length())) { propFileName = DEFAULT_LOGFILE; if (logger.isDebugEnabled()) { logger.debug("No input properties file. Use default " + DEFAULT_LOGFILE); } } PropertyConfigurator.configureAndWatch(propFileName); if (logger.isDebugEnabled()) { logger.debug("New Property file : " + propFileName); } } catch (Throwable e) { logger.error("loadPropertiesFile() Exception : " + e.toString()); } } /** * Set the logging level in the Log4J * * @param logVal */ private void setLevel(String logVal) { try { if (logger.isDebugEnabled()) { logger.debug("Entry setLevel " + logVal); } // lower case the value for matching. if (null != logVal) { logVal = logVal.toLowerCase(); } if (DEBUG_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.DEBUG); } else if (INFO_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.INFO); } else if (WARN_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.WARN); } else if (ERROR_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.ERROR); } else if (FATAL_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.FATAL); } else if (ALL_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.ALL); } // default is OFF else //if (OFF_ATTR.equals(logVal)) { logger.setLevel(org.apache.log4j.Level.OFF); logVal = OFF_ATTR; } // testLog(); if (logger.isDebugEnabled()) { logger.debug("Exit setLevel " + logVal); } } catch (Throwable e) { logger.error("setLevel() Exception : " + e.toString()); } } /** * Test the logging levels after changing it. * */ private void testLog() { logger.error("Test Error message"); logger.info("Test Info message"); logger.warn("Test Warn message"); logger.debug("Test Debug message"); logger.fatal("Test Fatal message"); } /** * Portlet Setting attribute added. */ public void attributeAdded(PortletSettingsAttributeEvent arg0) { try { if (logger.isDebugEnabled()) { logger.debug("Entry attributeAdded Name " + arg0.getName() + " Val " + arg0.getValue()); } if (LOGGING.equals(arg0.getName())) { String newVal = getPortletSettings().getAttribute(LOGGING); logger.debug("Entry attributeReplaced New value " + newVal); setLevel(newVal); } } catch (Throwable e) { logger.error("attributeAdded() Exception : " + e.toString()); } if (logger.isDebugEnabled()) { logger.debug("Exit attributeAdded"); } } /** * Portlet Setting attribute removed */ public void attributeRemoved(PortletSettingsAttributeEvent arg0) { try { if (logger.isDebugEnabled()) { logger.debug("Entry attributeRemoved Name " + arg0.getName() + " Val " + arg0.getValue()); } if (LOGGING.equals(arg0.getName())) { String newVal = getPortletSettings().getAttribute(LOGGING); if (logger.isDebugEnabled()) { logger.debug("Entry attributeReplaced New value " + newVal); } setLevel(newVal); } } catch (Throwable e) { logger.error("attributeRemoved() Exception : " + e.toString()); } if (logger.isDebugEnabled()) { logger.debug("Exit attributeRemoved"); } } /** * Portlet Setting attribute replaced */ public void attributeReplaced(PortletSettingsAttributeEvent arg0) { try { if (logger.isDebugEnabled()) { logger.debug("Entry attributeReplaced Name " + arg0.getName() + " Current Val " + arg0.getValue()); } if (LOGGING.equalsIgnoreCase(arg0.getName())) { String newVal = getPortletSettings().getAttribute(LOGGING); if (logger.isDebugEnabled()) { logger.debug("Entry attributeReplaced New value " + newVal); } setLevel(newVal); } } catch (Throwable e) { logger.error("attributeReplaced() Exception : " + e.toString()); } if (logger.isDebugEnabled()) { logger.debug("Exit attributeReplaced"); } } } LISTING 7 CONFIG PARAMETERS FOR PORTLET.XML <concrete-portlet href="#test_log4j_struts.TestLog4JStrutsPortlet"> <portlet-name>Test Log4J Struts portlet</portlet-name> <default-locale>en</default-locale> <language locale="en"> <title>Test Log4J Struts portlet</title> <title-short /> <description /> <keywords>WPS, Struts</keywords> </language> <config-param> <param-name>Logging</param-name> <param-value>Debug</param-value> </config-param> <config-param> <param-name>LogPropFile</param-name> <param-value>log4j.properties</param-value> </config-param> </concrete-portlet> LISTING 8 LOG4J.PROPERTIES FILE FOR STRUTS LOGGING PORTLET # # Default log level is set to DEBUG. # Levels are ERROR, INFO, DEBUG, WARN, FATAL, ALL or OFF # log4j.rootLogger=DEBUG, ROOT log4j.appender.ROOT=org.apache.log4j.RollingFileAppender # # location of the log file # log4j.appender.ROOT.File=mytestportlet.log # # Maximum file size # log4j.appender.ROOT.MaxFileSize=1000KB # # This defines the no of log files to keep. Since this is a rolling file system, after the number of # files reaches this number, the oldest file is rewritten # log4j.appender.ROOT.MaxBackupIndex=5 # # Setup your own format # log4j.appender.ROOT.layout=org.apache.log4j.PatternLayout # # Format almost same as WebSphere's common log format. # log4j.appender.ROOT.layout.ConversionPattern=[%d] %t %c %-5p - %m%n

Additional Source Code - Zip file