This is an automated email from the ASF dual-hosted git repository.

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit 0847b463b37b60b177a95d677b808da08d10e14f
Author: Robert Lazarski <[email protected]>
AuthorDate: Mon Apr 20 11:36:34 2026 -1000

    AXIS2-5881 Sort services and operations in listServices.jsp
    
    Sort services alphabetically (case-insensitive) by passing a TreeMap
    from ListingAgent.processListServices() as a request attribute, per
    Andreas Veithen's recommendation to sort in Java code rather than
    adding more Java to the JSP.
    
    Sort operations alphabetically by name within each service.
    
    Based on the original patch by Jeff Thomas (JWT007) from 2017.
---
 .../java/org/apache/axis2/transport/http/ListingAgent.java | 14 ++++++++++++++
 .../webapp/src/main/webapp/WEB-INF/views/listServices.jsp  |  9 +++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
index 448740a059..2ca25eefd0 100644
--- 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
+++ 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
@@ -356,6 +356,20 @@ public class ListingAgent extends AbstractAgent {
            return;
         }
         populateRequestAttributes(req);
+        // AXIS2-5881: Sort services alphabetically by name for the listing 
page.
+        // Take a snapshot via putAll to avoid ConcurrentModificationException
+        // if services are deployed/undeployed during iteration (hot 
deployment).
+        java.util.TreeMap<String, AxisService> sortedServices = new 
java.util.TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        try {
+            java.util.Map<String, AxisService> services = 
configContext.getAxisConfiguration().getServices();
+            if (services != null) {
+                sortedServices.putAll(services);
+            }
+        } catch (java.util.ConcurrentModificationException e) {
+            // Hot deployment race — use whatever we captured so far
+            log.debug("ConcurrentModificationException while listing services, 
displaying partial list", e);
+        }
+        req.setAttribute("sortedServices", sortedServices);
         req.setAttribute(Constants.ERROR_SERVICE_MAP,
                 configContext.getAxisConfiguration().getFaultyServices());
         renderView(LIST_MULTIPLE_SERVICE_JSP_NAME, req, res);
diff --git a/modules/webapp/src/main/webapp/WEB-INF/views/listServices.jsp 
b/modules/webapp/src/main/webapp/WEB-INF/views/listServices.jsp
index fb8664a3e2..b47b5912f1 100644
--- a/modules/webapp/src/main/webapp/WEB-INF/views/listServices.jsp
+++ b/modules/webapp/src/main/webapp/WEB-INF/views/listServices.jsp
@@ -47,11 +47,16 @@
     Hashtable errornessservice = (Hashtable) 
request.getAttribute(Constants.ERROR_SERVICE_MAP);
     boolean status = false;
 %>
-<c:forEach var="service" 
items="${requestScope.configContext.axisConfiguration.services.values()}">
+<c:forEach var="service" items="${requestScope.sortedServices.values()}">
 <%
             AxisService axisService = (AxisService) 
pageContext.getAttribute("service");
             if (!Utils.isHiddenService(axisService)) {
+            // AXIS2-5881: Sort operations alphabetically
+            java.util.List<AxisOperation> sortedOps = new 
java.util.ArrayList<>();
             Iterator opItr = axisService.getOperations();
+            while (opItr.hasNext()) { sortedOps.add((AxisOperation) 
opItr.next()); }
+            sortedOps.sort(java.util.Comparator.comparing(o -> 
o.getName().getLocalPart()));
+            opItr = sortedOps.iterator();
             String serviceName = axisService.getName();
 %><h2><a style="color:blue" href="<%=prefix + 
axisService.getName()%>?wsdl"><%=serviceName%></a></h2>
 <%
@@ -69,7 +74,7 @@
 } else {
 %><i> There are no Operations specified</i><%
     }
-    opItr = axisService.getOperations();
+    opItr = sortedOps.iterator();
 %><ul><%
     while (opItr.hasNext()) {
         AxisOperation axisOperation = (AxisOperation) opItr.next();

Reply via email to