[hornetq-commits] JBoss hornetq SVN: r9835 - in trunk: src/main/org/hornetq/api/jms/management and 16 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed Nov 3 04:37:12 EDT 2010


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 at 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 at 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 at 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



More information about the hornetq-commits mailing list