FileDocCategorySizeDatePackage
JMSAppender.javaAPI DocApache log4j 1.2.1513224Sat Aug 25 00:09:40 BST 2007org.apache.log4j.net

JMSAppender

public class JMSAppender extends AppenderSkeleton
A simple appender that publishes events to a JMS Topic. The events are serialized and transmitted as JMS message type {@link ObjectMessage}.

JMS {@link Topic topics} and {@link TopicConnectionFactory topic connection factories} are administered objects that are retrieved using JNDI messaging which in turn requires the retreival of a JNDI {@link Context}.

There are two common methods for retrieving a JNDI {@link Context}. If a file resource named jndi.properties is available to the JNDI API, it will use the information found therein to retrieve an initial JNDI context. To obtain an initial context, your code will simply call:

InitialContext jndiContext = new InitialContext();

Calling the no-argument InitialContext() method will also work from within Enterprise Java Beans (EJBs) because it is part of the EJB contract for application servers to provide each bean an environment naming context (ENC).

In the second approach, several predetermined properties are set and these properties are passed to the InitialContext contructor to connect to the naming service provider. For example, to connect to JBoss naming service one would write:

Properties env = new Properties( );
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
env.put(Context.PROVIDER_URL, "jnp://hostname:1099");
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
InitialContext jndiContext = new InitialContext(env);
where hostname is the host where the JBoss applicaiton server is running.

To connect to the the naming service of Weblogic application server one would write:

Properties env = new Properties( );
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
InitialContext jndiContext = new InitialContext(env);

Other JMS providers will obviously require different values. The initial JNDI context can be obtained by calling the no-argument InitialContext() method in EJBs. Only clients running in a separate JVM need to be concerned about the jndi.properties file and calling {@link InitialContext#InitialContext()} or alternatively correctly setting the different properties before calling {@link InitialContext#InitialContext(java.util.Hashtable)} method.

author
Ceki Gülcü

Fields Summary
String
securityPrincipalName
String
securityCredentials
String
initialContextFactoryName
String
urlPkgPrefixes
String
providerURL
String
topicBindingName
String
tcfBindingName
String
userName
String
password
boolean
locationInfo
javax.jms.TopicConnection
topicConnection
javax.jms.TopicSession
topicSession
javax.jms.TopicPublisher
topicPublisher
Constructors Summary
public JMSAppender()

  
Methods Summary
public voidactivateOptions()
Options are activated and become effective only after calling this method.

    TopicConnectionFactory  topicConnectionFactory;

    try {
      Context jndi;

      LogLog.debug("Getting initial context.");
      if(initialContextFactoryName != null) {
	Properties env = new Properties( );
	env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
	if(providerURL != null) {
	  env.put(Context.PROVIDER_URL, providerURL);
	} else {
	  LogLog.warn("You have set InitialContextFactoryName option but not the "
		     +"ProviderURL. This is likely to cause problems.");
	}
	if(urlPkgPrefixes != null) {
	  env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
	}
	
	if(securityPrincipalName != null) {
	  env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
	  if(securityCredentials != null) {
	    env.put(Context.SECURITY_CREDENTIALS, securityCredentials);
	  } else {
	    LogLog.warn("You have set SecurityPrincipalName option but not the "
			+"SecurityCredentials. This is likely to cause problems.");
	  }
	}	
	jndi = new InitialContext(env);
      } else {
	jndi = new InitialContext();
      }

      LogLog.debug("Looking up ["+tcfBindingName+"]");
      topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, tcfBindingName);
      LogLog.debug("About to create TopicConnection.");
      if(userName != null) {
	topicConnection = topicConnectionFactory.createTopicConnection(userName, 
								       password); 
      } else {
	topicConnection = topicConnectionFactory.createTopicConnection();
      }

      LogLog.debug("Creating TopicSession, non-transactional, "
		   +"in AUTO_ACKNOWLEDGE mode.");
      topicSession = topicConnection.createTopicSession(false,
							Session.AUTO_ACKNOWLEDGE);

      LogLog.debug("Looking up topic name ["+topicBindingName+"].");
      Topic topic = (Topic) lookup(jndi, topicBindingName);

      LogLog.debug("Creating TopicPublisher.");
      topicPublisher = topicSession.createPublisher(topic);
      
      LogLog.debug("Starting TopicConnection.");
      topicConnection.start();

      jndi.close();
    } catch(Exception e) {
      errorHandler.error("Error while activating options for appender named ["+name+
			 "].", e, ErrorCode.GENERIC_FAILURE);
    }
  
