Skip to content

Add configurable REST servlet context paths via boot.properties#140

Open
Copilot wants to merge 5 commits intomasterfrom
copilot/add-rest-context-path-configuration
Open

Add configurable REST servlet context paths via boot.properties#140
Copilot wants to merge 5 commits intomasterfrom
copilot/add-rest-context-path-configuration

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 27, 2026

  • Update Portions Copyright 2024-20252024-2026 in 3 modified asciidoc doc files
  • Update Portions Copyrighted 2024-20252024-2026 in ServletRegistrationSingleton.java
  • Update Portions Copyrighted 2024-20252024-2026 in openidm-servlet-registrator/pom.xml
  • Add # Portions Copyright 2026 3A Systems LLC. header to openidm-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).

Текущий код:

import org.osgi.framework.BundleContext;
...

private static final String[] DEFAULT_SERVLET_NAME = new String[] { "OpenIDM REST" };
private static final String[] DEFAULT_SERVLET_URL_PATTERNS = new String[] { "/openidm/*", "/selfservice/*" };

...

@Activate
public void activate(ComponentContext context) {
    bundleContext = context.getBundleContext();
    sharedContext = webContainer.createDefaultSharedHttpContext();
}

Необходимые изменения:

  1. Добавить импорт org.forgerock.openidm.core.IdentityServer
  2. Добавить константы для имён свойств:
private static final String PROP_SERVLET_ALIAS = "openidm.servlet.alias";
private static final String PROP_SELFSERVICE_ALIAS = "openidm.selfservice.alias";
private static final String DEFAULT_SERVLET_ALIAS = "/openidm";
private static final String DEFAULT_SELFSERVICE_ALIAS = "/selfservice";
  1. Удалить или заменить DEFAULT_SERVLET_URL_PATTERNS — вместо статического массива строить его динамически в activate():
@Activate
public void activate(ComponentContext context) {
    bundleContext = context.getBundleContext();
    sharedContext = webContainer.createDefaultSharedHttpContext();

    String servletAlias = IdentityServer.getInstance().getProperty(PROP_SERVLET_ALIAS, DEFAULT_SERVLET_ALIAS);
    String selfServiceAlias = IdentityServer.getInstance().getProperty(PROP_SELFSERVICE_ALIAS, DEFAULT_SELFSERVICE_ALIAS);

    // Ensure paths start with /
    if (!servletAlias.startsWith("/")) {
        servletAlias = "/" + servletAlias;
    }
    if (!selfServiceAlias.startsWith("/")) {
        selfServiceAlias = "/" + selfServiceAlias;
    }

    defaultServletUrlPatterns = new String[] { servletAlias + "/*", selfServiceAlias + "/*" };
    logger.info("REST servlet URL patterns configured: {}, {}", servletAlias + "/*", selfServiceAlias + "/*");
}
  1. Изменить DEFAULT_SERVLET_URL_PATTERNS с private static final на private String[] (instance field), чтобы его можно было задавать в activate():
private String[] defaultServletUrlPatterns = new String[] { "/openidm/*", "/selfservice/*" };
  1. В методе registerFilterWithWebContainer заменить использование DEFAULT_SERVLET_URL_PATTERNS на defaultServletUrlPatterns:
List<String> urlPatterns = config.get(SERVLET_FILTER_URL_PATTERNS)
        .defaultTo(Arrays.asList(defaultServletUrlPatterns))
        .asList(String.class);

2. openidm-zip/src/main/resources/conf/boot/boot.properties

Добавить в конец файла документацию по новым свойствам (закомментированные примеры):

# REST API context path (default: /openidm). Example: /myidm
# openidm.servlet.alias=/openidm

# Self-service UI context path (default: /selfservice). Example: /myselfservice
# openidm.selfservice.alias=/selfservice

Требования

  • Обратная совместимость: если свойства не заданы в boot.properties, поведение идентично текущему (/openidm/* и /selfservice/*)
  • Значения по умолчанию: openidm.servlet.alias=/openidm, openidm.selfservice.alias=/selfservice
  • Пример кастомной конфигурации в boot.properties: openidm.servlet.alias=/myidm, openidm.selfservice.alias=/myselfservice
  • Путь автоматически дополняется / в начале, если она отсутствует
  • При старте сервиса в лог пишется итоговый URL pattern

Пример использования после мёржа

В conf/boot/boot.properties:

openidm.servlet.alias=/myidm
openidm.selfservice.alias=/myselfservice

После перезапуска 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" может подразумеваться две разные вещи:

  1. Базовый путь REST API (/openidm/) — корневой путь, по которому доступны все REST-эндпоинты
  2. Путь UI (/, /admin, /api) — пути, по которым зарегистрированы веб-интерфейсы

Пути решения

Вариант 1: Изменить путь UI (через конфигурационные файлы)

Это самый простой и поддерживаемый способ. В каталоге conf/ есть JSON-файлы контекстов:

conf/ui.context-selfservice.json — Self-Service UI (по умолчанию /):

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

- 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>
Copilot AI changed the title [WIP] Add configuration for REST context path in boot.properties Add configurable REST servlet context paths via boot.properties Mar 27, 2026
Copilot AI requested a review from vharseko March 27, 2026 10:16
- 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>
@vharseko vharseko marked this pull request as ready for review March 28, 2026 16:47
Copilot AI review requested due to automatic review settings March 28, 2026 16:47
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.alias properties to boot.properties (documented as examples).
  • Update ServletRegistrationSingleton to 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.

Comment on lines +123 to +130
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 + "/*");
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +155
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;
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 "/".

Suggested change
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);
}

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +199
=== 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`.

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +202
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`.

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
--
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"].
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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"].

Copilot uses AI. Check for mistakes.

`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"].
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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"].

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +73
# REST API context path (default: /openidm). Example: /myidm
#openidm.servlet.alias=/openidm

# Self-service UI context path (default: /selfservice). Example: /myselfservice
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
# 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

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants