From 114493496bd3c3b683d6459d28ab732113734c18 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Fri, 21 Aug 2026 10:43:53 +0300 Subject: [PATCH 1/2] [#1111] Click fork: stop calling javax.servlet-bound upstream ClickUtils The fork is compiled against jakarta.servlet, but click-nodeps 2.3.0 is not: upstream ClickUtils.getLogService() resolves a javax.servlet.Servlet- Context that is absent from the classpath, and reads a thread local that only the upstream servlet populates. Route these calls to the fork's own ClickUtils.getLogService() instead. ContainerUtils imported org.apache.click.util.ClickUtils, shadowing the same-package fork class, so its unqualified call resolved upstream too. Its LogService import is repointed as well: the upstream interface is javax.servlet-bound via onInit(ServletContext). No behaviour change; nothing reaches this code today. --- .../openam/click/util/ClickUtils.java | 12 +++++------ .../openam/click/util/ContainerUtils.java | 21 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java index 7e4c7533f4..af8ae3fbb1 100644 --- a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java +++ b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java @@ -534,11 +534,11 @@ public static void autoPostRedirect(HttpServletRequest request, } } catch (IOException ex) { - org.apache.click.util.ClickUtils.getLogService().error(ex.getMessage(), ex); + getLogService().error(ex.getMessage(), ex); } finally { - org.apache.click.util.ClickUtils.close(gos); - org.apache.click.util.ClickUtils.close(os); + close(gos); + close(os); } } @@ -1151,7 +1151,7 @@ public static InputStream getClickConfig(ServletContext servletContext) { servletContext.getResourceAsStream(DEFAULT_APP_CONFIG); if (inputStream == null) { - inputStream = org.apache.click.util.ClickUtils.getResourceAsStream("/click.xml", org.apache.click.util.ClickUtils.class); + inputStream = getResourceAsStream("/click.xml", ClickUtils.class); if (inputStream == null) { String msg = "could not find click app configuration file: " @@ -1570,7 +1570,7 @@ public static void deployFile(ServletContext servletContext, if (!destinationFile.exists()) { InputStream inputStream = - getResourceAsStream(resource, org.apache.click.util.ClickUtils.class); + getResourceAsStream(resource, ClickUtils.class); if (inputStream != null) { FileOutputStream fos = null; @@ -1676,7 +1676,7 @@ public static void deployFileList(ServletContext servletContext, String descriptorFile = packageName + "/" + controlName + ".files"; logService.debug("Use deployment descriptor file:" + descriptorFile); - InputStream is = getResourceAsStream(descriptorFile, org.apache.click.util.ClickUtils.class); + InputStream is = getResourceAsStream(descriptorFile, ClickUtils.class); List fileList = IOUtils.readLines(is); if (fileList == null || fileList.isEmpty()) { logService.info("there are no files to deploy for control " + controlClass.getName()); diff --git a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java index b499b14c72..2b9b301acc 100644 --- a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java +++ b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java @@ -43,8 +43,7 @@ import org.apache.click.control.FieldSet; import org.openidentityplatform.openam.click.control.Form; import org.apache.click.control.Label; -import org.apache.click.service.LogService; -import org.apache.click.util.ClickUtils; +import org.openidentityplatform.openam.click.service.LogService; import org.apache.click.util.HtmlStringBuffer; import org.apache.click.util.PropertyUtils; import org.apache.commons.lang.ClassUtils; @@ -114,7 +113,7 @@ public static void copyContainerToObject(Container container, } if (fieldList.isEmpty()) { - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); if (logService.isDebugEnabled()) { String containerClassName = ClassUtils.getShortClassName(container.getClass()); @@ -137,7 +136,7 @@ public static void copyContainerToObject(Container container, return; } - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); Set properties = getObjectPropertyNames(object); Map ognlContext = Ognl.createDefaultContext( @@ -235,7 +234,7 @@ public static void copyObjectToContainer(Object object, } if (fieldList.isEmpty()) { - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); if (logService.isDebugEnabled()) { String containerClassName = ClassUtils.getShortClassName(container.getClass()); @@ -261,7 +260,7 @@ public static void copyObjectToContainer(Object object, Set properties = getObjectPropertyNames(object); - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); for (Field field : fieldList) { @@ -902,7 +901,7 @@ private static Method findGetter(Object object, String property, String path) { // Find the getter for property - String getterName = org.apache.click.util.ClickUtils.toGetterName(property); + String getterName = ClickUtils.toGetterName(property); Method method = null; Class sourceClass = object.getClass(); @@ -913,7 +912,7 @@ private static Method findGetter(Object object, String property, } if (method == null) { - String isGetterName = org.apache.click.util.ClickUtils.toIsGetterName(property); + String isGetterName = ClickUtils.toIsGetterName(property); try { method = sourceClass.getMethod(isGetterName, (Class[]) null); } catch (Exception e) { @@ -973,7 +972,7 @@ private static Method findSetter(Object source, Method method = null; // Find the setter for property - String setterName = org.apache.click.util.ClickUtils.toSetterName(property); + String setterName = ClickUtils.toSetterName(property); Class sourceClass = source.getClass(); Class[] classArgs = { targetClass }; @@ -1050,7 +1049,7 @@ private static void logBasicDescription(org.apache.click.util.HtmlStringBuffer b */ private static void copyFieldsToMap(List fieldList, Map map) { - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); String objectClassname = map.getClass().getName(); objectClassname = @@ -1086,7 +1085,7 @@ private static void copyFieldsToMap(List fieldList, Map m */ private static void copyMapToFields(Map map, List fieldList) { - LogService logService = org.apache.click.util.ClickUtils.getLogService(); + LogService logService = ClickUtils.getLogService(); String objectClassname = map.getClass().getName(); objectClassname = From 21c3743c7531a100d67b0aa773667b3d75b2765e Mon Sep 17 00:00:00 2001 From: maximthomas Date: Fri, 21 Aug 2026 12:48:45 +0300 Subject: [PATCH 2/2] [#1111] Click fork: finish the upstream sweep in ContainerUtils, ClickUtils, ErrorReport ErrorReport fully-qualified org.apache.click.util.ClickUtils at seven sites. Unlike the rest, it is reachable (ErrorPage, VelocityTemplateService), so the fork kept a hard reference into the javax.servlet-compiled jar in live code. De-qualified onto the fork's own getBundle/escapeHtml. ContainerUtils imported upstream Button and Label, which extend upstream Field, so every instanceof filter was permanently false for fork controls. Repointed. FieldSet has no fork equivalent, so its guard was always true and is dropped. ClickUtils imported upstream ActionLink, making the getCssSelector branch at :1461 dead for every control the fork can produce. getConfigService's failure message told operators to register org.apache.click.ClickServlet, which never sets the fork's ConfigService attribute -- following it made the failure permanent. --- .../openam/click/util/ClickUtils.java | 12 +++---- .../openam/click/util/ContainerUtils.java | 31 +++++++++---------- .../openam/click/util/ErrorReport.java | 14 ++++----- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java index af8ae3fbb1..5ab8562498 100644 --- a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java +++ b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ClickUtils.java @@ -65,7 +65,7 @@ import org.apache.click.Stateful; import org.openidentityplatform.openam.click.control.AbstractControl; import org.openidentityplatform.openam.click.control.AbstractLink; -import org.apache.click.control.ActionLink; +import org.openidentityplatform.openam.click.control.ActionLink; import org.openidentityplatform.openam.click.control.Container; import org.openidentityplatform.openam.click.control.Field; import org.openidentityplatform.openam.click.control.Form; @@ -1187,7 +1187,7 @@ public static ConfigService getConfigService(ServletContext servletContext) { + " editing your web.xml and setting the load-on-startup to 0:\n\n" + " \n" + " ClickServlet\n" - + " org.apache.click.ClickServlet\n" + + " org.openidentityplatform.openam.click.ClickServlet\n" + " 0\n" + " \n"; @@ -1410,7 +1410,7 @@ public static String getApplicationResourceVersionIndicator() { * *
  • if control.getName() is set do the following: *
      - *
    1. if the control is of type {@link org.apache.click.control.ActionLink}, + *
    2. if the control is of type {@link org.openidentityplatform.openam.click.control.ActionLink}, * it's "class" attribute selector will be returned. For example: * a[class=red]. Please note: if the link class attribute is * not set, the class attribute will be set to its name, prefixed with @@ -2194,8 +2194,8 @@ public static LogService getLogService() { /** * Return the list of Fields for the given Form, including any Fields - * contained in FieldSets. The list of returned fields will exclude any - * Button, FieldSet or Label fields. + * contained in child containers. The list of returned fields will exclude + * any Button or Label fields. * * @param form the form to obtain the fields from * @return the list of contained form fields @@ -3072,7 +3072,7 @@ private static void bind(Container container, Context context) { for (int i = 0; i < container.getControls().size(); i++) { Control control = container.getControls().get(i); if (control instanceof Container) { - // Include fields but skip fieldSets + // Include fields that are containers if (control instanceof Field) { Field field = (Field) control; bindField(field, context); diff --git a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java index 2b9b301acc..35db144085 100644 --- a/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java +++ b/openam-core/src/main/java/org/openidentityplatform/openam/click/util/ContainerUtils.java @@ -37,12 +37,11 @@ import org.openidentityplatform.openam.click.Control; import org.openidentityplatform.openam.click.Page; -import org.apache.click.control.Button; +import org.openidentityplatform.openam.click.control.Button; import org.openidentityplatform.openam.click.control.Container; import org.openidentityplatform.openam.click.control.Field; -import org.apache.click.control.FieldSet; import org.openidentityplatform.openam.click.control.Form; -import org.apache.click.control.Label; +import org.openidentityplatform.openam.click.control.Label; import org.openidentityplatform.openam.click.service.LogService; import org.apache.click.util.HtmlStringBuffer; import org.apache.click.util.PropertyUtils; @@ -433,7 +432,7 @@ public static List getFields(Container container) { /** * Return the list of Fields for the given Container, recursively including * any Fields contained in child containers. The list of returned fields - * will exclude any Button and FieldSet fields. + * will exclude any Button fields. * * @param container the container to obtain the fields from * @return the list of contained fields @@ -451,7 +450,7 @@ public static List getFieldsAndLabels(Container container) { /** * Return the list of hidden Fields for the given Container, recursively including * any Fields contained in child containers. The list of returned fields - * will exclude any Button, FieldSet and Label + * will exclude any Button and Label * fields. * * @param container the container to obtain the fields from @@ -471,7 +470,7 @@ public static List getHiddenFields(final Container container) { * Return the list of input Fields (TextField, Select, Radio, Checkbox etc). * for the given Container, recursively including any Fields contained in * child containers. The list of returned fields will exclude any - * Button, FieldSet and Label fields. + * Button and Label fields. * * @param container the container to obtain the fields from * @return the list of contained fields @@ -1166,7 +1165,7 @@ private static void addFields(final Container container, final List field * Add input fields (TextField, TextArea, Select, Radio, Checkbox etc.) for * the given Container to the specified field list, recursively including * any Fields contained in child containers. The list of returned fields - * will exclude any Button, FieldSet and Label + * will exclude any Button and Label * fields. * * @param container the container to obtain the fields from @@ -1180,8 +1179,8 @@ private static void addInputFields(final Container container, final List continue; } else if (control instanceof Container) { - // Include fields but skip fieldSets - if (control instanceof Field && !(control instanceof FieldSet)) { + // Include fields that are containers + if (control instanceof Field) { fields.add((Field) control); } Container childContainer = (Container) control; @@ -1196,8 +1195,8 @@ private static void addInputFields(final Container container, final List /** * Add hidden fields for the given Container to the specified field list, * recursively including any Fields contained in child containers. The list - * of returned fields will exclude any Button, FieldSet - * and Label fields. + * of returned fields will exclude any Button and + * Label fields. * * @param container the container to obtain the hidden fields from * @param fields the list of contained fields @@ -1210,8 +1209,8 @@ private static void addHiddenFields(final Container container, final List continue; } else if (control instanceof Container) { - // Include fields but skip fieldSets - if (control instanceof Field && !(control instanceof FieldSet)) { + // Include fields that are containers + if (control instanceof Field) { Field field = (Field) control; if (field.isHidden()) { fields.add((Field) control); @@ -1233,7 +1232,7 @@ private static void addHiddenFields(final Container container, final List /** * Add fields for the container to the specified field list, recursively * including any Fields contained in child containers. The list - * of returned fields will exclude any Button and FieldSet + * of returned fields will exclude any Button * fields. * * @param container the container to obtain the fields from @@ -1247,8 +1246,8 @@ private static void addFieldsAndLabels(final Container container, final List"); - buffer.append(org.apache.click.util.ClickUtils.escapeHtml(sw.toString().trim())); + buffer.append(ClickUtils.escapeHtml(sw.toString().trim())); buffer.append(""); return buffer.toString(); @@ -653,7 +653,7 @@ protected void writeMap(Map map, HtmlStringBuffer buffer) { buffer.append(key); buffer.append("="); if (value != null) { - buffer.append(org.apache.click.util.ClickUtils.escapeHtml(value.toString())); + buffer.append(ClickUtils.escapeHtml(value.toString())); } else { buffer.append("null"); }