This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch WW-5659-lazy-params-request-scoping in repository https://gitbox.apache.org/repos/asf/struts.git
commit c35483c65eab332e0635f508399804732bf36d98 Author: Lukasz Lenart <[email protected]> AuthorDate: Mon Jul 27 10:18:42 2026 +0200 WW-5659 feat(core): add InterceptorParams contract and DisableParams holder Co-Authored-By: Claude Opus 5 <[email protected]> --- .../apache/struts2/interceptor/DisableParams.java | 51 ++++++++++++++++++ .../struts2/interceptor/InterceptorParams.java | 43 ++++++++++++++++ .../struts2/interceptor/DisableParamsTest.java | 60 ++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/core/src/main/java/org/apache/struts2/interceptor/DisableParams.java b/core/src/main/java/org/apache/struts2/interceptor/DisableParams.java new file mode 100644 index 000000000..aa3446787 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/DisableParams.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.interceptor; + +/** + * Opt-in support for the {@code disabled} interceptor parameter. + * <p> + * Interceptors implementing {@link WithLazyParams} must have their params holder extend this + * class to support {@code <param name="disabled">...</param>}; there is deliberately no + * fallback to the interceptor instance, which would reintroduce shared mutable state. + * + * @since 7.3.0 + */ +public class DisableParams implements InterceptorParams { + + private boolean disabled; + + public DisableParams() { + } + + protected DisableParams(DisableParams other) { + this.disabled = other.disabled; + } + + /** + * @param disable if {@code true}, execution of the interceptor is skipped for this invocation + */ + public void setDisabled(String disable) { + this.disabled = Boolean.parseBoolean(disable); + } + + public boolean isDisabled() { + return disabled; + } +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/InterceptorParams.java b/core/src/main/java/org/apache/struts2/interceptor/InterceptorParams.java new file mode 100644 index 000000000..68cf3e2ba --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/InterceptorParams.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.interceptor; + +/** + * Contract for an object holding the parameters of a single interceptor. + * <p> + * Implementations are per-invocation value objects: the framework resolves configured + * parameters into a fresh instance for each action invocation, so nothing is written back + * onto the interceptor, which stays immutable after {@link Interceptor#init()}. + * + * @since 7.3.0 + */ +public interface InterceptorParams { + + /** + * Called when a {@code ${...}} parameter could not be resolved for the current invocation. + * The framework skips the write, leaving the seeded configuration value in place, and + * notifies the holder so it can decide how to degrade. + * <p> + * The default implementation does nothing. + * + * @param paramName name of the parameter that could not be resolved + */ + default void unresolved(String paramName) { + } +} diff --git a/core/src/test/java/org/apache/struts2/interceptor/DisableParamsTest.java b/core/src/test/java/org/apache/struts2/interceptor/DisableParamsTest.java new file mode 100644 index 000000000..3a41b0b84 --- /dev/null +++ b/core/src/test/java/org/apache/struts2/interceptor/DisableParamsTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.interceptor; + +import junit.framework.TestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DisableParamsTest extends TestCase { + + public void testDisabledDefaultsToFalse() { + assertThat(new DisableParams().isDisabled()).isFalse(); + } + + public void testSetDisabledParsesStringValue() { + DisableParams params = new DisableParams(); + params.setDisabled("true"); + assertThat(params.isDisabled()).isTrue(); + + params.setDisabled("false"); + assertThat(params.isDisabled()).isFalse(); + } + + public void testSetDisabledTreatsNonBooleanTextAsFalse() { + DisableParams params = new DisableParams(); + params.setDisabled("yes"); + assertThat(params.isDisabled()).isFalse(); + } + + public void testCopyConstructorCarriesDisabledFlag() { + DisableParams original = new DisableParams(); + original.setDisabled("true"); + + DisableParams copy = new DisableParams(original); + + assertThat(copy.isDisabled()).isTrue(); + } + + public void testUnresolvedDefaultsToNoOp() { + DisableParams params = new DisableParams(); + params.unresolved("someParam"); // must not throw + assertThat(params.isDisabled()).isFalse(); + } +}
