alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.  */

package org.apache.log4j.net;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.helpers.LogLog;

import java.util.Properties;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.Topic;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.Session;
import javax.jms.ObjectMessage;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

/**
 * 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ü */ public class JMSAppender extends AppenderSkeleton { String securityPrincipalName; String securityCredentials; String initialContextFactoryName; String urlPkgPrefixes; String providerURL; String topicBindingName; String tcfBindingName; String userName; String password; boolean locationInfo; TopicConnection topicConnection; TopicSession topicSession; TopicPublisher topicPublisher; public JMSAppender() { } /** The TopicConnectionFactoryBindingName option takes a string value. Its value will be used to lookup the appropriate TopicConnectionFactory from the JNDI context. */ public void setTopicConnectionFactoryBindingName(String tcfBindingName) { this.tcfBindingName = tcfBindingName; } /** Returns the value of the TopicConnectionFactoryBindingName option. */ public String getTopicConnectionFactoryBindingName() { return tcfBindingName; } /** The TopicBindingName option takes a string value. Its value will be used to lookup the appropriate Topic from the JNDI context. */ public void setTopicBindingName(String topicBindingName) { this.topicBindingName = topicBindingName; } /** Returns the value of the TopicBindingName option. */ public String getTopicBindingName() { return topicBindingName; } /** Returns value of the LocationInfo property which determines whether location (stack) info is sent to the remote subscriber. */ public boolean getLocationInfo() { return locationInfo; } /** * Options are activated and become effective only after calling * this method.*/ public void activateOptions() { 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); } } protected Object lookup(Context ctx, String name) throws NamingException { try { return ctx.lookup(name); } catch(NameNotFoundException e) { LogLog.error("Could not find name ["+name+"]."); throw e; } } protected boolean checkEntryConditions() { 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; } } /** Close this JMSAppender. Closing releases all resources used by the appender. A closed appender cannot be re-opened. */ public synchronized void close() { // 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; } /** This method called by {@link AppenderSkeleton#doAppend} method to do most of the real appending work. */ public void append(LoggingEvent event) { 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); } } /** * Returns the value of the InitialContextFactoryName option. * See {@link #setInitialContextFactoryName} for more details on the * meaning of this option. * */ public String getInitialContextFactoryName() { return 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)}. * */ public void setInitialContextFactoryName(String initialContextFactoryName) { this.initialContextFactoryName = initialContextFactoryName; } public String getProviderURL() { return providerURL; } public void setProviderURL(String providerURL) { this.providerURL = providerURL; } String getURLPkgPrefixes( ) { return urlPkgPrefixes; } public void setURLPkgPrefixes(String urlPkgPrefixes ) { this.urlPkgPrefixes = urlPkgPrefixes; } public String getSecurityCredentials() { return securityCredentials; } public void setSecurityCredentials(String securityCredentials) { this.securityCredentials = securityCredentials; } public String getSecurityPrincipalName() { return securityPrincipalName; } public void setSecurityPrincipalName(String securityPrincipalName) { this.securityPrincipalName = securityPrincipalName; } public String getUserName() { return 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)}. * */ public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } /** * The paswword to use when creating a topic session. */ public void setPassword(String password) { this.password = password; } /** 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. */ public void setLocationInfo(boolean locationInfo) { this.locationInfo = locationInfo; } /** * The JMSAppender sends serialized events and consequently does not * require a layout. * */ public boolean requiresLayout() { return false; } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.