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();
