logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ralph Goers <ralph.go...@dslextreme.com>
Subject Re: [02/29] Split out JMS appender and receiver into new log4j module.
Date Fri, 12 Sep 2014 04:25:05 GMT
I kind of got the impression that the point of this discussion was that you wanted jms put back into core.

Ralph

On Sep 11, 2014, at 12:15 PM, Gary Gregory <garydgregory@gmail.com> wrote:

> Right, so we can table this discussion. Unless we want to put JMS back into its 2.0.x location...
> 
> Gary
> 
> On Thu, Sep 11, 2014 at 3:04 PM, Matt Sicker <boards@gmail.com> wrote:
> Plus the LMAX library for AsyncLogger (which I find to be a rather killer feature) makes it somewhat awkward to truly enforce that policy.
> 
> 
> On 11 September 2014 08:47, Gary Gregory <garydgregory@gmail.com> wrote:
> I think the API module should have 0-deps, ideally, which we do. The OSGi dep is "provided" so that's an exception.
> 
> For Core, I do not think we've ever settled on a policy. The policy could be: if you have a runtime dep (test only deps are OK), then you cannot live in Core. But that breaks right away since we bring in lots of deps just to do XML and JSON IO. So that would have to be moved out. Bleh, seems like a big mess.
> 
> Gary
> 
> On Thu, Sep 11, 2014 at 9:29 AM, Matt Sicker <boards@gmail.com> wrote:
> Well, I wouldn't mind putting it back in log4j-core. I mean, the JPA appender is in there, and it would be weird to split that out from the JDBC ones even though only JDBC is in the JDK. Other than the JPA appender, what other appenders are in core that require optional dependencies? I think the SMTP appender requires JavaMail, so there's one more.
> 
> On 11 September 2014 07:39, Ralph Goers <rgoers@apache.org> wrote:
> It sounds like you and I have a similar point of view. If I had to vote it would be something like -0.5 - not a veto but really don't see why this is better.
> 
> Sent from my iPad
> 
> On Sep 11, 2014, at 4:30 AM, Gary Gregory <garydgregory@gmail.com> wrote:
> 
>> So... do we have consensus here?
>> 
>> Right now we have a "Apache Log4j JMS Appenders" module. Shouldn't that be renamed to "Appender" singular?
>> 
>> The only advantage I see is not dragging in the JMS API jar...
>> 
>> Gary
>> 
>> 
>> On Sat, Sep 6, 2014 at 5:47 PM, Matt Sicker <boards@gmail.com> wrote:
>> Honestly, I'd be more likely to use Log4j to log my JMS server rather than the other way around. Plus, Flume is really awesome for distributed logging without the hassle of setting up a network of brokers and other configuration fun when dealing with JMS on a large scale.
>> 
>> 
>> On 6 September 2014 16:20, Ralph Goers <ralph.goers@dslextreme.com> wrote:
>> I guess I prefer to follow the 80/20 rule - core should have all the functionality that 80% of the users will use.  The other 20% - which necessarily require their own dependencies - can be found in outside jars.  I don’t mind telling a user that core has a few optional dependencies for a few optional features. But there should only be a handful of those.
>> 
>> JMS might fit into the same bucket as Flume but it could also be argued that it is similar to JDBC, so I’m on the fence as to whether moving it out is the right thing to do.  
>> 
>> Ralph
>> 
>> On Sep 6, 2014, at 11:56 AM, Gary Gregory <garydgregory@gmail.com> wrote:
>> 
>>> I agree with most of that but the flip side for logging is that we deliver all of log4j because it is the users of our products that decide how to integrate with our products and how logging is done is all up to the users. So our use case is give users all of log4j and let them configure it as they see fit. Which is why I want a all - in - one module where core is the impl.
>>> 
>>> Gary
>>> 
>>> 
>>> -------- Original message --------
>>> From: Matt Sicker
>>> Date:09/06/2014 14:15 (GMT-05:00)
>>> To: Log4J Developers List
>>> Cc: Ralph Goers
>>> Subject: Re: [02/29] Split out JMS appender and receiver into new log4j module.
>>> 
>>> The basic idea is that instead of so many optional dependencies (which still need to be specified in your build script or included as additional JARs), we can break out non-essential pieces with said dependencies into more easily used components. Most of log4j-core doesn't require outside dependencies, so that's a good thing! Sure, in a sense it could be broken up into tons of little modules, but besides the mass of JARs you get from that, I've found that most projects that are so finely split up like that have next to no documentation outside the core modules. Then again, that could be the same with monolithic projects, too. In that regard, I think Log4j is more like Spring where the entire project is rather well documented; however, the javadoc side of things is still lacking (which is understandable).
>>> 
>>> Basically, clear, concise documentation relevant to users and developers alike is key to having a bunch of features (or modules). There are projects like Apache Karaf which have like a bazillion features but tons of them are either undocumented or exist on entirely different projects (like ops4j, Felix, Aries, Geronimo, OpenEJB, OpenWebBeans, Weld, the list goes on and on). The documentation is the code so to say, and when that's split up into dozens of modules, good luck finding anything!
>>> 
>>> I also think that encouraging users to use build systems like Maven or Gradle instead of relying on IDE builds should be encouraged. However, yes, it is important to document how to properly pull all the necessary libraries together manually. I know we've still got various Ant-based builds at my work that require a lot of work to get new libraries added (like Camel, CXF, etc.), and as a user, that's a huge pain. However, I think Log4j is a bit different than projects like Spring/CXF/Camel/Mule as with those projects, you tend to bring in tons of their modules (if not most of them); in Log4j, you only need the modules that correspond to the features you're using (which is probably in log4j-core most of the time; people still prefer logging to files). So instead of having a long chain of dependencies within our own project, anything outside log4j-core would only need third party dependencies/APIs rather than trying to figure out which set of Log4j dependencies are required for yet another Log4j dependency. That would be a much more modular system than the sort of modules we get from monoliths like Spring. (Speaking of Spring, to see just how ridiculous transitive dependencies have gotten, take a look at the Spring IO Platform project: <http://docs.spring.io/platform/docs/1.0.2.RELEASE/reference/htmlsingle/>)
>>> 
>>> I also find that it helps testability when you separate things out a bit more. It can help identify weak areas that don't have many tests that would otherwise go unnoticed (without test coverage tools). It can help identify documentation gaps, too. A monolithic application can mask its lack of manuals or stability just out of its sheer size! I feel that way every time I work with a Java EE server (even though they all use OSGi nowadays) or proprietary libraries with even less documentation than your typical Incubator project. Plus, when things are modularised in a nice fashion (and not ad hoc), then it makes it that much easier for outside contributors to provide changes. Of course, that's more related to high cohesion and loose coupling, but having a module system helps enforce those goals.
>>> 
>>> 
>>> On 6 September 2014 12:22, Gary Gregory <garydgregory@gmail.com> wrote:
>>> Hi Matt, 
>>> 
>>> Feel free to document your thinking process on the ML since we can't banter around a water cooler...
>>> 
>>> I'm all for packaging log4j in a way to make it appealing to the widest audience. I am not fond personally of lots of little jars but it seems to be what OSGi wants. It's that correct? 
>>> 
>>> Gary
>>> 
>>> 
>>> -------- Original message --------
>>> From: Matt Sicker
>>> Date:09/06/2014 12:08 (GMT-05:00)
>>> To: Log4J Developers List
>>> Cc: Ralph Goers
>>> Subject: Re: [02/29] Split out JMS appender and receiver into new log4j module.
>>> 
>>> The nice thing about it being separate from core is that you no longer have
>>> to make the JMS API optional, so this helps transitive dependency
>>> resolution. I already fixed the OSGi problem while it was in core (just had
>>> to make it optional as well as provided). Was it part of log4j 1.2?
>>> http://activemq.apache.org/how-do-i-use-log4j-jms-appender-with-activemq.html
>>> 
>>> Plus, log4j-web is split out, too, though now I'm starting to reconsider
>>> that.
>>> 
>>> 
>>> On 6 September 2014 10:54, Gary Gregory <garydgregory@gmail.com> wrote:
>>> 
>>> > Unless you count the JMS API jar which is not part of the JRE... but is
>>> > that reason enough to have a new module?
>>> >
>>> > Gary
>>> >
>>> >
>>> > -------- Original message --------
>>> > From: Ralph Goers
>>> > Date:09/06/2014 09:17 (GMT-05:00)
>>> > To: Log4J Developers List
>>> > Subject: Re: [02/29] Split out JMS appender and receiver into new log4j
>>> > module.
>>> >
>>> > I think he is doing it for OSGi. But if it has no third party dependencies
>>> > I am not sure why it is necessary.
>>> >
>>> > Sent from my iPad
>>> >
>>> > > On Sep 6, 2014, at 5:14 AM, Gary Gregory <garydgregory@gmail.com> wrote:
>>> > >
>>> > > What is the thought behind splitting JMS out of core?
>>> > >
>>> > > Gary
>>> > >
>>> > >
>>> > > -------- Original message --------
>>> > > From: mattsicker@apache.org
>>> > > Date:09/06/2014 00:58 (GMT-05:00)
>>> > > To: commits@logging.apache.org
>>> > > Subject: [02/29] Split out JMS appender and receiver into new log4j
>>> > module.
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/pom.xml
>>> > > ----------------------------------------------------------------------
>>> > > diff --git a/log4j-mom/pom.xml b/log4j-mom/pom.xml
>>> > > new file mode 100644
>>> > > index 0000000..6c3f760
>>> > > --- /dev/null
>>> > > +++ b/log4j-mom/pom.xml
>>> > > @@ -0,0 +1,53 @@
>>> > > +<?xml version="1.0" encoding="UTF-8"?>
>>> > > +<project xmlns="http://maven.apache.org/POM/4.0.0"
>>> > > +         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>> > > +         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
>>> > http://maven.apache.org/xsd/maven-4.0.0.xsd">
>>> > > +  <parent>
>>> > > +    <artifactId>log4j</artifactId>
>>> > > +    <groupId>org.apache.logging.log4j</groupId>
>>> > > +    <version>2.0-SNAPSHOT</version>
>>> > > +  </parent>
>>> > > +  <modelVersion>4.0.0</modelVersion>
>>> > > +
>>> > > +  <artifactId>log4j-mom</artifactId>
>>> > > +  <name>Log4j 2 MOM Plugins</name>
>>> > > +  <description>Message Oriented Middleware plugins for Log4j
>>> > 2</description>
>>> > > +
>>> > > +  <dependencies>
>>> > > +    <dependency>
>>> > > +      <groupId>org.apache.logging.log4j</groupId>
>>> > > +      <artifactId>log4j-api</artifactId>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>org.apache.logging.log4j</groupId>
>>> > > +      <artifactId>log4j-core</artifactId>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>org.jboss.spec.javax.jms</groupId>
>>> > > +      <artifactId>jboss-jms-api_1.1_spec</artifactId>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>junit</groupId>
>>> > > +      <artifactId>junit</artifactId>
>>> > > +      <scope>test</scope>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>org.mockejb</groupId>
>>> > > +      <artifactId>mockejb</artifactId>
>>> > > +      <scope>test</scope>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>org.apache.logging.log4j</groupId>
>>> > > +      <artifactId>log4j-core</artifactId>
>>> > > +      <type>test-jar</type>
>>> > > +      <scope>test</scope>
>>> > > +    </dependency>
>>> > > +    <dependency>
>>> > > +      <groupId>org.mockito</groupId>
>>> > > +      <artifactId>mockito-all</artifactId>
>>> > > +      <version>1.9.5</version>
>>> > > +      <scope>test</scope>
>>> > > +    </dependency>
>>> > > +  </dependencies>
>>> > > +
>>> > > +</project>
>>> > > \ No newline at end of file
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
>>> > > new file mode 100644
>>> > > index 0000000..284e1f6
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
>>> > > @@ -0,0 +1,111 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.appender;
>>> > > +
>>> > > +import java.io.Serializable;
>>> > > +
>>> > > +import org.apache.logging.log4j.core.Filter;
>>> > > +import org.apache.logging.log4j.core.Layout;
>>> > > +import org.apache.logging.log4j.core.LogEvent;
>>> > > +import org.apache.logging.log4j.core.appender.AbstractAppender;
>>> > > +import org.apache.logging.log4j.core.appender.AppenderLoggingException;
>>> > > +import org.apache.logging.log4j.core.config.plugins.Plugin;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginElement;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
>>> > > +import org.apache.logging.log4j.core.layout.SerializedLayout;
>>> > > +import org.apache.logging.log4j.mom.jms.receiver.JmsQueueManager;
>>> > > +import org.apache.logging.log4j.core.util.Booleans;
>>> > > +
>>> > > +/**
>>> > > + * Appender to write to a JMS Queue.
>>> > > + */
>>> > > +@Plugin(name = "JMSQueue", category = "Core", elementType = "appender",
>>> > printObject = true)
>>> > > +public final class JmsQueueAppender extends AbstractAppender {
>>> > > +
>>> > > +    private final JmsQueueManager manager;
>>> > > +
>>> > > +    private JmsQueueAppender(final String name, final Filter filter,
>>> > final Layout<? extends Serializable> layout,
>>> > > +                             final JmsQueueManager manager, final
>>> > boolean ignoreExceptions) {
>>> > > +        super(name, filter, layout, ignoreExceptions);
>>> > > +        this.manager = manager;
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Actual writing occurs here.
>>> > > +     *
>>> > > +     * @param event The LogEvent.
>>> > > +     */
>>> > > +    @Override
>>> > > +    public void append(final LogEvent event) {
>>> > > +        try {
>>> > > +            manager.send(getLayout().toSerializable(event));
>>> > > +        } catch (final Exception ex) {
>>> > > +            throw new AppenderLoggingException(ex);
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Create a JmsQueueAppender.
>>> > > +     * @param name The name of the Appender.
>>> > > +     * @param factoryName The fully qualified class name of the
>>> > InitialContextFactory.
>>> > > +     * @param providerURL The URL of the provider to use.
>>> > > +     * @param urlPkgPrefixes A colon-separated list of package prefixes
>>> > for the class name of the factory class that
>>> > > +     * will create a URL context factory
>>> > > +     * @param securityPrincipalName The name of the identity of the
>>> > Principal.
>>> > > +     * @param securityCredentials The security credentials of the
>>> > Principal.
>>> > > +     * @param factoryBindingName The name to locate in the Context that
>>> > provides the QueueConnectionFactory.
>>> > > +     * @param queueBindingName The name to use to locate the Queue.
>>> > > +     * @param userName The user ID to use to create the Queue
>>> > Connection.
>>> > > +     * @param password The password to use to create the Queue
>>> > Connection.
>>> > > +     * @param layout The layout to use (defaults to SerializedLayout).
>>> > > +     * @param filter The Filter or null.
>>> > > +     * @param ignore If {@code "true"} (default) exceptions encountered
>>> > when appending events are logged; otherwise
>>> > > +     *               they are propagated to the caller.
>>> > > +     * @return The JmsQueueAppender.
>>> > > +     */
>>> > > +    @PluginFactory
>>> > > +    public static JmsQueueAppender createAppender(
>>> > > +            @PluginAttribute("name") final String name,
>>> > > +            @PluginAttribute("factoryName") final String factoryName,
>>> > > +            @PluginAttribute("providerURL") final String providerURL,
>>> > > +            @PluginAttribute("urlPkgPrefixes") final String
>>> > urlPkgPrefixes,
>>> > > +            @PluginAttribute("securityPrincipalName") final String
>>> > securityPrincipalName,
>>> > > +            @PluginAttribute("securityCredentials") final String
>>> > securityCredentials,
>>> > > +            @PluginAttribute("factoryBindingName") final String
>>> > factoryBindingName,
>>> > > +            @PluginAttribute("queueBindingName") final String
>>> > queueBindingName,
>>> > > +            @PluginAttribute("userName") final String userName,
>>> > > +            @PluginAttribute("password") final String password,
>>> > > +            @PluginElement("Layout") Layout<? extends Serializable>
>>> > layout,
>>> > > +            @PluginElement("Filter") final Filter filter,
>>> > > +            @PluginAttribute("ignoreExceptions") final String ignore) {
>>> > > +        if (name == null) {
>>> > > +            LOGGER.error("No name provided for JmsQueueAppender");
>>> > > +            return null;
>>> > > +        }
>>> > > +        final boolean ignoreExceptions = Booleans.parseBoolean(ignore,
>>> > true);
>>> > > +        final JmsQueueManager manager =
>>> > JmsQueueManager.getJmsQueueManager(factoryName, providerURL, urlPkgPrefixes,
>>> > > +            securityPrincipalName, securityCredentials,
>>> > factoryBindingName, queueBindingName, userName, password);
>>> > > +        if (manager == null) {
>>> > > +            return null;
>>> > > +        }
>>> > > +        if (layout == null) {
>>> > > +            layout = SerializedLayout.createLayout();
>>> > > +        }
>>> > > +        return new JmsQueueAppender(name, filter, layout, manager,
>>> > ignoreExceptions);
>>> > > +    }
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
>>> > > new file mode 100644
>>> > > index 0000000..9985746
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
>>> > > @@ -0,0 +1,112 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.appender;
>>> > > +
>>> > > +import java.io.Serializable;
>>> > > +
>>> > > +import org.apache.logging.log4j.core.Filter;
>>> > > +import org.apache.logging.log4j.core.Layout;
>>> > > +import org.apache.logging.log4j.core.LogEvent;
>>> > > +import org.apache.logging.log4j.core.appender.AbstractAppender;
>>> > > +import org.apache.logging.log4j.core.appender.AppenderLoggingException;
>>> > > +import org.apache.logging.log4j.core.config.plugins.Plugin;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginElement;
>>> > > +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
>>> > > +import org.apache.logging.log4j.core.layout.SerializedLayout;
>>> > > +import org.apache.logging.log4j.mom.jms.receiver.JmsTopicManager;
>>> > > +import org.apache.logging.log4j.core.util.Booleans;
>>> > > +
>>> > > +/**
>>> > > + * Appender to write to a JMS Topic.
>>> > > + */
>>> > > +@Plugin(name = "JMSTopic", category = "Core", elementType = "appender",
>>> > printObject = true)
>>> > > +public final class JmsTopicAppender extends AbstractAppender {
>>> > > +
>>> > > +    private final JmsTopicManager manager;
>>> > > +
>>> > > +    private JmsTopicAppender(final String name, final Filter filter,
>>> > final Layout<? extends Serializable> layout,
>>> > > +                             final JmsTopicManager manager, final
>>> > boolean ignoreExceptions) {
>>> > > +        super(name, filter, layout, ignoreExceptions);
>>> > > +        this.manager = manager;
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Actual writing occurs here.
>>> > > +     * <p/>
>>> > > +     * @param event The LogEvent.
>>> > > +     */
>>> > > +    @Override
>>> > > +    public void append(final LogEvent event) {
>>> > > +        try {
>>> > > +            manager.send(getLayout().toSerializable(event));
>>> > > +        } catch (final Exception ex) {
>>> > > +            throw new AppenderLoggingException(ex);
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Create a JmsTopicAppender.
>>> > > +     * @param name The name of the Appender.
>>> > > +     * @param factoryName The fully qualified class name of the
>>> > InitialContextFactory.
>>> > > +     * @param providerURL The URL of the provider to use.
>>> > > +     * @param urlPkgPrefixes A colon-separated list of package prefixes
>>> > for the class name of the factory class that
>>> > > +     * will create a URL context factory
>>> > > +     * @param securityPrincipalName The name of the identity of the
>>> > Principal.
>>> > > +     * @param securityCredentials The security credentials of the
>>> > Principal.
>>> > > +     * @param factoryBindingName The name to locate in the Context that
>>> > provides the TopicConnectionFactory.
>>> > > +     * @param topicBindingName The name to use to locate the Topic.
>>> > > +     * @param userName The userid to use to create the Topic Connection.
>>> > > +     * @param password The password to use to create the Topic
>>> > Connection.
>>> > > +     * @param layout The layout to use (defaults to SerializedLayout).
>>> > > +     * @param filter The Filter or null.
>>> > > +     * @param ignore If {@code "true"} (default) exceptions encountered
>>> > when appending events are logged; otherwise
>>> > > +     *               they are propagated to the caller.
>>> > > +     * @return The JmsTopicAppender.
>>> > > +     */
>>> > > +    @PluginFactory
>>> > > +    public static JmsTopicAppender createAppender(
>>> > > +            @PluginAttribute("name") final String name,
>>> > > +            @PluginAttribute("factoryName") final String factoryName,
>>> > > +            @PluginAttribute("providerURL") final String providerURL,
>>> > > +            @PluginAttribute("urlPkgPrefixes") final String
>>> > urlPkgPrefixes,
>>> > > +            @PluginAttribute("securityPrincipalName") final String
>>> > securityPrincipalName,
>>> > > +            @PluginAttribute("securityCredentials") final String
>>> > securityCredentials,
>>> > > +            @PluginAttribute("factoryBindingName") final String
>>> > factoryBindingName,
>>> > > +            @PluginAttribute("topicBindingName") final String
>>> > topicBindingName,
>>> > > +            @PluginAttribute("userName") final String userName,
>>> > > +            @PluginAttribute("password") final String password,
>>> > > +            @PluginElement("Layout") Layout<? extends Serializable>
>>> > layout,
>>> > > +            @PluginElement("Filters") final Filter filter,
>>> > > +            @PluginAttribute("ignoreExceptions") final String ignore) {
>>> > > +
>>> > > +        if (name == null) {
>>> > > +            LOGGER.error("No name provided for JmsQueueAppender");
>>> > > +            return null;
>>> > > +        }
>>> > > +        final boolean ignoreExceptions = Booleans.parseBoolean(ignore,
>>> > true);
>>> > > +        final JmsTopicManager manager =
>>> > JmsTopicManager.getJmsTopicManager(factoryName, providerURL, urlPkgPrefixes,
>>> > > +            securityPrincipalName, securityCredentials,
>>> > factoryBindingName, topicBindingName, userName, password);
>>> > > +        if (manager == null) {
>>> > > +            return null;
>>> > > +        }
>>> > > +        if (layout == null) {
>>> > > +            layout = SerializedLayout.createLayout();
>>> > > +        }
>>> > > +        return new JmsTopicAppender(name, filter, layout, manager,
>>> > ignoreExceptions);
>>> > > +    }
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
>>> > > new file mode 100644
>>> > > index 0000000..0c7a4ff
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
>>> > > @@ -0,0 +1,20 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +/**
>>> > > + * Appender classes for using JMS. These are directly configured
>>> > through your log4j2 configuration file.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.appender;
>>> > > \ No newline at end of file
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
>>> > > new file mode 100644
>>> > > index 0000000..d3ae2a3
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
>>> > > @@ -0,0 +1,155 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.receiver;
>>> > > +
>>> > > +import java.io.Serializable;
>>> > > +import java.util.Properties;
>>> > > +
>>> > > +import javax.jms.JMSException;
>>> > > +import javax.jms.Message;
>>> > > +import javax.jms.MessageProducer;
>>> > > +import javax.jms.ObjectMessage;
>>> > > +import javax.jms.Session;
>>> > > +import javax.jms.TextMessage;
>>> > > +import javax.naming.Context;
>>> > > +import javax.naming.InitialContext;
>>> > > +import javax.naming.NameNotFoundException;
>>> > > +import javax.naming.NamingException;
>>> > > +
>>> > > +import org.apache.logging.log4j.core.appender.AbstractManager;
>>> > > +
>>> > > +/**
>>> > > + * Base Class for Managers of JMS connections.
>>> > > + */
>>> > > +public abstract class AbstractJmsManager extends AbstractManager {
>>> > > +
>>> > > +    /**
>>> > > +     * The Constructor.
>>> > > +     * @param name The name of the Appender.
>>> > > +     */
>>> > > +    public AbstractJmsManager(final String name) {
>>> > > +        super(name);
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Create the InitialContext.
>>> > > +     * @param factoryName The fully qualified class name of the
>>> > InitialContextFactory.
>>> > > +     * @param providerURL The URL of the provider to use.
>>> > > +     * @param urlPkgPrefixes A colon-separated list of package prefixes
>>> > for the class name of the factory class that
>>> > > +     * will create a URL context factory
>>> > > +     * @param securityPrincipalName The name of the identity of the
>>> > Principal.
>>> > > +     * @param securityCredentials The security credentials of the
>>> > Principal.
>>> > > +     * @return the InitialContext.
>>> > > +     * @throws NamingException if a naming error occurs.
>>> > > +     */
>>> > > +    protected static Context createContext(final String factoryName,
>>> > final String providerURL,
>>> > > +                                           final String urlPkgPrefixes,
>>> > final String securityPrincipalName,
>>> > > +                                           final String
>>> > securityCredentials)
>>> > > +        throws NamingException {
>>> > > +
>>> > > +        final Properties props = getEnvironment(factoryName,
>>> > providerURL, urlPkgPrefixes, securityPrincipalName,
>>> > > +                                          securityCredentials);
>>> > > +        return new InitialContext(props);
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Looks up the name in the context.
>>> > > +     * @param ctx The Context.
>>> > > +     * @param name The name to locate.
>>> > > +     * @return The object to be located.
>>> > > +     * @throws NamingException If an error occurs locating the name.
>>> > > +     */
>>> > > +    protected static Object lookup(final Context ctx, final String
>>> > name) throws NamingException {
>>> > > +        try {
>>> > > +            return ctx.lookup(name);
>>> > > +        } catch (final NameNotFoundException e) {
>>> > > +            LOGGER.warn("Could not find name [{}].", name);
>>> > > +            throw e;
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Sets up the properties to pass to the InitialContext.
>>> > > +     * @param factoryName The fully qualified class name of the
>>> > InitialContextFactory.
>>> > > +     * @param providerURL The URL of the provider to use.
>>> > > +     * @param urlPkgPrefixes A colon-separated list of package prefixes
>>> > for the class name of the factory class that
>>> > > +     * will create a URL context factory
>>> > > +     * @param securityPrincipalName The name of the identity of the
>>> > Principal.
>>> > > +     * @param securityCredentials The security credentials of the
>>> > Principal.
>>> > > +     * @return The Properties.
>>> > > +     */
>>> > > +    protected static Properties getEnvironment(final String
>>> > factoryName, final String providerURL,
>>> > > +                                               final String
>>> > urlPkgPrefixes, final String securityPrincipalName,
>>> > > +                                               final String
>>> > securityCredentials) {
>>> > > +        final Properties props = new Properties();
>>> > > +        if (factoryName != null) {
>>> > > +            props.put(Context.INITIAL_CONTEXT_FACTORY, factoryName);
>>> > > +            if (providerURL != null) {
>>> > > +                props.put(Context.PROVIDER_URL, providerURL);
>>> > > +            } else {
>>> > > +                LOGGER.warn("The InitialContext factory name has been
>>> > provided without a ProviderURL. " +
>>> > > +                    "This is likely to cause problems");
>>> > > +            }
>>> > > +            if (urlPkgPrefixes != null) {
>>> > > +                props.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
>>> > > +            }
>>> > > +            if (securityPrincipalName != null) {
>>> > > +                props.put(Context.SECURITY_PRINCIPAL,
>>> > securityPrincipalName);
>>> > > +                if (securityCredentials != null) {
>>> > > +                    props.put(Context.SECURITY_CREDENTIALS,
>>> > securityCredentials);
>>> > > +                } else {
>>> > > +                    LOGGER.warn("SecurityPrincipalName has been set
>>> > without SecurityCredentials. " +
>>> > > +                        "This is likely to cause problems.");
>>> > > +                }
>>> > > +            }
>>> > > +            return props;
>>> > > +        }
>>> > > +        return null;
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Send the message.
>>> > > +     * @param object The Object to sent.
>>> > > +     * @throws Exception if an error occurs.
>>> > > +     */
>>> > > +    public abstract void send(Serializable object) throws Exception;
>>> > > +
>>> > > +    /**
>>> > > +     * Send the Object.
>>> > > +     * @param object The Object to send.
>>> > > +     * @param session The Session.
>>> > > +     * @param producer The MessageProducer.
>>> > > +     * @throws Exception if an error occurs.
>>> > > +     */
>>> > > +    public synchronized void send(final Serializable object, final
>>> > Session session, final MessageProducer producer)
>>> > > +        throws Exception {
>>> > > +        try {
>>> > > +            Message msg;
>>> > > +            if (object instanceof String) {
>>> > > +                msg = session.createTextMessage();
>>> > > +                ((TextMessage) msg).setText((String) object);
>>> > > +            } else {
>>> > > +                msg = session.createObjectMessage();
>>> > > +                ((ObjectMessage) msg).setObject(object);
>>> > > +            }
>>> > > +            producer.send(msg);
>>> > > +        } catch (final JMSException ex) {
>>> > > +            LOGGER.error("Could not publish message via JMS {}",
>>> > getName());
>>> > > +            throw ex;
>>> > > +        }
>>> > > +    }
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
>>> > > new file mode 100644
>>> > > index 0000000..bf86c65
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
>>> > > @@ -0,0 +1,83 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.receiver;
>>> > > +
>>> > > +import java.io.Serializable;
>>> > > +
>>> > > +import javax.jms.JMSException;
>>> > > +import javax.jms.ObjectMessage;
>>> > > +import javax.naming.Context;
>>> > > +import javax.naming.NameNotFoundException;
>>> > > +import javax.naming.NamingException;
>>> > > +
>>> > > +import org.apache.logging.log4j.LogManager;
>>> > > +import org.apache.logging.log4j.Logger;
>>> > > +import org.apache.logging.log4j.core.LogEvent;
>>> > > +import org.apache.logging.log4j.core.LogEventListener;
>>> > > +
>>> > > +/**
>>> > > + * Abstract base class for receiving LogEvents over JMS. This class
>>> > expects all messages to be serialized log events.
>>> > > + */
>>> > > +public abstract class AbstractJmsReceiver extends LogEventListener
>>> > implements javax.jms.MessageListener {
>>> > > +
>>> > > +    /**
>>> > > +     * Logger to capture diagnostics.
>>> > > +     */
>>> > > +    protected Logger logger =
>>> > LogManager.getLogger(this.getClass().getName());
>>> > > +
>>> > > +    /**
>>> > > +     * Listener that receives the event.
>>> > > +     * @param message The received message.
>>> > > +     */
>>> > > +    @Override
>>> > > +    public void onMessage(final javax.jms.Message message) {
>>> > > +        try {
>>> > > +            if (message instanceof ObjectMessage) {
>>> > > +                final ObjectMessage objectMessage = (ObjectMessage)
>>> > message;
>>> > > +                final Serializable object = objectMessage.getObject();
>>> > > +                if (object instanceof LogEvent) {
>>> > > +                    log((LogEvent) object);
>>> > > +                } else {
>>> > > +                    logger.warn("Received message is of type " +
>>> > object.getClass().getName() + ", was expecting LogEvent.");
>>> > > +                }
>>> > > +            } else {
>>> > > +                logger.warn("Received message is of type " +
>>> > message.getJMSType()
>>> > > +                    + ", was expecting ObjectMessage.");
>>> > > +            }
>>> > > +        } catch (final JMSException jmse) {
>>> > > +            logger.error("Exception thrown while processing incoming
>>> > message.",
>>> > > +                jmse);
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Looks up an object from the Context.
>>> > > +     * @param ctx The Context.
>>> > > +     * @param name The name of the object to locate.
>>> > > +     * @return The object.
>>> > > +     * @throws NamingException if an error occurs.
>>> > > +     */
>>> > > +    protected Object lookup(final Context ctx, final String name)
>>> > throws NamingException {
>>> > > +        try {
>>> > > +            return ctx.lookup(name);
>>> > > +        } catch (final NameNotFoundException e) {
>>> > > +            logger.error("Could not find name [" + name + "].");
>>> > > +            throw e;
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
>>> > > new file mode 100644
>>> > > index 0000000..6825282
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
>>> > > @@ -0,0 +1,237 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.receiver;
>>> > > +
>>> > > +import java.io.Serializable;
>>> > > +
>>> > > +import javax.jms.JMSException;
>>> > > +import javax.jms.Queue;
>>> > > +import javax.jms.QueueConnection;
>>> > > +import javax.jms.QueueConnectionFactory;
>>> > > +import javax.jms.QueueSender;
>>> > > +import javax.jms.QueueSession;
>>> > > +import javax.jms.Session;
>>> > > +import javax.naming.Context;
>>> > > +import javax.naming.NamingException;
>>> > > +
>>> > > +import org.apache.logging.log4j.core.appender.ManagerFactory;
>>> > > +
>>> > > +/**
>>> > > + * Manager for a JMS Queue.
>>> > > + */
>>> > > +public class JmsQueueManager extends AbstractJmsManager {
>>> > > +
>>> > > +    private static final JMSQueueManagerFactory FACTORY = new
>>> > JMSQueueManagerFactory();
>>> > > +
>>> > > +    private QueueInfo info;
>>> > > +    private final String factoryBindingName;
>>> > > +    private final String queueBindingName;
>>> > > +    private final String userName;
>>> > > +    private final String password;
>>> > > +    private final Context context;
>>> > > +
>>> > > +    /**
>>> > > +     * The Constructor.
>>> > > +     * @param name The unique name of the connection.
>>> > > +     * @param context The context.
>>> > > +     * @param factoryBindingName The factory binding name.
>>> > > +     * @param queueBindingName The queue binding name.
>>> > > +     * @param userName The user name.
>>> > > +     * @param password The credentials for the user.
>>> > > +     * @param info The Queue connection info.
>>> > > +     */
>>> > > +    protected JmsQueueManager(final String name, final Context context,
>>> > final String factoryBindingName,
>>> > > +                              final String queueBindingName, final
>>> > String userName, final String password,
>>> > > +                              final QueueInfo info) {
>>> > > +        super(name);
>>> > > +        this.context = context;
>>> > > +        this.factoryBindingName = factoryBindingName;
>>> > > +        this.queueBindingName = queueBindingName;
>>> > > +        this.userName = userName;
>>> > > +        this.password = password;
>>> > > +        this.info = info;
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Obtain a JmsQueueManager.
>>> > > +     * @param factoryName The fully qualified class name of the
>>> > InitialContextFactory.
>>> > > +     * @param providerURL The URL of the provider to use.
>>> > > +     * @param urlPkgPrefixes A colon-separated list of package prefixes
>>> > for the class name of the factory class that
>>> > > +     * will create a URL context factory
>>> > > +     * @param securityPrincipalName The name of the identity of the
>>> > Principal.
>>> > > +     * @param securityCredentials The security credentials of the
>>> > Principal.
>>> > > +     * @param factoryBindingName The name to locate in the Context that
>>> > provides the QueueConnectionFactory.
>>> > > +     * @param queueBindingName The name to use to locate the Queue.
>>> > > +     * @param userName The userid to use to create the Queue Connection.
>>> > > +     * @param password The password to use to create the Queue
>>> > Connection.
>>> > > +     * @return The JmsQueueManager.
>>> > > +     */
>>> > > +    public static JmsQueueManager getJmsQueueManager(final String
>>> > factoryName, final String providerURL,
>>> > > +                                                     final String
>>> > urlPkgPrefixes, final String securityPrincipalName,
>>> > > +                                                     final String
>>> > securityCredentials, final String factoryBindingName,
>>> > > +                                                     final String
>>> > queueBindingName, final String userName,
>>> > > +                                                     final String
>>> > password) {
>>> > > +
>>> > > +        if (factoryBindingName == null) {
>>> > > +            LOGGER.error("No factory name provided for
>>> > JmsQueueManager");
>>> > > +            return null;
>>> > > +        }
>>> > > +        if (queueBindingName == null) {
>>> > > +            LOGGER.error("No topic name provided for JmsQueueManager");
>>> > > +            return null;
>>> > > +        }
>>> > > +
>>> > > +        final String name = "JMSQueue:" + factoryBindingName + '.' +
>>> > queueBindingName;
>>> > > +        return getManager(name, FACTORY, new FactoryData(factoryName,
>>> > providerURL, urlPkgPrefixes,
>>> > > +            securityPrincipalName, securityCredentials,
>>> > factoryBindingName, queueBindingName, userName, password));
>>> > > +    }
>>> > > +
>>> > > +    @Override
>>> > > +    public synchronized void send(final Serializable object) throws
>>> > Exception {
>>> > > +        if (info == null) {
>>> > > +            info = connect(context, factoryBindingName,
>>> > queueBindingName, userName, password, false);
>>> > > +        }
>>> > > +        try {
>>> > > +            super.send(object, info.session, info.sender);
>>> > > +        } catch (final Exception ex) {
>>> > > +            cleanup(true);
>>> > > +            throw ex;
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    @Override
>>> > > +    public void releaseSub() {
>>> > > +        if (info != null) {
>>> > > +            cleanup(false);
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    private void cleanup(final boolean quiet) {
>>> > > +        try {
>>> > > +            info.session.close();
>>> > > +        } catch (final Exception e) {
>>> > > +            if (!quiet) {
>>> > > +                LOGGER.error("Error closing session for " + getName(),
>>> > e);
>>> > > +            }
>>> > > +        }
>>> > > +        try {
>>> > > +            info.conn.close();
>>> > > +        } catch (final Exception e) {
>>> > > +            if (!quiet) {
>>> > > +                LOGGER.error("Error closing connection for " +
>>> > getName(), e);
>>> > > +            }
>>> > > +        }
>>> > > +        info = null;
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Data for the factory.
>>> > > +     */
>>> > > +    private static class FactoryData {
>>> > > +        private final String factoryName;
>>> > > +        private final String providerURL;
>>> > > +        private final String urlPkgPrefixes;
>>> > > +        private final String securityPrincipalName;
>>> > > +        private final String securityCredentials;
>>> > > +        private final String factoryBindingName;
>>> > > +        private final String queueBindingName;
>>> > > +        private final String userName;
>>> > > +        private final String password;
>>> > > +
>>> > > +        public FactoryData(final String factoryName, final String
>>> > providerURL, final String urlPkgPrefixes,
>>> > > +                           final String securityPrincipalName, final
>>> > String securityCredentials,
>>> > > +                           final String factoryBindingName, final
>>> > String queueBindingName, final String userName,
>>> > > +                           final String password) {
>>> > > +            this.factoryName = factoryName;
>>> > > +            this.providerURL = providerURL;
>>> > > +            this.urlPkgPrefixes = urlPkgPrefixes;
>>> > > +            this.securityPrincipalName = securityPrincipalName;
>>> > > +            this.securityCredentials = securityCredentials;
>>> > > +            this.factoryBindingName = factoryBindingName;
>>> > > +            this.queueBindingName = queueBindingName;
>>> > > +            this.userName = userName;
>>> > > +            this.password = password;
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    private static QueueInfo connect(final Context context, final
>>> > String factoryBindingName,
>>> > > +                                     final String queueBindingName,
>>> > final String userName, final String password,
>>> > > +                                     final boolean suppress) throws
>>> > Exception {
>>> > > +        try {
>>> > > +            final QueueConnectionFactory factory =
>>> > (QueueConnectionFactory) lookup(context, factoryBindingName);
>>> > > +            QueueConnection conn;
>>> > > +            if (userName != null) {
>>> > > +                conn = factory.createQueueConnection(userName,
>>> > password);
>>> > > +            } else {
>>> > > +                conn = factory.createQueueConnection();
>>> > > +            }
>>> > > +            final QueueSession sess = conn.createQueueSession(false,
>>> > Session.AUTO_ACKNOWLEDGE);
>>> > > +            final Queue queue = (Queue) lookup(context,
>>> > queueBindingName);
>>> > > +            final QueueSender sender = sess.createSender(queue);
>>> > > +            conn.start();
>>> > > +            return new QueueInfo(conn, sess, sender);
>>> > > +        } catch (final NamingException ex) {
>>> > > +            LOGGER.warn("Unable to locate connection factory " +
>>> > factoryBindingName, ex);
>>> > > +            if (!suppress) {
>>> > > +                throw ex;
>>> > > +            }
>>> > > +        } catch (final JMSException ex) {
>>> > > +            LOGGER.warn("Unable to create connection to queue " +
>>> > queueBindingName, ex);
>>> > > +            if (!suppress) {
>>> > > +                throw ex;
>>> > > +            }
>>> > > +        }
>>> > > +        return null;
>>> > > +    }
>>> > > +
>>> > > +    /** Queue connection information */
>>> > > +    private static class QueueInfo {
>>> > > +        private final QueueConnection conn;
>>> > > +        private final QueueSession session;
>>> > > +        private final QueueSender sender;
>>> > > +
>>> > > +        public QueueInfo(final QueueConnection conn, final QueueSession
>>> > session, final QueueSender sender) {
>>> > > +            this.conn = conn;
>>> > > +            this.session = session;
>>> > > +            this.sender = sender;
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Factory to create the JmsQueueManager.
>>> > > +     */
>>> > > +    private static class JMSQueueManagerFactory implements
>>> > ManagerFactory<JmsQueueManager, FactoryData> {
>>> > > +
>>> > > +        @Override
>>> > > +        public JmsQueueManager createManager(final String name, final
>>> > FactoryData data) {
>>> > > +            try {
>>> > > +                final Context ctx = createContext(data.factoryName,
>>> > data.providerURL, data.urlPkgPrefixes,
>>> > > +                                            data.securityPrincipalName,
>>> > data.securityCredentials);
>>> > > +                final QueueInfo info = connect(ctx,
>>> > data.factoryBindingName, data.queueBindingName, data.userName,
>>> > > +                    data.password, true);
>>> > > +                return new JmsQueueManager(name, ctx,
>>> > data.factoryBindingName, data.queueBindingName,
>>> > > +                    data.userName, data.password, info);
>>> > > +            } catch (final NamingException ex) {
>>> > > +                LOGGER.error("Unable to locate resource", ex);
>>> > > +            } catch (final Exception ex) {
>>> > > +                LOGGER.error("Unable to connect", ex);
>>> > > +            }
>>> > > +
>>> > > +            return null;
>>> > > +        }
>>> > > +    }
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
>>> > > ----------------------------------------------------------------------
>>> > > diff --git
>>> > a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
>>> > > new file mode 100644
>>> > > index 0000000..b231489
>>> > > --- /dev/null
>>> > > +++
>>> > b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
>>> > > @@ -0,0 +1,107 @@
>>> > > +/*
>>> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> > > + * contributor license agreements. See the NOTICE file distributed with
>>> > > + * this work for additional information regarding copyright ownership.
>>> > > + * The ASF licenses this file to You under the Apache license, Version
>>> > 2.0
>>> > > + * (the "License"); you may not use this file except in compliance with
>>> > > + * the License. You may obtain a copy of the License at
>>> > > + *
>>> > > + *      http://www.apache.org/licenses/LICENSE-2.0
>>> > > + *
>>> > > + * Unless required by applicable law or agreed to in writing, software
>>> > > + * distributed under the License is distributed on an "AS IS" BASIS,
>>> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> > implied.
>>> > > + * See the license for the specific language governing permissions and
>>> > > + * limitations under the license.
>>> > > + */
>>> > > +package org.apache.logging.log4j.mom.jms.receiver;
>>> > > +
>>> > > +import java.io.BufferedReader;
>>> > > +import java.io.InputStreamReader;
>>> > > +import java.nio.charset.Charset;
>>> > > +
>>> > > +import javax.jms.JMSException;
>>> > > +import javax.jms.Queue;
>>> > > +import javax.jms.QueueConnection;
>>> > > +import javax.jms.QueueConnectionFactory;
>>> > > +import javax.jms.QueueReceiver;
>>> > > +import javax.jms.QueueSession;
>>> > > +import javax.jms.Session;
>>> > > +import javax.naming.Context;
>>> > > +import javax.naming.InitialContext;
>>> > > +import javax.naming.NamingException;
>>> > > +
>>> > > +/**
>>> > > + * Receives Log Events over a JMS Queue. This implementation expects
>>> > that all messages will
>>> > > + * contain a serialized LogEvent.
>>> > > + */
>>> > > +public class JmsQueueReceiver extends AbstractJmsReceiver {
>>> > > +
>>> > > +    /**
>>> > > +     * Constructor.
>>> > > +     * @param qcfBindingName The QueueConnectionFactory binding name.
>>> > > +     * @param queueBindingName The Queue binding name.
>>> > > +     * @param username The userid to connect to the queue.
>>> > > +     * @param password The password to connect to the queue.
>>> > > +     */
>>> > > +    public JmsQueueReceiver(final String qcfBindingName, final String
>>> > queueBindingName, final String username,
>>> > > +                            final String password) {
>>> > > +
>>> > > +        try {
>>> > > +            final Context ctx = new InitialContext();
>>> > > +            QueueConnectionFactory queueConnectionFactory;
>>> > > +            queueConnectionFactory = (QueueConnectionFactory)
>>> > lookup(ctx, qcfBindingName);
>>> > > +            final QueueConnection queueConnection =
>>> > queueConnectionFactory.createQueueConnection(username, password);
>>> > > +            queueConnection.start();
>>> > > +            final QueueSession queueSession =
>>> > queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
>>> > > +            final Queue queue = (Queue) ctx.lookup(queueBindingName);
>>> > > +            final QueueReceiver queueReceiver =
>>> > queueSession.createReceiver(queue);
>>> > > +            queueReceiver.setMessageListener(this);
>>> > > +        } catch (final JMSException e) {
>>> > > +            logger.error("Could not read JMS message.", e);
>>> > > +        } catch (final NamingException e) {
>>> > > +            logger.error("Could not read JMS message.", e);
>>> > > +        } catch (final RuntimeException e) {
>>> > > +            logger.error("Could not read JMS message.", e);
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +    /**
>>> > > +     * Main startup for the receiver.
>>> > > +     * @param args The command line arguments.
>>> > > +     * @throws Exception if an error occurs.
>>> > > +     */
>>> > > +    public static void main(final String[] args) throws Exception {
>>> > > +        if (args.length != 4) {
>>> > > +            usage("Wrong number of arguments.");
>>> > > +        }
>>> > > +
>>> > > +        final String qcfBindingName = args[0];
>>> > > +        final String queueBindingName = args[1];
>>> > > +        final String username = args[2];
>>> > > +        final String password = args[3];
>>> > > +
>>> > > +        new JmsQueueReceiver(qcfBindingName, queueBindingName,
>>> > username, password);
>>> > > +
>>> > > +        final Charset enc = Charset.defaultCharset();
>>> > > +        final BufferedReader stdin = new BufferedReader(new
>>> > InputStreamReader(System.in, enc));
>>> > > +        // Loop until the word "exit" is typed
>>> > > +        System.out.println("Type \"exit\" to quit JmsQueueReceiver.");
>>> > > +        while (true) {
>>> > > +            final String line = stdin.readLine();
>>> > > +            if (line == null || line.equalsIgnoreCase("exit")) {
>>> > > +                System.out.println("Exiting. Kill the application if it
>>> > does not exit "
>>> > > +                    + "due to daemon threads.");
>>> > > +                return;
>>> > > +            }
>>> > > +        }
>>> > > +    }
>>> > > +
>>> > > +
>>> > > +    private static void usage(final String msg) {
>>> > > +        System.err.println(msg);
>>> > > +        System.err.println("Usage: java " +
>>> > JmsQueueReceiver.class.getName()
>>> > > +            + " QueueConnectionFactoryBindingName QueueBindingName
>>> > username password");
>>> > > +        System.exit(1);
>>> > > +    }
>>> > > +}
>>> > >
>>> > >
>>> > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsTop
>>> 
>>> 
>>> 
>>> -- 
>>> Matt Sicker <boards@gmail.com>
>> 
>> 
>> 
>> 
>> -- 
>> Matt Sicker <boards@gmail.com>
>> 
>> 
>> 
>> -- 
>> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>> Java Persistence with Hibernate, Second Edition
>> JUnit in Action, Second Edition
>> Spring Batch in Action
>> Blog: http://garygregory.wordpress.com 
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
> 
> 
> 
> -- 
> Matt Sicker <boards@gmail.com>
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
> 
> 
> 
> -- 
> Matt Sicker <boards@gmail.com>
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory


Mime
View raw message