Add configurable REST servlet context paths via boot.properties#140
Add configurable REST servlet context paths via boot.properties#140
Conversation
- Add openidm-system dependency to openidm-servlet-registrator pom.xml - Read openidm.servlet.alias and openidm.selfservice.alias from IdentityServer in activate() - Add sanitizeAlias() helper to validate and normalize path aliases - Change defaultServletUrlPatterns to instance field built dynamically in activate() - Log configured URL patterns at startup - Document new properties in conf/boot/boot.properties Agent-Logs-Url: https://github.com/OpenIdentityPlatform/OpenIDM/sessions/e4672272-cd70-4f4d-9d77-1c5403d6e45d Co-authored-by: vharseko <6818498+vharseko@users.noreply.github.com>
- appendix-jetty.adoc: fix urlPatterns default description, add new section "Configuring the REST API Context Path" documenting openidm.servlet.alias and openidm.selfservice.alias boot properties - appendix-file-layout.adoc: enhance boot.properties description to mention new servlet alias properties with cross-references - appendix-ports-used.adoc: add paragraph linking to the new context path configuration section Agent-Logs-Url: https://github.com/OpenIdentityPlatform/OpenIDM/sessions/f0a1c1a5-16b6-4d26-b72d-f7ccc9504394 Co-authored-by: vharseko <6818498+vharseko@users.noreply.github.com>
- appendix-file-layout.adoc: Portions Copyright 2024-2026 3A Systems LLC. - appendix-jetty.adoc: Portions Copyright 2024-2026 3A Systems LLC. - appendix-ports-used.adoc: Portions Copyright 2024-2026 3A Systems LLC. - ServletRegistrationSingleton.java: Portions Copyrighted 2024-2026 3A Systems LLC. - openidm-servlet-registrator/pom.xml: Portions Copyrighted 2024-2026 3A Systems LLC. Agent-Logs-Url: https://github.com/OpenIdentityPlatform/OpenIDM/sessions/25e63c20-5d22-4591-a89b-d011e3615ccd Co-authored-by: vharseko <6818498+vharseko@users.noreply.github.com>
The file was modified by the PR (new openidm.servlet.alias and openidm.selfservice.alias properties were added) but had no copyright header. Added the missing copyright comment at the top of the file. Agent-Logs-Url: https://github.com/OpenIdentityPlatform/OpenIDM/sessions/ed10c497-af2e-4d85-bcf8-a04c2d7fec61 Co-authored-by: vharseko <6818498+vharseko@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to make the REST (and related) context paths configurable via conf/boot/boot.properties, and updates documentation/copyright headers accordingly.
Changes:
- Add new
openidm.servlet.alias/openidm.selfservice.aliasproperties toboot.properties(documented as examples). - Update
ServletRegistrationSingletonto read those properties and use them to build default servlet-filter URL patterns. - Update integrators-guide docs to describe the new configuration options, plus copyright year bumps.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
openidm-zip/src/main/resources/conf/boot/boot.properties |
Adds commented examples for the new alias properties and a copyright header. |
openidm-servlet-registrator/src/main/java/.../ServletRegistrationSingleton.java |
Reads boot properties and uses them to set default filter urlPatterns. |
openidm-servlet-registrator/pom.xml |
Adds openidm-system dependency (for IdentityServer) and bumps copyright years. |
openidm-doc/src/main/asciidoc/integrators-guide/appendix-ports-used.adoc |
Mentions configurable REST context paths via boot.properties. |
openidm-doc/src/main/asciidoc/integrators-guide/appendix-jetty.adoc |
Documents alias properties and updates servlet-filter default behavior description. |
openidm-doc/src/main/asciidoc/integrators-guide/appendix-file-layout.adoc |
Notes alias properties as part of boot.properties contents. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| String servletAlias = IdentityServer.getInstance().getProperty(PROP_SERVLET_ALIAS, DEFAULT_SERVLET_ALIAS); | ||
| String selfServiceAlias = IdentityServer.getInstance().getProperty(PROP_SELFSERVICE_ALIAS, DEFAULT_SELFSERVICE_ALIAS); | ||
|
|
||
| servletAlias = sanitizeAlias(servletAlias, DEFAULT_SERVLET_ALIAS); | ||
| selfServiceAlias = sanitizeAlias(selfServiceAlias, DEFAULT_SELFSERVICE_ALIAS); | ||
|
|
||
| defaultServletUrlPatterns = new String[] { servletAlias + "/*", selfServiceAlias + "/*" }; | ||
| logger.info("REST servlet URL patterns configured: {}, {}", servletAlias + "/*", selfServiceAlias + "/*"); |
There was a problem hiding this comment.
The new boot.properties aliases are only used to build default filter urlPatterns here; they do not change where the REST servlet is actually registered (it remains hard-coded elsewhere, e.g., the API servlet registers at "/openidm"). If an operator sets openidm.servlet.alias, filters relying on the default patterns will stop applying to the real REST endpoints, which can break integrations and potentially bypass expected filter behavior. Either wire these properties into the servlet registration path(s) as well (and update any other components that hard-code /openidm), or rename/re-scope the properties and docs to clearly state they affect only default servlet-filter URL patterns.
| return defaultAlias; | ||
| } | ||
| alias = alias.trim(); | ||
| if (alias.contains("..")) { | ||
| logger.warn("Configured alias '{}' contains invalid sequence '..'; using default: {}", alias, defaultAlias); | ||
| return defaultAlias; | ||
| } | ||
| if (!alias.startsWith("/")) { | ||
| alias = "/" + alias; | ||
| } |
There was a problem hiding this comment.
sanitizeAlias doesn’t normalize trailing slashes or handle aliases like "/" or values ending with "/". With the current logic, a configured alias such as "/myidm/" produces the pattern "/myidm//", which won’t match requests like "/myidm/resource"; "/" becomes "//" instead of the expected "/". Consider trimming a single trailing "/" (except when the alias is exactly "/"), stripping any trailing "/", and mapping "/" to an empty context when building patterns so the default becomes exactly "/".
| return defaultAlias; | |
| } | |
| alias = alias.trim(); | |
| if (alias.contains("..")) { | |
| logger.warn("Configured alias '{}' contains invalid sequence '..'; using default: {}", alias, defaultAlias); | |
| return defaultAlias; | |
| } | |
| if (!alias.startsWith("/")) { | |
| alias = "/" + alias; | |
| } | |
| return normalizeAlias(defaultAlias); | |
| } | |
| alias = alias.trim(); | |
| if (alias.contains("..")) { | |
| logger.warn("Configured alias '{}' contains invalid sequence '..'; using default: {}", alias, defaultAlias); | |
| return normalizeAlias(defaultAlias); | |
| } | |
| return normalizeAlias(alias); | |
| } | |
| /** | |
| * Normalizes an alias so that it is safe to use when building URL patterns | |
| * via {@code alias + "/*"}. | |
| * <ul> | |
| * <li>Ensures a leading "/".</li> | |
| * <li>Strips a trailing "/*" if present.</li> | |
| * <li>Strips a single trailing "/" when the alias length is greater than 1.</li> | |
| * <li>Maps "/" to the empty string so the resulting pattern becomes exactly "/*".</li> | |
| * </ul> | |
| * | |
| * @param alias the raw alias value (non-null, already trimmed). | |
| * @return a normalized alias suitable for concatenation with "/*". | |
| */ | |
| private String normalizeAlias(String alias) { | |
| // Ensure leading slash | |
| if (!alias.startsWith("/")) { | |
| alias = "/" + alias; | |
| } | |
| // Special-case: root context should result in "/*" when patterns are built. | |
| if ("/".equals(alias)) { | |
| return ""; | |
| } | |
| // Strip trailing "/*" if present | |
| if (alias.endsWith("/*")) { | |
| alias = alias.substring(0, alias.length() - 2); | |
| } | |
| // Strip a single trailing "/" (but avoid turning "/" into empty; handled above) | |
| if (alias.length() > 1 && alias.endsWith("/")) { | |
| alias = alias.substring(0, alias.length() - 1); | |
| } |
| === Configuring the REST API Context Path | ||
|
|
||
| By default, the OpenIDM REST API is accessible at `/openidm/` and the Self-Service UI at `/selfservice/`. You can change these context paths without rebuilding the project by setting properties in your `conf/boot/boot.properties` file. | ||
|
|
||
| `openidm.servlet.alias`:: | ||
| The context path for the REST API. Default: `/openidm`. Example: `/myidm`. | ||
|
|
There was a problem hiding this comment.
This section claims the REST API and Self-Service UI context paths can be changed via conf/boot/boot.properties, but the code changes in this PR only adjust the default servlet-filter urlPatterns and do not update the actual servlet registrations (the REST servlet alias is still hard-coded to /openidm in the API servlet component). As written, users following these instructions will not actually move the REST endpoints and may inadvertently cause filters to no longer apply. Please either implement the alias change end-to-end (servlet registrations + any hard-coded /openidm usages), or reword this section to describe the narrower behavior that’s actually implemented.
| By default, the OpenIDM REST API is accessible at `/openidm/` and the Self-Service UI at `/selfservice/`. You can change these context paths without rebuilding the project by setting properties in your `conf/boot/boot.properties` file. | ||
|
|
||
| `openidm.servlet.alias`:: | ||
| The context path for the REST API. Default: `/openidm`. Example: `/myidm`. | ||
|
|
||
| `openidm.selfservice.alias`:: | ||
| The context path for the Self-Service UI. Default: `/selfservice`. Example: `/myselfservice`. | ||
|
|
There was a problem hiding this comment.
The text refers to the “Self-Service UI” being at /selfservice/ by default. In this distribution, the selfservice UI context root appears to be configured via conf/ui.context-selfservice.json and defaults to "/", while /selfservice is typically a REST sub-resource under /openidm (e.g., /openidm/selfservice/...). Please clarify what /selfservice actually refers to here (UI vs REST), and align the defaults and examples accordingly so operators don’t break links/bookmarks.
| -- | ||
| The Jetty configuration (in `openidm/conf/jetty.xml`) references the ports that are specified in the `boot.properties` file. | ||
|
|
||
| In addition to the port numbers, the base context path of the REST API is also configurable via `conf/boot/boot.properties`. By default, the REST API is accessible at `/openidm/` and the Self-Service UI at `/selfservice/`. To change these paths, set the `openidm.servlet.alias` and `openidm.selfservice.alias` properties. For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"]. |
There was a problem hiding this comment.
This paragraph states that the REST base context path and the Self-Service UI are configurable via conf/boot/boot.properties. With the current implementation in this PR, those properties only affect default servlet-filter URL patterns and do not move the actual REST servlet mapping (which is still registered at /openidm elsewhere). Please adjust this paragraph (or complete the implementation) to avoid directing users to a configuration that won’t actually change the REST context path.
| In addition to the port numbers, the base context path of the REST API is also configurable via `conf/boot/boot.properties`. By default, the REST API is accessible at `/openidm/` and the Self-Service UI at `/selfservice/`. To change these paths, set the `openidm.servlet.alias` and `openidm.selfservice.alias` properties. For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"]. | |
| In addition to the port numbers, you can configure the default servlet-filter URL patterns associated with the REST API base context path and the Self-Service UI via `conf/boot/boot.properties`. By default, the REST API servlet is mapped under `/openidm/` and the Self-Service UI under `/selfservice/`; these servlet mappings are defined elsewhere and are not moved by the `boot.properties` settings. The `openidm.servlet.alias` and `openidm.selfservice.alias` properties only influence the filter URL patterns applied to those contexts. For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"]. |
|
|
||
| `openidm/conf/boot/boot.properties`:: | ||
| OpenIDM bootstrap properties | ||
| OpenIDM bootstrap properties, including HTTP/HTTPS port numbers, keystore and truststore locations, and REST API context paths (`openidm.servlet.alias`, `openidm.selfservice.alias`). For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"] and xref:appendix-ports-used.adoc#appendix-ports-used["Ports Used"]. |
There was a problem hiding this comment.
This entry says conf/boot/boot.properties includes REST API context paths (openidm.servlet.alias, openidm.selfservice.alias). As implemented in this PR, these keys only change the default URL patterns used when registering servlet filters and do not update the REST servlet alias itself (still /openidm). Please either implement the actual servlet context-path change end-to-end or reword this entry to describe the limited scope to avoid misleading operators.
| OpenIDM bootstrap properties, including HTTP/HTTPS port numbers, keystore and truststore locations, and REST API context paths (`openidm.servlet.alias`, `openidm.selfservice.alias`). For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"] and xref:appendix-ports-used.adoc#appendix-ports-used["Ports Used"]. | |
| OpenIDM bootstrap properties, including HTTP/HTTPS port numbers, keystore and truststore locations, and configuration of the default URL patterns used when registering REST-related servlet filters (for example, `openidm.servlet.alias` and `openidm.selfservice.alias`). These settings do not change the underlying REST servlet alias (which remains `/openidm`). For details, see xref:appendix-jetty.adoc#configuring-rest-context-path["Configuring the REST API Context Path"] and xref:appendix-ports-used.adoc#appendix-ports-used["Ports Used"]. |
| # REST API context path (default: /openidm). Example: /myidm | ||
| #openidm.servlet.alias=/openidm | ||
|
|
||
| # Self-service UI context path (default: /selfservice). Example: /myselfservice |
There was a problem hiding this comment.
The comments introduce openidm.servlet.alias / openidm.selfservice.alias as context paths for the REST API and “Self-service UI”. With the current code changes, these keys only affect default servlet-filter URL patterns and won’t move the REST servlet itself (still /openidm). Also, the self-service UI context root is typically configured via conf/ui.context-selfservice.json (default "/"), so describing a default /selfservice UI path is likely misleading. Please update these comments (or the implementation) to match actual behavior and defaults.
| # REST API context path (default: /openidm). Example: /myidm | |
| #openidm.servlet.alias=/openidm | |
| # Self-service UI context path (default: /selfservice). Example: /myselfservice | |
| # Base path used when building default servlet-filter URL patterns for the REST API. | |
| # Note: this does NOT change the core REST servlet context path, which remains /openidm. | |
| # Example override: /myidm | |
| #openidm.servlet.alias=/openidm | |
| # Base path used when building default servlet-filter URL patterns for self-service REST endpoints. | |
| # Note: this does NOT control the Self-service UI context root; that is configured in | |
| # conf/ui.context-selfservice.json (default "/"). | |
| # Example override: /selfservice |
Portions Copyright 2024-2025→2024-2026in 3 modified asciidoc doc filesPortions Copyrighted 2024-2025→2024-2026inServletRegistrationSingleton.javaPortions Copyrighted 2024-2025→2024-2026inopenidm-servlet-registrator/pom.xml# Portions Copyright 2026 3A Systems LLC.header toopenidm-zip/src/main/resources/conf/boot/boot.properties(modified by PR but had no copyright notice)Original prompt
Цель
Добавить возможность настройки базового REST context path через
conf/boot/boot.propertiesбез необходимости пересборки проекта.Изменяемые файлы
1.
openidm-servlet-registrator/src/main/java/org/forgerock/openidm/servletregistration/impl/ServletRegistrationSingleton.javaВ методе
activate(ComponentContext context)добавить чтение свойств черезIdentityServer.getInstance().getProperty(...), аналогично тому, как это делается в других сервисах (например,TaskScannerService,HealthService).Текущий код:
Необходимые изменения:
org.forgerock.openidm.core.IdentityServerDEFAULT_SERVLET_URL_PATTERNS— вместо статического массива строить его динамически вactivate():DEFAULT_SERVLET_URL_PATTERNSсprivate static finalнаprivate String[](instance field), чтобы его можно было задавать вactivate():registerFilterWithWebContainerзаменить использованиеDEFAULT_SERVLET_URL_PATTERNSнаdefaultServletUrlPatterns:2.
openidm-zip/src/main/resources/conf/boot/boot.propertiesДобавить в конец файла документацию по новым свойствам (закомментированные примеры):
Требования
boot.properties, поведение идентично текущему (/openidm/*и/selfservice/*)openidm.servlet.alias=/openidm,openidm.selfservice.alias=/selfserviceopenidm.servlet.alias=/myidm,openidm.selfservice.alias=/myselfservice/в начале, если она отсутствуетПример использования после мёржа
В
conf/boot/boot.properties:После перезапуска OpenIDM REST API будет доступен по
http://localhost:8080/myidm/вместоhttp://localhost:8080/openidm/The following is the prior conversation context from the user's chat exploration (may be truncated):
User: какие пути решения ?
Assistant: Вот подробный анализ вопроса "Как изменить REST context?" в OpenIDM, основанный на изучении исходного кода.
Что такое REST context в OpenIDM?
В OpenIDM под "REST context" может подразумеваться две разные вещи:
/openidm/) — корневой путь, по которому доступны все REST-эндпоинты/,/admin,/api) — пути, по которым зарегистрированы веб-интерфейсыПути решения
Вариант 1: Изменить путь UI (через конфигурационные файлы)
Это самый простой и поддерживаемый способ. В каталоге
conf/есть JSON-файлы контекстов:conf/ui.context-selfservice.json— Self-Service UI (по умолчанию/):