public voidappend(org.apache.log4j.spi.LoggingEvent event)
This method called by {@link AppenderSkeleton#doAppend} method to do most of the real appending work.

    if(!checkEntryConditions()) {
      return;
    }

    try {
      ObjectMessage msg = topicSession.createObjectMessage();
      if(locationInfo) {
	event.getLocationInformation();
      }
      msg.setObject(event);
      topicPublisher.publish(msg);
    } catch(Exception e) {
      errorHandler.error("Could not publish message in JMSAppender ["+name+"].", e,
			 ErrorCode.GENERIC_FAILURE);
    }
  
protected booleancheckEntryConditions()

    String fail = null;

    if(this.topicConnection == null) {
      fail = "No TopicConnection";
    } else if(this.topicSession == null) {
      fail = "No TopicSession";
    } else if(this.topicPublisher == null) {
      fail = "No TopicPublisher";
    }

    if(fail != null) {
      errorHandler.error(fail +" for JMSAppender named ["+name+"].");
      return false;
    } else {
      return true;
    }
  
public synchronized voidclose()
Close this JMSAppender. Closing releases all resources used by the appender. A closed appender cannot be re-opened.

    // The synchronized modifier avoids concurrent append and close operations

    if(this.closed)
      return;

    LogLog.debug("Closing appender ["+name+"].");
    this.closed = true;

    try {
      if(topicSession != null)
	topicSession.close();
      if(topicConnection != null)
	topicConnection.close();
    } catch(Exception e) {
      LogLog.error("Error while closing JMSAppender ["+name+"].", e);
    }
    // Help garbage collection
    topicPublisher = null;
    topicSession = null;
    topicConnection = null;
  
public java.lang.StringgetInitialContextFactoryName()
Returns the value of the InitialContextFactoryName option. See {@link #setInitialContextFactoryName} for more details on the meaning of this option.

    return initialContextFactoryName;    
  
public booleangetLocationInfo()
Returns value of the LocationInfo property which determines whether location (stack) info is sent to the remote subscriber.

    return locationInfo;
  
public java.lang.StringgetPassword()

    return password;    
  
public java.lang.StringgetProviderURL()

    return providerURL;    
  
public java.lang.StringgetSecurityCredentials()

    return securityCredentials;    
  
public java.lang.StringgetSecurityPrincipalName()

    return securityPrincipalName;    
  
public java.lang.StringgetTopicBindingName()
Returns the value of the TopicBindingName option.

    return topicBindingName;
  
protected javax.jms.TopicConnectiongetTopicConnection()
Returns the TopicConnection used for this appender. Only valid after activateOptions() method has been invoked.

    return topicConnection;
  
public java.lang.StringgetTopicConnectionFactoryBindingName()
Returns the value of the TopicConnectionFactoryBindingName option.

    return tcfBindingName;
  
protected javax.jms.TopicPublishergetTopicPublisher()
Returns the TopicPublisher used for this appender. Only valid after activateOptions() method has been invoked.

    return topicPublisher;
  
protected javax.jms.TopicSessiongetTopicSession()
Returns the TopicSession used for this appender. Only valid after activateOptions() method has been invoked.

    return topicSession;
  
java.lang.StringgetURLPkgPrefixes()

    return urlPkgPrefixes;
  
public java.lang.StringgetUserName()

    return userName;    
  
protected java.lang.Objectlookup(javax.naming.Context ctx, java.lang.String name)

    try {
      return ctx.lookup(name);
    } catch(NameNotFoundException e) {
      LogLog.error("Could not find name ["+name+"].");
      throw e;
    }
  
public booleanrequiresLayout()
The JMSAppender sends serialized events and consequently does not require a layout.

    return false;
  
public voidsetInitialContextFactoryName(java.lang.String initialContextFactoryName)
Setting the InitialContextFactoryName method will cause this JMSAppender instance to use the {@link InitialContext#InitialContext(Hashtable)} method instead of the no-argument constructor. If you set this option, you should also at least set the ProviderURL option.

See also {@link #setProviderURL(String)}.

    this.initialContextFactoryName = initialContextFactoryName;
  
public voidsetLocationInfo(boolean locationInfo)
If true, the information sent to the remote subscriber will include caller's location information. By default no location information is sent to the subscriber.

    this.locationInfo = locationInfo;
  
public voidsetPassword(java.lang.String password)
The paswword to use when creating a topic session.

    this.password = password;
  
public voidsetProviderURL(java.lang.String providerURL)

    this.providerURL = providerURL;
  
public voidsetSecurityCredentials(java.lang.String securityCredentials)

    this.securityCredentials = securityCredentials;
  
public voidsetSecurityPrincipalName(java.lang.String securityPrincipalName)

    this.securityPrincipalName = securityPrincipalName;
  
public voidsetTopicBindingName(java.lang.String topicBindingName)
The TopicBindingName option takes a string value. Its value will be used to lookup the appropriate Topic from the JNDI context.

    this.topicBindingName = topicBindingName;
  
public voidsetTopicConnectionFactoryBindingName(java.lang.String tcfBindingName)
The TopicConnectionFactoryBindingName option takes a string value. Its value will be used to lookup the appropriate TopicConnectionFactory from the JNDI context.

    this.tcfBindingName = tcfBindingName;
  
public voidsetURLPkgPrefixes(java.lang.String urlPkgPrefixes)

    this.urlPkgPrefixes = urlPkgPrefixes;
  
public voidsetUserName(java.lang.String userName)
The user name to use when {@link TopicConnectionFactory#createTopicConnection(String, String) creating a topic session}. If you set this option, you should also set the Password option. See {@link #setPassword(String)}.

    this.userName = userName;