【问题标题】:How to use log4j2 JMSAppender with ActiveMQ如何在 ActiveMQ 中使用 log4j2 JMSAppender
【发布时间】:2015-07-04 18:30:39
【问题描述】:

我正在努力编写一个将消息记录到队列的简单 POC 程序。我发现的所有教程和问答(herehere)都使用 log4j 1.2 版,它们将消息放入主题而不是队列。我的要求是登录到队列。

我遵循了official site 中提到的文档,但无法使其正常工作。

我的类路径上有 log4j2 和 ActiveMQ JAR,我创建了队列“logQueue”,我能够在 ActiveMQ Web 控制台中看到队列,当我尝试执行程序来写入日志时,我得到以下信息错误:

ERROR Error creating JmsManager using ConnectionFactory [ConnectionFactory] and Destination [logQueue]. javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)

它显然看起来像一些 JNDI 问题,但我无法弄清楚是什么。根据 log4j 1.2 教程,我还将 jndi.properties 文件添加到我的类路径中,其值为

queue.logQueue=logQueue

但这显然没有帮助。下面是我的 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <JMS name="jmsQueue" destinationBindingName="logQueue"
         factoryBindingName="ConnectionFactory"
         providerURL="tcp://localhost:61616"/>
  </Appenders>
  <Loggers>
    <Root level="all">
      <AppenderRef ref="jmsQueue"/>
    </Root>
  </Loggers>
</Configuration>

谢谢!

【问题讨论】:

    标签: java jms activemq jndi log4j2


    【解决方案1】:

    在 JMS 元素中添加factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory" 解决了这个问题。

    log4j2.xml 中的最终 JMS 元素如下所示:

    <JMS name="jmsQueue" destinationBindingName="logQueue"
            factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory"
            factoryBindingName="ConnectionFactory"
            providerURL="tcp://localhost:61616"/>
    

    【讨论】:

    • 嗨,上面还提到了 factoryName,我遇到的错误如下 使用 ConnectionFactory [ConnectionFactory] ​​和 Destination [JMSL4JQ] 创建 JmsManager 时出错。 javax.naming.NameNotFoundException: JMSL4JQ.... 任何帮助都会被理解..... :(
    【解决方案2】:

    我在appender的初始化过程中遇到了错误,所以我尝试自己编写而不是使用现有的xml配置。

    依赖版本:

    • ActiveMQ 5.12.1 客户端
    • log4j-core-2.5
    • slf4j-1.7.12

    Java 类:

    复制该类并将其放在项目中的任何位置,

    package com.towersoft.eagleserver;
    
    import java.io.Serializable;
    
    import javax.jms.DeliveryMode;
    import javax.jms.Destination;
    import javax.jms.MessageProducer;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import org.apache.activemq.ActiveMQConnectionFactory;
    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.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.PatternLayout;
    
    
    @Plugin(name = "JMSQueueAppender", category = "Core", elementType = "appender", printObject = true)
    public class JMSQueueAppender extends AbstractAppender {
    
    //    private static Logger logger = Logger.getLogger("JMSQueueAppender");
        private String brokerUri = "failover://tcp://localhost:61616";
        private String queueName = "logQueue";
        Session session;
    
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(this.brokerUri);
        javax.jms.Connection connection;
        Destination destination;
        MessageProducer producer;
    
    
        private void init() {
            try {
    
                connection = connectionFactory.createConnection();
                connection.start();
                // Create a Session
                session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                destination = session.createQueue(this.queueName);
                producer = session.createProducer(destination);
                producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        protected JMSQueueAppender(String name, Filter filter,
                Layout<? extends Serializable> layout, final boolean ignoreExceptions) {
            super(name, filter, layout, ignoreExceptions);
            init();
        }
    
        @Override
        public void append(LogEvent le) {
            try {
                if (connection == null) {
                    init();
                }
                TextMessage message = session.createTextMessage(le.getMessage().getFormattedMessage());
                // Tell the producer to send the message
                producer.send(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void stop() {
            super.stop(); 
            try {
                session.close();
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @PluginFactory
        public static JMSQueueAppender createAppender(
                @PluginAttribute("name") String name,
                @PluginElement("Layout") Layout<? extends Serializable> layout,
                @PluginElement("Filter") final Filter filter) {
            if (name == null) {
                LOGGER.error("No name provided for MyCustomAppenderImpl");
                return null;
            }
            if (layout == null) {
                layout = PatternLayout.createDefaultLayout();
            }
            return new JMSQueueAppender(name, filter, layout, true);
        }
    }
    

    log4j2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            </Console>
            <JMSQueueAppender name="jmsQueue"/>
        </Appenders>
        <Loggers>
            <Root level="debug">
                <AppenderRef ref="Console"/>
                <AppenderRef ref="jmsQueue"/>
            </Root>
            <Logger name="org.quartz" level="ERROR"/>
            <Logger name="com.zaxxer" level="ERROR"/>
            <Logger name="org.apache.activemq" level="ERROR"/>
        </Loggers>
    </Configuration>
    

    【讨论】:

      【解决方案3】:

      我确实遇到了这个问题。通过向我的 Maven 资源目录添加一个名为 jndi.properties 的文件来解决,其内容...

      topic.logTopic=logTopic
      queue.logQueue=logQueue
      

      显然可以修改实际使用的名称。就我而言,我的 appender 可能是 ...

      <JMS name="jmsQueue" 
                  destinationBindingName="logQueue" 
                  factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory"
                  factoryBindingName="ConnectionFactory"
                  providerURL="tcp://localhost:61616"
                  userName="admin"
                  password="admin">
                  <SyslogLayout />
                </JMS>
      

      注意:我必须修改附加程序的布局以避免序列化错误(其他可能的值是... JSONLayout、YamlLayout、HtmlLayout 等)。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-01
        • 2021-04-24
        • 2017-02-08
        相关资源
        最近更新 更多