获取Hawtio以在JMS消息中显示超过255个字符

时间:2015-09-01 17:55:29

标签: jms apache-camel activemq hawtio

我使用Hawtio浏览我的ActiveMQ队列。我还希望能够在将JMS消息重新发送到另一个队列之前编辑它。

我不知道如何在Hawtio中编辑邮件,但这没关系,我想在代理中直接修改邮件并不合法。

相反,我会复制邮件正文并发送一条修改了正文的新邮件。现在,我遇到的问题是我只能看到邮件正文的前255个字符。如何在hawtio中查看整个ActiveMQ消息?不只是前255个字符。

2 个答案:

答案 0 :(得分:2)

Hawtio用于浏览JMX接口的队列。它调用队列上的browse()方法。这会将消息作为CompositedData[]返回。

转换ActiveMQBytesMessage后(检查课程org.apache.activemq.broker.jmx.OpenTypeSupport.ByteMessageOpenTypeFactory),会添加两个字段BodyLengthBodyPreview。这些字段返回以下数据。

  • BodyLength - JMS邮件正文的长度
  • BodyPreview - JMS消息正文的前255个字节(硬编码的长度,Claus Ibsen已在答案中说明;-))

在课程org.apache.activemq.broker.jmx.OpenTypeSupport.ByteMessageOpenTypeFactory中检查方法Map<String, Object> getFields(Object o)

Hawtio使用字段BodyPreview显示非短信息的消息。

签入Hawtio文件hawtio-web/src/main/webapp/app/activemq/js/browse.ts

function createBodyText(message) {
    if (message.Text) {
        ...
    } else if (message.BodyPreview) {
        ...
        if (code === 1 || code === 2) {
            // bytes and text
            var len = message.BodyPreview.length;
            var lenTxt = "" + textArr.length;
            body = "bytes:\n" + bytesData + "\n\ntext:\n" + textData;
            message.textMode = "bytes (" + len + " bytes) and text (" + lenTxt + " chars)";
        } else {
            // bytes only
            var len = message.BodyPreview.length;
            body = bytesData;
            message.textMode = "bytes (" + len + " bytes)";
        }
        ...
    } else {
        message.textMode = "unsupported";
        ...

如果您想要更改它,则必须在ActiveMQHawtio中进行更改。

一个冗长而冗长的例子来证明解释。

import static java.lang.System.out;
import java.lang.management.ManagementFactory;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeType;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.jmx.QueueViewMBean;
import org.apache.activemq.command.ActiveMQBytesMessage;
import org.apache.activemq.command.ActiveMQTextMessage;

public class BodyPreviewExample {

    public static void main(String[] args) throws Exception {
        String password = "password";
        String user = "user";
        String queueName = "TEST_QUEUE";
        String brokerUrl = "tcp://localhost:61616";

        BrokerService broker = BrokerFactory.createBroker("broker:"+brokerUrl);
        broker.start();
        broker.waitUntilStarted();

        Connection conn = new ActiveMQConnectionFactory(brokerUrl)
                .createConnection(user, password);
        conn.start();

        Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue producerQueue = session.createQueue(queueName);
        MessageProducer producer = session.createProducer(producerQueue);

        // create a dummy message
        StringBuilder sb = new StringBuilder(1000);
        for (int i = 0; i < 100; i++) {
            sb.append(">CAFEBABE<");
        }

        // create and send a JMSBytesMessage
        BytesMessage bytesMsg = session.createBytesMessage();
        bytesMsg.writeBytes(sb.toString().getBytes());
        producer.send(bytesMsg);

        // create and send a JMSTextMessage
        TextMessage textMsg = session.createTextMessage();
        textMsg.setText(sb.toString());
        producer.send(textMsg);

        producer.close();

        out.printf("%nmessage info via session browser%n");
        String format = "%-20s = %s%n";
        Queue consumerQueue = session.createQueue(queueName);
        QueueBrowser browser = session.createBrowser(consumerQueue);
        for (Enumeration p = browser.getEnumeration(); p.hasMoreElements();) {
            out.println();
            Object next = p.nextElement();
            if (next instanceof ActiveMQBytesMessage) {
                ActiveMQBytesMessage amq = (ActiveMQBytesMessage) next;
                out.printf(format, "JMSMessageID", amq.getJMSMessageID());
                out.printf(format, "JMSDestination", amq.getJMSDestination());
                out.printf(format, "JMSXMimeType", amq.getJMSXMimeType());
                out.printf(format, "BodyLength", amq.getBodyLength());
            } else if (next instanceof ActiveMQTextMessage) {
                ActiveMQTextMessage amq = (ActiveMQTextMessage) next;
                out.printf(format, "JMSMessageID", amq.getJMSMessageID());
                out.printf(format, "JMSDestination", amq.getJMSDestination());
                out.printf(format, "JMSXMimeType", amq.getJMSXMimeType());
                out.printf(format, "text.length", amq.getText().length());
            } else {
                out.printf("unhandled message type: %s%n", next.getClass());
            }
        }
        session.close();
        conn.close();

        // access the queue via JMX
        out.printf("%nmessage info via JMX browse operation%n");
        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("org.apache.activemq:type=Broker"
                + ",brokerName=localhost"
                + ",destinationType=Queue"
                + ",destinationName=" + queueName);
        QueueViewMBean queue
                = MBeanServerInvocationHandler.newProxyInstance(mbeanServer,
                        name, QueueViewMBean.class, true);
        CompositeData[] browse = queue.browse();
        for (CompositeData compositeData : browse) {
            out.println();
            CompositeType compositeType = compositeData.getCompositeType();
            out.printf(format, "CompositeType", compositeType.getTypeName());
            out.printf(format,"JMSMessageID",compositeData.get("JMSMessageID"));
            if (compositeData.containsKey("BodyLength")) {
                // body length of the ActiveMQBytesMessage
                Long bodyLength = (Long) compositeData.get("BodyLength");
                out.printf(format, "BodyLength", bodyLength);
                // the content displayed by hawtio
                Byte[] bodyPreview = (Byte[]) compositeData.get("BodyPreview");
                out.printf(format, "size of BodyPreview", bodyPreview.length);
            } else if (compositeData.containsKey("Text")) {
                String text = (String) compositeData.get("Text");
                out.printf(format, "Text.length()", text.length());
            }
        }
        // uncomment if you want to check with e.g. JConsole
        // TimeUnit.MINUTES.sleep(5);
        broker.stop();
    }
}

示例输出

message info via session browser

JMSMessageID         = ID:hostname-50075-1467979678722-3:1:1:1:1
JMSDestination       = queue://TEST_QUEUE
JMSXMimeType         = jms/bytes-message
BodyLength           = 1000

JMSMessageID         = ID:hostname-50075-1467979678722-3:1:1:1:2
JMSDestination       = queue://TEST_QUEUE
JMSXMimeType         = jms/text-message
text.length          = 1000

message info via JMX browse operation

CompositeType        = org.apache.activemq.command.ActiveMQBytesMessage
JMSMessageID         = ID:hostname-50075-1467979678722-3:1:1:1:1
BodyLength           = 1000
size of BodyPreview  = 255

CompositeType        = org.apache.activemq.command.ActiveMQTextMessage
JMSMessageID         = ID:hostname-50075-1467979678722-3:1:1:1:2
Text.length()        = 1000

答案 1 :(得分:1)

我认为当您使用JWX API查询和浏览队列时,ActiveMQ中存在硬编码限制,这是hawtio使用的。但是不记得它是否只有255个字节或更高。

在hawtio设置中查看,可能有一个ActiveMQ插件设置可以更改255个字符,也不记得;)