Skip to content

Make REST context path configurable via openidm.context.path system property#142

Open
Copilot wants to merge 5 commits intomasterfrom
copilot/make-rest-context-path-configurable
Open

Make REST context path configurable via openidm.context.path system property#142
Copilot wants to merge 5 commits intomasterfrom
copilot/make-rest-context-path-configurable

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

  • Update copyright in appendix-rest.adoc and chap-configuration.adoc to 2024-2026
  • Update ServletComponent.java: 2024-20252024-2026
  • Update ServletComponentTest.java: 20252025-2026
  • Update ServletRegistrationSingleton.java: 2024-20252024-2026
  • Add Portions copyright 2026 3A Systems LLC. to RemoteCommandScope.java
  • Add Portions copyright 2026 3A Systems LLC. to all 34 JS delegate/view files
Original prompt

Problem

The REST context path /openidm is hardcoded throughout the entire codebase — in Java backend, JavaScript UI delegates, servlet registration, CLI tools, and documentation. This makes it impossible to change the REST API base path (e.g., to /myidm) without modifying source code.

As shown in the screenshot, there are 101+ matches in 53+ JS files alone for the hardcoded "/openidm" string:

image1

Requirements

  1. Make the REST context path configurable via a system property (e.g., openidm.context.path) with default value /openidm.
  2. Apply changes to both REST API and UI (openidm-ui) so they use the configured path.
  3. Update documentation to describe the new configuration parameter.
  4. Add automated tests for both the default (/openidm) and a custom value (e.g., /myidm).

Detailed Plan

1. Backend (Java)

1.1. Add system property support in ServerConstants or IdentityServer

  • Add a constant for the system property name: openidm.context.path
  • Add a static method to retrieve the configured context path (defaulting to /openidm)
  • Ensure it always starts with / and does not end with /

1.2. Refactor ServletComponent.java

File: openidm-api-servlet/src/main/java/org/forgerock/openidm/servlet/internal/ServletComponent.java

  • Replace private static final String SERVLET_ALIAS = "/openidm"; with a dynamic lookup:
    private static String getServletAlias() {
        return System.getProperty("openidm.context.path", "/openidm");
    }
  • Use this method in activate() instead of the constant.

1.3. Refactor ServletRegistrationSingleton.java

File: openidm-servlet-registrator/src/main/java/org/forgerock/openidm/servletregistration/impl/ServletRegistrationSingleton.java

  • Replace hardcoded DEFAULT_SERVLET_URL_PATTERNS = new String[] { "/openidm/*", "/selfservice/*" } to use the configurable context path:
    private static String[] getDefaultServletUrlPatterns() {
        String contextPath = System.getProperty("openidm.context.path", "/openidm");
        return new String[] { contextPath + "/*", "/selfservice/*" };
    }

1.4. Refactor RemoteCommandScope.java

File: openidm-shell/src/main/java/org/forgerock/openidm/shell/impl/RemoteCommandScope.java

  • Replace IDM_URL_DEFAULT = "http://localhost:8080/openidm/" to use the system property.

1.5. Add the property to default system.properties / boot.properties

File: openidm-zip/src/main/resources/conf/system.properties (or equivalent)

  • Add: openidm.context.path=/openidm

2. Frontend (JavaScript UI — openidm-ui)

2.1. Expose context path as a global constant

  • Add a configurable context path constant (e.g., in Constants.js or a new config module) that the UI reads. The backend should expose the configured context path, for example via an initial config endpoint or by injecting it into the HTML page template.
  • Alternatively, add a contextPath field to the existing Constants object that defaults to "/openidm" and can be overridden.

2.2. Refactor all UI delegate files

Replace all hardcoded "/openidm" and "/openidm/..." references with the configurable constant. Key files include (but are not limited to):

openidm-ui-admin delegates:

  • ReconDelegate.jsserviceUrl: "/openidm/recon/", "/openidm/audit/recon", "/openidm/" + link.targetObjectId
  • SchedulerDelegate.jsconstants.host + "/openidm/scheduler/job"
  • ExternalAccessDelegate.jsconstants.host + "/openidm/endpoint/oauthproxy", constants.host + "/openidm/external/rest"
  • ClusterDelegate.jsconstants.host + "/openidm"
  • WorkflowDelegate.jsconstants.host + "/openidm/workflow/processdefinition"
  • ScriptDelegate.jsconstants.host + "/openidm/script"
  • ConnectorDelegate.js — uses "/openidm/system"
  • AuditDelegate.js — uses "/openidm/audit/"
  • MaintenanceDelegate.js — uses "/openidm/maintenance"

openidm-ui-admin views/models:

  • ProcessInstanceView.jsurl: "/openidm/workflow/processinstance", "/openidm/workflow/processdefinition", "/openidm/managed/user", "/openidm/repo/internal/user", "/openidm/workflow/processinstance/", "/openidm/workflow/processdefinition/"
  • ProcessDefinitionView.jsurl: "/openidm/workflow/processdefinition", "/openidm/workflow/processdefinition/"
  • AdminValidators.jsif (v === "/openidm" || v === "/admin" || v === "/system")
  • SettingsView.jsConstants.host + "/openidm/maintenance"

