Author: igarashitm
Date: 2010-11-03 04:37:11 -0400 (Wed, 03 Nov 2010)
New Revision: 9835
Added:
trunk/src/main/org/hornetq/core/transaction/TransactionDetail.java
trunk/src/main/org/hornetq/core/transaction/impl/CoreTransactionDetail.java
trunk/src/main/org/hornetq/jms/transaction/
trunk/src/main/org/hornetq/jms/transaction/JMSTransactionDetail.java
Modified:
trunk/src/main/org/hornetq/api/core/management/HornetQServerControl.java
trunk/src/main/org/hornetq/api/jms/management/JMSServerControl.java
trunk/src/main/org/hornetq/core/management/impl/HornetQServerControlImpl.java
trunk/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
trunk/src/main/org/hornetq/core/postoffice/impl/DuplicateIDCacheImpl.java
trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
trunk/src/main/org/hornetq/core/server/impl/QueueImpl.java
trunk/src/main/org/hornetq/core/transaction/Transaction.java
trunk/src/main/org/hornetq/core/transaction/TransactionOperation.java
trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java
trunk/src/main/org/hornetq/jms/management/impl/JMSServerControlImpl.java
trunk/src/main/org/hornetq/jms/server/JMSServerManager.java
trunk/src/main/org/hornetq/jms/server/impl/JMSServerManagerImpl.java
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlTest.java
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlUsingJMSTest.java
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlTest.java
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlUsingCoreTest.java
trunk/tests/src/org/hornetq/tests/integration/xa/XaTimeoutTest.java
trunk/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java
Log:
https://jira.jboss.org/browse/HORNETQ-405
Add listPreparedTransactionDetailsAsJSON(), listPreparedTransactionDetailsAsHTML() on
HornetQServerControl and JMSServerControl. You can see transaction ID, message contents,
and some other information about prepared transaction with these method via JMX.
Modified: trunk/src/main/org/hornetq/api/core/management/HornetQServerControl.java
===================================================================
--- trunk/src/main/org/hornetq/api/core/management/HornetQServerControl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/api/core/management/HornetQServerControl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -411,6 +411,20 @@
String[] listPreparedTransactions() throws Exception;
/**
+ * List all the prepared transaction, sorted by date,
+ * oldest first, with details, in text format.
+ */
+ @Operation(desc = "List all the prepared transaction, sorted by date, oldest
first, with details, in JSON format")
+ String listPreparedTransactionDetailsAsJSON() throws Exception;
+
+ /**
+ * List all the prepared transaction, sorted by date,
+ * oldest first, with details, in HTML format
+ */
+ @Operation(desc = "List all the prepared transaction, sorted by date, oldest
first, with details, in HTML format")
+ String listPreparedTransactionDetailsAsHTML() throws Exception;
+
+ /**
* List transactions which have been heuristically committed.
*/
String[] listHeuristicCommittedTransactions() throws Exception;
Modified: trunk/src/main/org/hornetq/api/jms/management/JMSServerControl.java
===================================================================
--- trunk/src/main/org/hornetq/api/jms/management/JMSServerControl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/api/jms/management/JMSServerControl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -234,5 +234,19 @@
@Operation(desc = "List the sessions for the given connectionID", impact =
MBeanOperationInfo.INFO)
String[] listSessions(@Parameter(desc = "a connection ID", name =
"connectionID") String connectionID) throws Exception;
+ /**
+ * List all the prepared transaction, sorted by date,
+ * oldest first, with details, in text format
+ */
+ @Operation(desc = "List all the prepared transaction, sorted by date, oldest
first, with details, in JSON format", impact = MBeanOperationInfo.INFO)
+ String listPreparedTransactionDetailsAsJSON() throws Exception;
+
+ /**
+ * List all the prepared transaction, sorted by date,
+ * oldest first, with details, in HTML format
+ */
+ @Operation(desc = "List all the prepared transaction, sorted by date, oldest
first, with details, in HTML format", impact = MBeanOperationInfo.INFO)
+ String listPreparedTransactionDetailsAsHTML() throws Exception;
+
}
Modified: trunk/src/main/org/hornetq/core/management/impl/HornetQServerControlImpl.java
===================================================================
---
trunk/src/main/org/hornetq/core/management/impl/HornetQServerControlImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/src/main/org/hornetq/core/management/impl/HornetQServerControlImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -20,6 +20,7 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -64,6 +65,8 @@
import org.hornetq.core.settings.impl.AddressSettings;
import org.hornetq.core.transaction.ResourceManager;
import org.hornetq.core.transaction.Transaction;
+import org.hornetq.core.transaction.TransactionDetail;
+import org.hornetq.core.transaction.impl.CoreTransactionDetail;
import org.hornetq.core.transaction.impl.XidImpl;
import org.hornetq.spi.core.protocol.RemotingConnection;
import org.hornetq.utils.SecurityFormatter;
@@ -902,6 +905,134 @@
}
}
+ public String listPreparedTransactionDetailsAsJSON() throws Exception
+ {
+ checkStarted();
+
+ clearIO();
+ try
+ {
+ Map<Xid, Long> xids =
resourceManager.getPreparedTransactionsWithCreationTime();
+ if(xids == null || xids.size()==0)
+ {
+ return "";
+ }
+
+ ArrayList<Entry<Xid, Long>> xidsSortedByCreationTime = new
ArrayList<Map.Entry<Xid, Long>>(xids.entrySet());
+ Collections.sort(xidsSortedByCreationTime, new Comparator<Entry<Xid,
Long>>()
+ {
+ public int compare(final Entry<Xid, Long> entry1, final Entry<Xid,
Long> entry2)
+ {
+ // sort by creation time, oldest first
+ return (int)(entry1.getValue() - entry2.getValue());
+ }
+ });
+
+ JSONArray txDetailListJson = new JSONArray();
+ for (Map.Entry<Xid, Long> entry : xidsSortedByCreationTime)
+ {
+ Xid xid = entry.getKey();
+ TransactionDetail detail = new CoreTransactionDetail(xid,
+
resourceManager.getTransaction(xid),
+ entry.getValue());
+
+ txDetailListJson.put(detail.toJSON());
+ }
+ return txDetailListJson.toString();
+ }
+ finally
+ {
+ blockOnIO();
+ }
+ }
+
+ public String listPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ checkStarted();
+
+ clearIO();
+ try
+ {
+ Map<Xid, Long> xids =
resourceManager.getPreparedTransactionsWithCreationTime();
+ if(xids == null || xids.size() == 0)
+ {
+ return "<h3>*** Prepared Transaction Details
***</h3><p>No entry.</p>";
+ }
+
+ ArrayList<Entry<Xid, Long>> xidsSortedByCreationTime = new
ArrayList<Map.Entry<Xid, Long>>(xids.entrySet());
+ Collections.sort(xidsSortedByCreationTime, new Comparator<Entry<Xid,
Long>>()
+ {
+ public int compare(final Entry<Xid, Long> entry1, final Entry<Xid,
Long> entry2)
+ {
+ // sort by creation time, oldest first
+ return (int)(entry1.getValue() - entry2.getValue());
+ }
+ });
+
+ StringBuilder html = new StringBuilder();
+ html.append("<h3>*** Prepared Transaction Details
***</h3>");
+
+ for (Map.Entry<Xid, Long> entry : xidsSortedByCreationTime)
+ {
+ Xid xid = entry.getKey();
+ TransactionDetail detail = new CoreTransactionDetail(xid,
+
resourceManager.getTransaction(xid),
+ entry.getValue());
+
+ JSONObject txJson = detail.toJSON();
+
+ html.append("<table border=\"1\">");
+ html.append("<tr><th>creation_time</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_CREATION_TIME) + "</td>");
+ html.append("<th>xid_as_base_64</th>");
+ html.append("<td colspan=\"3\">" +
txJson.get(TransactionDetail.KEY_XID_AS_BASE64) + "</td></tr>");
+ html.append("<tr><th>xid_format_id</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_FORMAT_ID) + "</td>");
+ html.append("<th>xid_global_txid</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_GLOBAL_TXID) + "</td>");
+ html.append("<th>xid_branch_qual</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_BRANCH_QUAL) + "</td></tr>");
+
+ html.append("<tr><th colspan=\"6\">Message
List</th></tr>");
+ html.append("<tr><td colspan=\"6\">");
+ html.append("<table border=\"1\"
cellspacing=\"0\" cellpadding=\"0\">");
+
+ JSONArray msgs =
txJson.getJSONArray(TransactionDetail.KEY_TX_RELATED_MESSAGES);
+ for(int i=0; i<msgs.length(); i++)
+ {
+ JSONObject msgJson = msgs.getJSONObject(i);
+ JSONObject props =
msgJson.getJSONObject(TransactionDetail.KEY_MSG_PROPERTIES);
+ StringBuilder propstr = new StringBuilder();
+ @SuppressWarnings("unchecked")
+ Iterator<String> propkeys = props.keys();
+ while(propkeys.hasNext())
+ {
+ String key = propkeys.next();
+ propstr.append(key);
+ propstr.append("=");
+ propstr.append(props.get(key));
+ propstr.append(", ");
+ }
+
+ html.append("<th>operation_type</th>");
+ html.append("<td>" +
msgJson.get(TransactionDetail.KEY_MSG_OP_TYPE) + "</th>");
+ html.append("<th>message_type</th>");
+ html.append("<td>" +
msgJson.get(TransactionDetail.KEY_MSG_TYPE) + "</td></tr>");
+ html.append("<tr><th>properties</th>");
+ html.append("<td colspan=\"3\">" +
propstr.toString() + "</td></tr>");
+ }
+ html.append("</table></td></tr>");
+ html.append("</table><br/>");
+ }
+
+ return html.toString();
+ }
+ finally
+ {
+ blockOnIO();
+ }
+ }
+
public String[] listHeuristicCommittedTransactions()
{
checkStarted();
Modified: trunk/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -13,6 +13,7 @@
package org.hornetq.core.paging.impl;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -22,6 +23,7 @@
import org.hornetq.core.paging.PageTransactionInfo;
import org.hornetq.core.paging.PagingManager;
import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.core.server.MessageReference;
import org.hornetq.core.transaction.Transaction;
import org.hornetq.core.transaction.TransactionOperation;
import org.hornetq.utils.DataConstants;
@@ -196,6 +198,11 @@
{
pgToUpdate.update(depages, storageManager, pagingManager);
}
+
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
});
}
Modified:
trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
===================================================================
---
trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -2068,6 +2068,10 @@
return DataConstants.SIZE_LONG + DataConstants.SIZE_INT;
}
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
}
private static class ScheduledDeliveryEncoding extends QueueEncoding
@@ -2191,6 +2195,11 @@
{
}
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
+
}
private static final class AddMessageRecord
Modified: trunk/src/main/org/hornetq/core/postoffice/impl/DuplicateIDCacheImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/postoffice/impl/DuplicateIDCacheImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/core/postoffice/impl/DuplicateIDCacheImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -25,6 +25,7 @@
import org.hornetq.core.logging.Logger;
import org.hornetq.core.persistence.StorageManager;
import org.hornetq.core.postoffice.DuplicateIDCache;
+import org.hornetq.core.server.MessageReference;
import org.hornetq.core.server.Queue;
import org.hornetq.core.transaction.Transaction;
import org.hornetq.core.transaction.TransactionOperation;
@@ -298,6 +299,11 @@
{
}
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
+
/* (non-Javadoc)
* @see org.hornetq.core.transaction.TransactionOperation#getDistinctQueues()
*/
Modified: trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -1212,6 +1212,11 @@
}
}
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
+
private void pageMessages(final Transaction tx) throws Exception
{
if (!pagingData.isEmpty())
@@ -1341,6 +1346,11 @@
message.decrementRefCount();
}
}
+
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return refs;
+ }
}
public Bindings createBindings()
Modified: trunk/src/main/org/hornetq/core/server/impl/QueueImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-03 03:13:23 UTC
(rev 9834)
+++ trunk/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-03 08:37:11 UTC
(rev 9835)
@@ -1636,6 +1636,10 @@
public void beforeRollback(final Transaction tx) throws Exception
{
}
+
+ public List<MessageReference> getRelatedMessageReferences() {
+ return refsToAck;
+ }
}
private class DelayedAddRedistributor implements Runnable
Modified: trunk/src/main/org/hornetq/core/transaction/Transaction.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/Transaction.java 2010-11-03 03:13:23 UTC
(rev 9834)
+++ trunk/src/main/org/hornetq/core/transaction/Transaction.java 2010-11-03 08:37:11 UTC
(rev 9835)
@@ -13,6 +13,8 @@
package org.hornetq.core.transaction;
+import java.util.List;
+
import javax.transaction.xa.Xid;
import org.hornetq.api.core.HornetQException;
@@ -59,6 +61,8 @@
void removeOperation(TransactionOperation sync);
+ public List<TransactionOperation> getAllOperations();
+
boolean hasTimedOut(long currentTime, int defaultTimeout);
/** We don't want to look on operations at every send, so we keep the paging
attribute and will only look at
Added: trunk/src/main/org/hornetq/core/transaction/TransactionDetail.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/TransactionDetail.java
(rev 0)
+++ trunk/src/main/org/hornetq/core/transaction/TransactionDetail.java 2010-11-03 08:37:11
UTC (rev 9835)
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat 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.hornetq.core.transaction;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.transaction.xa.Xid;
+
+import org.hornetq.core.server.MessageReference;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.impl.XidImpl;
+import org.hornetq.utils.json.JSONArray;
+import org.hornetq.utils.json.JSONObject;
+
+/**
+ * A TransactionDetail
+ *
+ * @author <a href="tm.igarashi(a)gmail.com">Tomohisa Igarashi</a>
+ */
+public abstract class TransactionDetail
+{
+ public static final String KEY_CREATION_TIME = "creation_time";
+
+ public static final String KEY_XID_AS_BASE64 = "xid_as_base64";
+
+ public static final String KEY_XID_FORMAT_ID = "xid_format_id";
+
+ public static final String KEY_XID_GLOBAL_TXID = "xid_global_txid";
+
+ public static final String KEY_XID_BRANCH_QUAL = "xid_branch_qual";
+
+ public static final String KEY_TX_RELATED_MESSAGES = "tx_related_messages";
+
+ public static final String KEY_MSG_OP_TYPE = "message_operation_type";
+
+ public static final String KEY_MSG_BODY_BUFFER = "message_body";
+
+ public static final String KEY_MSG_TYPE = "message_type";
+
+ public static final String KEY_MSG_PROPERTIES = "message_properties";
+
+ public static final String KEY_MSG_PAYLOAD = "message_payload";
+
+ private Xid xid;
+ private Transaction transaction;
+ private Long creationTime;
+
+ public TransactionDetail(Xid xid, Transaction tx, Long creation)
+ {
+ this.xid = xid;
+ this.transaction = tx;
+ this.creationTime = creation;
+ }
+
+ public JSONObject toJSON() throws Exception
+ {
+ DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.MEDIUM);
+ JSONObject detailJson = new JSONObject();
+
+ detailJson.put(KEY_CREATION_TIME, dateFormat.format(new Date(this.creationTime)));
+ detailJson.put(KEY_XID_AS_BASE64, XidImpl.toBase64String(this.xid));
+ detailJson.put(KEY_XID_FORMAT_ID, this.xid.getFormatId());
+ detailJson.put(KEY_XID_GLOBAL_TXID, new
String(this.xid.getGlobalTransactionId()));
+ detailJson.put(KEY_XID_BRANCH_QUAL, new String(this.xid.getBranchQualifier()));
+
+ JSONArray msgsJson = new JSONArray();
+ List<TransactionOperation> txops = this.transaction.getAllOperations();
+ detailJson.put(KEY_TX_RELATED_MESSAGES, msgsJson);
+ if (txops == null)
+ {
+ return detailJson;
+ }
+
+ for (TransactionOperation op : txops)
+ {
+ String opClassName = op.getClass().getName();
+ String opType = null;
+ if
(opClassName.equals("org.hornetq.core.postoffice.impl.PostOfficeImpl$AddOperation"))
+ {
+ opType = "(+) send";
+ }
+ else if
(opClassName.equals("org.hornetq.core.server.impl.QueueImpl$RefsOperation"))
+ {
+ opType = "(-) receive";
+ }
+
+ List<MessageReference> msgs = op.getRelatedMessageReferences();
+ if (msgs == null)
+ {
+ continue;
+ }
+
+ for (MessageReference ref : msgs)
+ {
+ JSONObject msgJson = new JSONObject();
+ msgsJson.put(msgJson);
+
+ msgJson.put(KEY_MSG_OP_TYPE, opType);
+
+ ServerMessage msg = ref.getMessage().copy();
+
+ msgJson.put(KEY_MSG_TYPE, decodeMessageType(msg));
+ msgJson.put(KEY_MSG_PAYLOAD, decodeMessagePayload(msg));
+ msgJson.put(KEY_MSG_PROPERTIES, decodeMessageProperties(msg));
+ }
+ }
+ return detailJson;
+ }
+
+ public abstract String decodeMessageType(ServerMessage msg);
+
+ public abstract String decodeMessagePayload(ServerMessage msg);
+
+ public abstract Map<String,Object> decodeMessageProperties(ServerMessage msg);
+}
Property changes on: trunk/src/main/org/hornetq/core/transaction/TransactionDetail.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/src/main/org/hornetq/core/transaction/TransactionOperation.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/TransactionOperation.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/core/transaction/TransactionOperation.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -13,6 +13,10 @@
package org.hornetq.core.transaction;
+import java.util.List;
+
+import org.hornetq.core.server.MessageReference;
+
/**
*
* A TransactionOperation
@@ -36,4 +40,6 @@
/** After rollback shouldn't throw any exception. Any verification has to be done
on before rollback */
void afterRollback(Transaction tx);
+
+ List<MessageReference> getRelatedMessageReferences();
}
Added: trunk/src/main/org/hornetq/core/transaction/impl/CoreTransactionDetail.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/impl/CoreTransactionDetail.java
(rev 0)
+++ trunk/src/main/org/hornetq/core/transaction/impl/CoreTransactionDetail.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat 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.hornetq.core.transaction.impl;
+
+import java.util.Map;
+
+import javax.transaction.xa.Xid;
+
+import org.hornetq.api.core.Message;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.Transaction;
+import org.hornetq.core.transaction.TransactionDetail;
+
+/**
+ * A CoreTransactionDetail
+ *
+ * @author <a href="tm.igarashi(a)gmail.com">Tomohisa Igarashi</a>
+ *
+ *
+ */
+public class CoreTransactionDetail extends TransactionDetail
+{
+ public CoreTransactionDetail(Xid xid, Transaction tx, Long creation) throws Exception
+ {
+ super(xid,tx,creation);
+ }
+
+ @Override
+ public String decodeMessageType(ServerMessage msg)
+ {
+ int type = msg.getType();
+ switch (type)
+ {
+ case Message.DEFAULT_TYPE: // 0
+ return "Default";
+ case Message.OBJECT_TYPE: // 2
+ return "ObjectMessage";
+ case Message.TEXT_TYPE: // 3
+ return "TextMessage";
+ case Message.BYTES_TYPE: // 4
+ return "ByteMessage";
+ case Message.MAP_TYPE: // 5
+ return "MapMessage";
+ case Message.STREAM_TYPE: // 6
+ return "StreamMessage";
+ default:
+ return "(Unknown Type)";
+ }
+ }
+
+ @Override
+ public String decodeMessagePayload(ServerMessage msg)
+ {
+ return msg.getBodyBuffer().toByteBuffer().toString();
+ }
+
+ @Override
+ public Map<String, Object> decodeMessageProperties(ServerMessage msg)
+ {
+ return msg.toMap();
+ }
+}
Property changes on:
trunk/src/main/org/hornetq/core/transaction/impl/CoreTransactionDetail.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -401,6 +401,10 @@
return operations.size();
}
+ public List<TransactionOperation> getAllOperations() {
+ return operations;
+ }
+
public void putProperty(final int index, final Object property)
{
if (index >= properties.length)
Modified: trunk/src/main/org/hornetq/jms/management/impl/JMSServerControlImpl.java
===================================================================
--- trunk/src/main/org/hornetq/jms/management/impl/JMSServerControlImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/jms/management/impl/JMSServerControlImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -31,7 +31,6 @@
import org.hornetq.api.core.Pair;
import org.hornetq.api.core.TransportConfiguration;
import org.hornetq.api.core.management.ManagementHelper;
-import org.hornetq.api.core.management.Parameter;
import org.hornetq.api.jms.management.ConnectionFactoryControl;
import org.hornetq.api.jms.management.JMSQueueControl;
import org.hornetq.api.jms.management.JMSServerControl;
@@ -700,6 +699,38 @@
}
}
+ public String listPreparedTransactionDetailsAsJSON() throws Exception
+ {
+ checkStarted();
+
+ clearIO();
+
+ try
+ {
+ return server.listPreparedTransactionDetailsAsJSON();
+ }
+ finally
+ {
+ blockOnIO();
+ }
+ }
+
+ public String listPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ checkStarted();
+
+ clearIO();
+
+ try
+ {
+ return server.listPreparedTransactionDetailsAsHTML();
+ }
+ finally
+ {
+ blockOnIO();
+ }
+ }
+
@Override
public MBeanInfo getMBeanInfo()
{
Modified: trunk/src/main/org/hornetq/jms/server/JMSServerManager.java
===================================================================
--- trunk/src/main/org/hornetq/jms/server/JMSServerManager.java 2010-11-03 03:13:23 UTC
(rev 9834)
+++ trunk/src/main/org/hornetq/jms/server/JMSServerManager.java 2010-11-03 08:37:11 UTC
(rev 9835)
@@ -286,6 +286,10 @@
String[] listSessions(String connectionID) throws Exception;
+ String listPreparedTransactionDetailsAsJSON() throws Exception;
+
+ String listPreparedTransactionDetailsAsHTML() throws Exception;
+
void setContext(final Context context);
HornetQServer getHornetQServer();
Modified: trunk/src/main/org/hornetq/jms/server/impl/JMSServerManagerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/jms/server/impl/JMSServerManagerImpl.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/src/main/org/hornetq/jms/server/impl/JMSServerManagerImpl.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -14,16 +14,20 @@
package org.hornetq.jms.server.impl;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
+import javax.transaction.xa.Xid;
import org.hornetq.api.core.HornetQException;
import org.hornetq.api.core.Pair;
@@ -45,6 +49,8 @@
import org.hornetq.core.server.ActivateCallback;
import org.hornetq.core.server.HornetQServer;
import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.core.transaction.ResourceManager;
+import org.hornetq.core.transaction.TransactionDetail;
import org.hornetq.jms.client.HornetQConnectionFactory;
import org.hornetq.jms.client.HornetQDestination;
import org.hornetq.jms.client.HornetQQueue;
@@ -65,8 +71,11 @@
import org.hornetq.jms.server.config.impl.ConnectionFactoryConfigurationImpl;
import org.hornetq.jms.server.management.JMSManagementService;
import org.hornetq.jms.server.management.impl.JMSManagementServiceImpl;
+import org.hornetq.jms.transaction.JMSTransactionDetail;
import org.hornetq.spi.core.naming.BindingRegistry;
import org.hornetq.utils.TimeAndCounterIDGenerator;
+import org.hornetq.utils.json.JSONArray;
+import org.hornetq.utils.json.JSONObject;
/**
* A Deployer used to create and add to JNDI queues, topics and connection
@@ -1372,7 +1381,117 @@
checkInitialised();
return server.getHornetQServerControl().listSessions(connectionID);
}
+
+ public String listPreparedTransactionDetailsAsJSON() throws Exception
+ {
+ ResourceManager resourceManager = server.getResourceManager();
+ Map<Xid, Long> xids =
resourceManager.getPreparedTransactionsWithCreationTime();
+ if(xids == null || xids.size()==0)
+ {
+ return "";
+ }
+
+ ArrayList<Entry<Xid, Long>> xidsSortedByCreationTime = new
ArrayList<Map.Entry<Xid, Long>>(xids.entrySet());
+ Collections.sort(xidsSortedByCreationTime, new Comparator<Entry<Xid,
Long>>()
+ {
+ public int compare(final Entry<Xid, Long> entry1, final Entry<Xid,
Long> entry2)
+ {
+ // sort by creation time, oldest first
+ return (int)(entry1.getValue() - entry2.getValue());
+ }
+ });
+
+ JSONArray txDetailListJson = new JSONArray();
+ for (Map.Entry<Xid, Long> entry : xidsSortedByCreationTime)
+ {
+ Xid xid = entry.getKey();
+ TransactionDetail detail = new JMSTransactionDetail(xid,
+
resourceManager.getTransaction(xid),
+ entry.getValue());
+ txDetailListJson.put(detail.toJSON());
+ }
+ return txDetailListJson.toString();
+ }
+
+ public String listPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ ResourceManager resourceManager = server.getResourceManager();
+ Map<Xid, Long> xids =
resourceManager.getPreparedTransactionsWithCreationTime();
+ if(xids == null || xids.size() == 0)
+ {
+ return "<h3>*** Prepared Transaction Details
***</h3><p>No entry.</p>";
+ }
+ ArrayList<Entry<Xid, Long>> xidsSortedByCreationTime = new
ArrayList<Map.Entry<Xid, Long>>(xids.entrySet());
+ Collections.sort(xidsSortedByCreationTime, new Comparator<Entry<Xid,
Long>>()
+ {
+ public int compare(final Entry<Xid, Long> entry1, final Entry<Xid,
Long> entry2)
+ {
+ // sort by creation time, oldest first
+ return (int)(entry1.getValue() - entry2.getValue());
+ }
+ });
+
+ StringBuilder html = new StringBuilder();
+ html.append("<h3>*** Prepared Transaction Details
***</h3>");
+
+ for (Map.Entry<Xid, Long> entry : xidsSortedByCreationTime)
+ {
+ Xid xid = entry.getKey();
+ TransactionDetail detail = new JMSTransactionDetail(xid,
+
resourceManager.getTransaction(xid),
+ entry.getValue());
+ JSONObject txJson = detail.toJSON();
+
+ html.append("<table border=\"1\">");
+ html.append("<tr><th>creation_time</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_CREATION_TIME) + "</td>");
+ html.append("<th>xid_as_base_64</th>");
+ html.append("<td colspan=\"3\">" +
txJson.get(TransactionDetail.KEY_XID_AS_BASE64) + "</td></tr>");
+ html.append("<tr><th>xid_format_id</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_FORMAT_ID) + "</td>");
+ html.append("<th>xid_global_txid</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_GLOBAL_TXID) + "</td>");
+ html.append("<th>xid_branch_qual</th>");
+ html.append("<td>" +
txJson.get(TransactionDetail.KEY_XID_BRANCH_QUAL) + "</td></tr>");
+
+ html.append("<tr><th colspan=\"6\">Message
List</th></tr>");
+ html.append("<tr><td colspan=\"6\">");
+ html.append("<table border=\"1\" cellspacing=\"0\"
cellpadding=\"0\">");
+
+ JSONArray msgs =
txJson.getJSONArray(TransactionDetail.KEY_TX_RELATED_MESSAGES);
+ for(int i=0; i<msgs.length(); i++)
+ {
+ JSONObject msgJson = msgs.getJSONObject(i);
+ JSONObject props =
msgJson.getJSONObject(TransactionDetail.KEY_MSG_PROPERTIES);
+ StringBuilder propstr = new StringBuilder();
+ @SuppressWarnings("unchecked")
+ Iterator<String> propkeys = props.keys();
+ while(propkeys.hasNext())
+ {
+ String key = propkeys.next();
+ propstr.append(key);
+ propstr.append("=");
+ propstr.append(props.get(key));
+ propstr.append(", ");
+ }
+
+ html.append("<th>operation_type</th>");
+ html.append("<td>" +
msgJson.get(TransactionDetail.KEY_MSG_OP_TYPE) + "</th>");
+ html.append("<th>message_type</th>");
+ html.append("<td>" +
msgJson.get(TransactionDetail.KEY_MSG_TYPE) + "</td></tr>");
+ html.append("<tr><th>properties</th>");
+ html.append("<td colspan=\"3\">" +
propstr.toString() + "</td></tr>");
+ html.append("<tr><th
colspan=\"4\">payload</th></tr>");
+ html.append("<tr><td colspan=\"4\">" +
msgJson.get(TransactionDetail.KEY_MSG_PAYLOAD) + "</td></tr>");
+ }
+ html.append("</table></td></tr>");
+ html.append("</table><br/>");
+ }
+
+ return html.toString();
+ }
+
// Public --------------------------------------------------------
// Private -------------------------------------------------------
Added: trunk/src/main/org/hornetq/jms/transaction/JMSTransactionDetail.java
===================================================================
--- trunk/src/main/org/hornetq/jms/transaction/JMSTransactionDetail.java
(rev 0)
+++ trunk/src/main/org/hornetq/jms/transaction/JMSTransactionDetail.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat 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.hornetq.jms.transaction;
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.Map;
+
+import javax.transaction.xa.Xid;
+
+import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.Transaction;
+import org.hornetq.core.transaction.TransactionDetail;
+import org.hornetq.jms.client.HornetQBytesMessage;
+import org.hornetq.jms.client.HornetQMapMessage;
+import org.hornetq.jms.client.HornetQMessage;
+import org.hornetq.jms.client.HornetQObjectMessage;
+import org.hornetq.jms.client.HornetQStreamMessage;
+import org.hornetq.jms.client.HornetQTextMessage;
+import org.hornetq.utils.TypedProperties;
+
+/**
+ * A JMSTransactionDetail
+ *
+ * @author <a href="tm.igarashi(a)gmail.com">Tomohisa Igarashi</a>
+ *
+ *
+ */
+public class JMSTransactionDetail extends TransactionDetail
+{
+ public JMSTransactionDetail(Xid xid, Transaction tx, Long creation) throws Exception
+ {
+ super(xid,tx,creation);
+ }
+
+ @Override
+ public String decodeMessageType(ServerMessage msg)
+ {
+ int type = msg.getType();
+ switch (type)
+ {
+ case HornetQMessage.TYPE: // 0
+ return "Default";
+ case HornetQObjectMessage.TYPE: // 2
+ return "ObjectMessage";
+ case HornetQTextMessage.TYPE: // 3
+ return "TextMessage";
+ case HornetQBytesMessage.TYPE: // 4
+ return "ByteMessage";
+ case HornetQMapMessage.TYPE: // 5
+ return "MapMessage";
+ case HornetQStreamMessage.TYPE: // 6
+ return "StreamMessage";
+ default:
+ return "(Unknown Type)";
+ }
+ }
+
+ @Override
+ public String decodeMessagePayload(ServerMessage msg)
+ {
+ int type = msg.getType();
+ HornetQBuffer bodyBuffer = msg.getBodyBuffer();
+
+ try
+ {
+ switch (type)
+ {
+ case HornetQObjectMessage.TYPE: // 2
+ int len = bodyBuffer.readInt();
+ byte[] data = new byte[len];
+ bodyBuffer.readBytes(data);
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new
org.hornetq.utils.ObjectInputStreamWithClassLoader(bais);
+ Serializable object = (Serializable)ois.readObject();
+ return object.toString();
+
+ case HornetQTextMessage.TYPE: // 3
+ return bodyBuffer.readNullableSimpleString().toString();
+
+ case HornetQMapMessage.TYPE: // 5
+ TypedProperties pmap = new TypedProperties();
+ pmap.decode(msg.getBodyBuffer());
+ return pmap.toString();
+ default:
+ return "(Not Available)";
+ }
+ }
+ catch(Throwable t)
+ {
+ return "(Not Available)";
+ }
+ }
+
+ @Override
+ public Map<String, Object> decodeMessageProperties(ServerMessage msg)
+ {
+ try
+ {
+ return HornetQMessage.coreMaptoJMSMap(msg.toMap());
+ }
+ catch (Throwable t)
+ {
+ return null;
+ }
+ }
+}
Property changes on: trunk/src/main/org/hornetq/jms/transaction/JMSTransactionDetail.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlTest.java
===================================================================
---
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -23,9 +23,15 @@
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
+import javax.jms.TextMessage;
import javax.jms.Topic;
+import javax.jms.XASession;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
import junit.framework.Assert;
@@ -46,6 +52,7 @@
import org.hornetq.core.replication.ReplicationEndpoint;
import org.hornetq.core.server.HornetQServer;
import org.hornetq.core.server.HornetQServers;
+import org.hornetq.jms.client.HornetQConnection;
import org.hornetq.jms.client.HornetQConnectionFactory;
import org.hornetq.jms.client.HornetQDestination;
import org.hornetq.jms.persistence.JMSStorageManager;
@@ -450,7 +457,98 @@
}
});
}
+
+ public void testListPreparedTransactionDetails() throws Exception
+ {
+ Xid xid = newXID();
+ JMSServerControl control = createManagementControl();
+ TransportConfiguration tc = new
TransportConfiguration(InVMConnectorFactory.class.getName());
+ String cfJNDIBinding = "/cf";
+ String cfName = "cf";
+
+ control.createConnectionFactory(cfName,
+ tc.getFactoryClassName(),
+ null,
+ tc.getFactoryClassName(),
+ null,
+ cfJNDIBinding);
+ control.createQueue("q","/q");
+
+ ConnectionFactory cf = (ConnectionFactory)context.lookup("/cf");
+ Destination dest = (Destination)context.lookup("/q");
+ HornetQConnection conn = (HornetQConnection)cf.createConnection();
+ XASession ss = conn.createXASession();
+ TextMessage m1 = ss.createTextMessage("m1");
+ TextMessage m2 = ss.createTextMessage("m2");
+ TextMessage m3 = ss.createTextMessage("m3");
+ TextMessage m4 = ss.createTextMessage("m4");
+ MessageProducer mp = ss.createProducer(dest);
+ XAResource xa = ss.getXAResource();
+ xa.start(xid, XAResource.TMNOFLAGS);
+ mp.send(m1);
+ mp.send(m2);
+ mp.send(m3);
+ mp.send(m4);
+ xa.end(xid, XAResource.TMSUCCESS);
+ xa.prepare(xid);
+
+ ss.close();
+
+ String txDetails = control.listPreparedTransactionDetailsAsJSON();
+
+ Assert.assertTrue(txDetails.matches(".*m1.*"));
+ Assert.assertTrue(txDetails.matches(".*m2.*"));
+ Assert.assertTrue(txDetails.matches(".*m3.*"));
+ Assert.assertTrue(txDetails.matches(".*m4.*"));
+ }
+
+ public void testListPreparedTranscationDetailsAsHTML() throws Exception
+ {
+ Xid xid = newXID();
+
+ JMSServerControl control = createManagementControl();
+ TransportConfiguration tc = new
TransportConfiguration(InVMConnectorFactory.class.getName());
+ String cfJNDIBinding = "/cf";
+ String cfName = "cf";
+
+ control.createConnectionFactory(cfName,
+ tc.getFactoryClassName(),
+ null,
+ tc.getFactoryClassName(),
+ null,
+ cfJNDIBinding);
+ control.createQueue("q","/q");
+
+ ConnectionFactory cf = (ConnectionFactory)context.lookup("/cf");
+ Destination dest = (Destination)context.lookup("/q");
+ HornetQConnection conn = (HornetQConnection)cf.createConnection();
+ XASession ss = conn.createXASession();
+ TextMessage m1 = ss.createTextMessage("m1");
+ TextMessage m2 = ss.createTextMessage("m2");
+ TextMessage m3 = ss.createTextMessage("m3");
+ TextMessage m4 = ss.createTextMessage("m4");
+ MessageProducer mp = ss.createProducer(dest);
+ XAResource xa = ss.getXAResource();
+ xa.start(xid, XAResource.TMNOFLAGS);
+ mp.send(m1);
+ mp.send(m2);
+ mp.send(m3);
+ mp.send(m4);
+ xa.end(xid, XAResource.TMSUCCESS);
+ xa.prepare(xid);
+
+ ss.close();
+
+ String html = control.listPreparedTransactionDetailsAsHTML();
+
+ Assert.assertTrue(html.matches(".*m1.*"));
+ Assert.assertTrue(html.matches(".*m2.*"));
+ Assert.assertTrue(html.matches(".*m3.*"));
+ Assert.assertTrue(html.matches(".*m4.*"));
+
+ }
+
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
Modified:
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlUsingJMSTest.java
===================================================================
---
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlUsingJMSTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/tests/src/org/hornetq/tests/integration/jms/server/management/JMSServerControlUsingJMSTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -275,6 +275,16 @@
return (Boolean)proxy.invokeOperation("createTopic", name,
jndiBinding);
}
+ public String listPreparedTransactionDetailsAsJSON() throws Exception
+ {
+ return
(String)proxy.invokeOperation("listPreparedTransactionDetailsAsJSON");
+ }
+
+ public String listPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ return
(String)proxy.invokeOperation("listPreparedTransactionDetailsAsHTML");
+ }
+
};
}
// Public --------------------------------------------------------
Modified:
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlTest.java
===================================================================
---
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -16,6 +16,9 @@
import java.util.HashMap;
import java.util.Map;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
import junit.framework.Assert;
import org.hornetq.api.core.SimpleString;
@@ -41,7 +44,9 @@
import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory;
import org.hornetq.core.server.HornetQServer;
import org.hornetq.core.server.HornetQServers;
+import org.hornetq.core.transaction.impl.XidImpl;
import org.hornetq.tests.util.RandomUtil;
+import org.hornetq.utils.UUIDGenerator;
import org.hornetq.utils.json.JSONArray;
import org.hornetq.utils.json.JSONObject;
@@ -671,6 +676,80 @@
session.close();
}
+ public void testListPreparedTransactionDetails() throws Exception
+ {
+ SimpleString atestq = new SimpleString("BasicXaTestq");
+ Xid xid = newXID();
+
+ ClientSessionFactory csf = HornetQClient.createClientSessionFactory(new
TransportConfiguration(InVMConnectorFactory.class.getCanonicalName()));
+ ClientSession clientSession = csf.createSession(true, false, false);
+ clientSession.createQueue(atestq, atestq, null, true);
+
+ ClientMessage m1 = createTextMessage(clientSession, "");
+ ClientMessage m2 = createTextMessage(clientSession, "");
+ ClientMessage m3 = createTextMessage(clientSession, "");
+ ClientMessage m4 = createTextMessage(clientSession, "");
+ m1.putStringProperty("m1", "m1");
+ m2.putStringProperty("m2", "m2");
+ m3.putStringProperty("m3", "m3");
+ m4.putStringProperty("m4", "m4");
+ ClientProducer clientProducer = clientSession.createProducer(atestq);
+ clientSession.start(xid, XAResource.TMNOFLAGS);
+ clientProducer.send(m1);
+ clientProducer.send(m2);
+ clientProducer.send(m3);
+ clientProducer.send(m4);
+ clientSession.end(xid, XAResource.TMSUCCESS);
+ clientSession.prepare(xid);
+
+ clientSession.close();
+
+ HornetQServerControl serverControl = createManagementControl();
+ String txDetails = serverControl.listPreparedTransactionDetailsAsJSON();
+
+ Assert.assertTrue(txDetails.matches(".*m1.*"));
+ Assert.assertTrue(txDetails.matches(".*m2.*"));
+ Assert.assertTrue(txDetails.matches(".*m3.*"));
+ Assert.assertTrue(txDetails.matches(".*m4.*"));
+ }
+
+ public void testListPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ SimpleString atestq = new SimpleString("BasicXaTestq");
+ Xid xid = newXID();
+
+ ClientSessionFactory csf = HornetQClient.createClientSessionFactory(new
TransportConfiguration(InVMConnectorFactory.class.getCanonicalName()));
+ ClientSession clientSession = csf.createSession(true, false, false);
+ clientSession.createQueue(atestq, atestq, null, true);
+
+ ClientMessage m1 = createTextMessage(clientSession, "");
+ ClientMessage m2 = createTextMessage(clientSession, "");
+ ClientMessage m3 = createTextMessage(clientSession, "");
+ ClientMessage m4 = createTextMessage(clientSession, "");
+ m1.putStringProperty("m1", "m1");
+ m2.putStringProperty("m2", "m2");
+ m3.putStringProperty("m3", "m3");
+ m4.putStringProperty("m4", "m4");
+ ClientProducer clientProducer = clientSession.createProducer(atestq);
+ clientSession.start(xid, XAResource.TMNOFLAGS);
+ clientProducer.send(m1);
+ clientProducer.send(m2);
+ clientProducer.send(m3);
+ clientProducer.send(m4);
+ clientSession.end(xid, XAResource.TMSUCCESS);
+ clientSession.prepare(xid);
+
+ clientSession.close();
+
+ HornetQServerControl serverControl = createManagementControl();
+ String html = serverControl.listPreparedTransactionDetailsAsHTML();
+
+ Assert.assertTrue(html.matches(".*m1.*"));
+ Assert.assertTrue(html.matches(".*m2.*"));
+ Assert.assertTrue(html.matches(".*m3.*"));
+ Assert.assertTrue(html.matches(".*m4.*"));
+ }
+
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
Modified:
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlUsingCoreTest.java
===================================================================
---
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlUsingCoreTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/tests/src/org/hornetq/tests/integration/management/HornetQServerControlUsingCoreTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -383,6 +383,16 @@
return
(String[])proxy.invokeOperation("listPreparedTransactions");
}
+ public String listPreparedTransactionDetailsAsJSON() throws Exception
+ {
+ return
(String)proxy.invokeOperation("listPreparedTransactionDetailsAsJSON");
+ }
+
+ public String listPreparedTransactionDetailsAsHTML() throws Exception
+ {
+ return
(String)proxy.invokeOperation("listPreparedTransactionDetailsAsHTML");
+ }
+
public String[] listHeuristicCommittedTransactions() throws Exception
{
return
(String[])proxy.invokeOperation("listHeuristicCommittedTransactions");
Modified: trunk/tests/src/org/hornetq/tests/integration/xa/XaTimeoutTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/xa/XaTimeoutTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++ trunk/tests/src/org/hornetq/tests/integration/xa/XaTimeoutTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -15,6 +15,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -32,6 +33,7 @@
import org.hornetq.core.config.impl.ConfigurationImpl;
import org.hornetq.core.server.HornetQServer;
import org.hornetq.core.server.HornetQServers;
+import org.hornetq.core.server.MessageReference;
import org.hornetq.core.server.Queue;
import org.hornetq.core.settings.impl.AddressSettings;
import org.hornetq.core.transaction.Transaction;
@@ -545,5 +547,10 @@
{
return Collections.emptySet();
}
+
+ public List<MessageReference> getRelatedMessageReferences()
+ {
+ return null;
+ }
}
}
Modified:
trunk/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java
===================================================================
---
trunk/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java 2010-11-03
03:13:23 UTC (rev 9834)
+++
trunk/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java 2010-11-03
08:37:11 UTC (rev 9835)
@@ -15,6 +15,7 @@
import java.io.InputStream;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -348,6 +349,14 @@
return false;
}
+ /* (non-Javadoc)
+ * @see org.hornetq.core.transaction.Transaction#getAllOperations()
+ */
+ public List<TransactionOperation> getAllOperations()
+ {
+ return null;
+ }
+
}
class FakeMessage implements ServerMessage