openidm-ui-common delegates:

  • SystemHealthDelegate.jsconstants.host + "/openidm/health"
  • SocialDelegate.jsConstants.host + "/openidm/identityProviders", serviceUrl: "/openidm/authentication"
  • SearchDelegate.jsconstants.host + "/openidm"
  • InternalUserDelegate.jsconstants.host + "/openidm/repo/internal/user"
  • ConfigDelegate.js — likely uses "/openidm/config"
  • ResourceDelegate.js — likely uses "/openidm/"

**Pattern...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Make REST context path configurable via system property Make REST context path configurable via openidm.context.path system property Mar 31, 2026
Copilot AI requested a review from vharseko March 31, 2026 10:42
@vharseko vharseko marked this pull request as ready for review March 31, 2026 16:37
@vharseko vharseko requested a review from Copilot March 31, 2026 16:37
Copy link
Copy Markdown
Contributor

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 remove hardcoded /openidm REST base-path usage by introducing a configurable REST context path via the openidm.context.path system property (defaulting to /openidm), and refactoring backend/CLI/UI call sites and docs to use that configuration.

Changes:

  • Add backend support for a configurable servlet alias and default servlet-filter URL patterns based on openidm.context.path.
  • Refactor many UI delegates/views to build REST URLs using Constants.context instead of hardcoding /openidm.
  • Add/extend docs and add automated tests for the default context path.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
openidm-zip/src/main/resources/conf/system.properties Documents the new openidm.context.path setting (commented example).
openidm-ui/openidm-ui-common/src/test/qunit/tests/org/forgerock/openidm/ui/common/util/ConstantsTest.js Adds QUnit assertions for the default Constants.context value and derived prefix.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/workflow/WorkflowDelegate.js Replaces hardcoded /openidm/... workflow endpoints with "/" + constants.context + ....
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/notifications/NotificationDelegate.js Uses constants.context when building the notifications endpoint URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/SystemHealthDelegate.js Uses constants.context for health endpoint base URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/SocialDelegate.js Uses Constants.context for identityProviders/authentication endpoints.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/SearchDelegate.js Uses constants.context for the search delegate base URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/ResourceDelegate.js Uses constants.context for the resource delegate base URL and linkedView endpoint.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/PolicyDelegate.js Uses constants.context for policy endpoint base URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/InternalUserDelegate.js Uses constants.context for internal user repo URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/InfoDelegate.js Uses constants.context for /info/ endpoint base URL.
openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/ConfigDelegate.js Uses constants.context for /config endpoint base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/TaskListView.js Uses constants.context for workflow task URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/TaskInstanceView.js Uses constants.context for task/process/user model URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ProcessListView.js Uses constants.context for process-definition query URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ProcessInstanceView.js Uses constants.context for workflow and repo/internal/user and diagram URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ProcessHistoryView.js Uses constants.context for workflow history URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ProcessDefinitionView.js Uses constants.context for process-definition and diagram URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ProcessDefinitionsView.js Uses constants.context for process-definition list/query URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/workflow/ActiveProcessesView.js Uses constants.context for active process URLs and queries.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/user/EditUserView.js Uses constants.context for managed user reset password endpoint.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/settings/SettingsView.js Uses Constants.context for maintenance delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/mapping/util/MappingUtils.js Uses constants.context for repo/links deletion command endpoint.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/mapping/association/DataAssociationManagementView.js Uses constants.context for reconResults endpoint; adds Constants dependency.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/WorkflowDelegate.js Uses constants.context for workflow processdefinition delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/SyncDelegate.js Uses constants.context for sync and repo/link endpoints and mappingDetails endpoint.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/SecurityDelegate.js Uses constants.context for security delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/ScriptDelegate.js Uses constants.context for script delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/SchedulerDelegate.js Uses constants.context for scheduler/job delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/ReconDelegate.js Uses constants.context for recon and audit/recon and target object URLs.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/MaintenanceDelegate.js Uses constants.context for maintenance delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/ExternalAccessDelegate.js Uses constants.context for oauthproxy and external/rest endpoints.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/ConnectorDelegate.js Uses constants.context for system endpoint base URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/ClusterDelegate.js Uses constants.context for base cluster delegate URL.
openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/delegates/AuditDelegate.js Uses constants.context for audit delegate base URL.
openidm-ui/openidm-ui-admin/src/main/js/config/validators/AdminValidators.js Treats "/" + constants.context as a reserved URL value; updates error message accordingly.
openidm-shell/src/main/java/org/forgerock/openidm/shell/impl/RemoteCommandScope.java Builds the default CLI URL using openidm.context.path when the default URL value is used.
openidm-servlet-registrator/src/main/java/org/forgerock/openidm/servletregistration/impl/ServletRegistrationSingleton.java Derives default servlet-filter URL patterns from openidm.context.path (instead of hardcoded /openidm/*).
openidm-doc/src/main/asciidoc/integrators-guide/chap-configuration.adoc Documents the new openidm.context.path property and configuration examples.
openidm-doc/src/main/asciidoc/integrators-guide/appendix-rest.adoc Adds note that /openidm in examples is the default and can be changed via openidm.context.path.
openidm-api-servlet/src/test/java/org/forgerock/openidm/servlet/internal/ServletComponentTest.java Adds unit tests for default/custom/normalized servlet alias based on system property.
openidm-api-servlet/src/main/java/org/forgerock/openidm/servlet/internal/ServletComponent.java Registers the REST servlet under an alias derived from openidm.context.path (normalized).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +180
After changing this property, the REST API will be accessible under the new path, for example `\https://localhost:8443/myidm/config`, and the Admin UI and Self-Service UI will automatically use the configured path for all API calls.

[NOTE]
====
Changing the context path affects all REST API endpoints, the Admin UI, and the Self-Service UI. Ensure that any external integrations, load balancer rules, or documentation referring to the `/openidm` path are updated accordingly.
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

The statement that the Admin UI and Self-Service UI will “automatically use the configured path for all API calls” appears inaccurate with the current UI implementation: openidm-ui-common/.../util/Constants.js still hardcodes commonConstants.context = "openidm", so changing -Dopenidm.context.path on the JVM won’t update the UI’s REST base path unless additional wiring is added (for example, injecting the context into the UI at runtime or deriving it from window.location). Please either implement that wiring or adjust this documentation to describe the actual behavior/requirements for the UI.

Suggested change
After changing this property, the REST API will be accessible under the new path, for example `\https://localhost:8443/myidm/config`, and the Admin UI and Self-Service UI will automatically use the configured path for all API calls.
[NOTE]
====
Changing the context path affects all REST API endpoints, the Admin UI, and the Self-Service UI. Ensure that any external integrations, load balancer rules, or documentation referring to the `/openidm` path are updated accordingly.
After changing this property, the REST API will be accessible under the new path, for example `\https://localhost:8443/myidm/config`. The Admin UI and Self-Service UI, however, are implemented with a default context path of `/openidm` for their REST calls. To use a custom context path with the UIs, you must either deploy them behind a reverse proxy that maps the public path (for example `/myidm`) to `/openidm` on the OpenIDM server, or customize and rebuild the UI so that it derives the REST base path from the runtime context (for example, `window.location`) or from injected configuration that matches `openidm.context.path`.
[NOTE]
====
Changing the context path affects all REST API endpoints. If you expose the Admin UI or Self-Service UI under a custom path, ensure that any external integrations, load balancer rules, or documentation referring to the `/openidm` path are updated accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +9
QUnit.test("Constants.context defaults to 'openidm'", function (assert) {
assert.equal(Constants.context, "openidm",
"The default context should be 'openidm'");
});
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

These tests only verify the hardcoded default (Constants.context === "openidm"). The PR goal is configurable REST context paths; please add coverage for a non-default value as well (e.g., verifying delegates build URLs correctly when the context is overridden), which will require providing a supported way to set/override Constants.context in tests and in runtime.

Copilot uses AI. Check for mistakes.
private static String getUrl(final String url) {
if (isNotBlank(url)) {
return url.endsWith("/") ? url : url + "/";
return getEffectiveIdmUrl(url.endsWith("/") ? url : url + "/");
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

getUrl() now always runs the value through getEffectiveIdmUrl(...), which will replace the URL with one derived from openidm.context.path whenever the normalized URL equals IDM_URL_DEFAULT. This means a user explicitly passing --url http://localhost:8080/openidm/ (or .../openidm which gets normalized) can be unexpectedly overridden by the system property. --url should take precedence over the system property; consider only applying getEffectiveIdmUrl when the --url option was not explicitly provided (e.g., by using a sentinel absentValue and treating blank as ‘use default’).

Suggested change
return getEffectiveIdmUrl(url.endsWith("/") ? url : url + "/");
return url.endsWith("/") ? url : url + "/";

Copilot uses AI. Check for mistakes.
Comment on lines +97 to +100
static final String OPENIDM_CONTEXT_PATH_PROPERTY = "openidm.context.path";

/** Default REST context path. */
static final String OPENIDM_CONTEXT_PATH_DEFAULT = "/openidm";
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

The openidm.context.path property name/default and the path-normalization logic are now duplicated in multiple modules/classes (e.g., this component, ServletRegistrationSingleton, and RemoteCommandScope). To avoid drift (e.g., different trimming/validation rules over time), consider centralizing the constant + normalization in a shared location (such as a core utility or ServerConstants/IdentityServer) and reusing it from all call sites.

Suggested change
static final String OPENIDM_CONTEXT_PATH_PROPERTY = "openidm.context.path";
/** Default REST context path. */
static final String OPENIDM_CONTEXT_PATH_DEFAULT = "/openidm";
static final String OPENIDM_CONTEXT_PATH_PROPERTY = ServerConstants.OPENIDM_CONTEXT_PATH_PROPERTY;
/** Default REST context path. */
static final String OPENIDM_CONTEXT_PATH_DEFAULT = ServerConstants.OPENIDM_CONTEXT_PATH_DEFAULT;

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