From b5f0234a5b3f58fff2e4ad5ca09d6a7b516b4459 Mon Sep 17 00:00:00 2001 From: ste-gr <84541644+ste-gr@users.noreply.github.com> Date: Wed, 15 May 2024 04:00:10 +0200 Subject: [PATCH 1/2] Remove unused attribute in TilesRequestProcessor --- .../struts/tiles2/TilesRequestProcessor.java | 135 +++++++++--------- 1 file changed, 69 insertions(+), 66 deletions(-) diff --git a/tiles2/src/main/java/org/apache/struts/tiles2/TilesRequestProcessor.java b/tiles2/src/main/java/org/apache/struts/tiles2/TilesRequestProcessor.java index aaa12ffce..c470fed04 100644 --- a/tiles2/src/main/java/org/apache/struts/tiles2/TilesRequestProcessor.java +++ b/tiles2/src/main/java/org/apache/struts/tiles2/TilesRequestProcessor.java @@ -18,12 +18,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts.tiles2; import java.io.IOException; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,21 +41,22 @@ import org.slf4j.LoggerFactory; /** - *

RequestProcessor contains the processing logic that - * the Struts controller servlet performs as it receives each servlet request - * from the container.

- *

This processor subclasses the Struts RequestProcessor in order to intercept calls to forward - * or include. When such calls are done, the Tiles processor checks if the specified URI - * is a definition name. If true, the definition is retrieved and included. If - * false, the original URI is included or a forward is performed. - *

- * Actually, catching is done by overloading the following methods: + * RequestProcessor contains the processing logic that the + * Struts controller servlet performs as it receives each servlet request from + * the container. + *

This processor subclasses the Struts RequestProcessor in order to + * intercept calls to forward or include. When such calls are done, the Tiles + * processor checks if the specified URI is a definition name. If {@code true}, + * the definition is retrieved and included. If {@code false}, the original URI + * is included or a forward is performed.

+ *

Actually, catching is done by overloading the following methods: *

*

+ * * @since Struts 1.1 */ public class TilesRequestProcessor extends RequestProcessor { @@ -69,16 +68,12 @@ public class TilesRequestProcessor extends RequestProcessor { private transient final Logger log = LoggerFactory.getLogger(TilesRequestProcessor.class); - /** - * The used servlet context. - */ - protected ServletContext servletContext; - /** * Initialize this request processor instance. * - * @param servlet The ActionServlet we are associated with. + * @param servlet The ActionServlet we are associated with. * @param moduleConfig The ModuleConfig we are associated with. + * * @throws ServletException If an error occurs during initialization. */ public void init(ActionServlet servlet, ModuleConfig moduleConfig) @@ -88,21 +83,22 @@ public void init(ActionServlet servlet, ModuleConfig moduleConfig) } /** - * Process a Tile definition name. - * This method tries to process the parameter definitionName - * as a definition name. - * It returns true if a definition has been processed, or - * false otherwise. + * Process a Tile definition name. This method tries to process the + * parameter {@code definitionName} as a definition name. It returns + * {@code true} if a definition has been processed, or {@code false} + * otherwise. * * @param definitionName Definition name to insert. - * @param req Current page request. - * @param res Current page response. - * @throws IOException If something goes wrong during writing the - * definition. + * @param req Current page request. + * @param res Current page response. + * + * @return {@code true} if the method has processed uri as a definition + * name, [@code false} otherwise. + * + * @throws IOException If something goes wrong during writing the + * definition. * @throws ServletException If something goes wrong during the evaluation - * of the definition - * @return true if the method has processed uri as a - * definition name, false otherwise. + * of the definition */ protected boolean processTilesDefinition( String definitionName, @@ -139,16 +135,17 @@ protected boolean processTilesDefinition( } /** - * Do a forward using request dispatcher. - * Uri is a valid uri. If response has already been commited, do an include - * instead. - * @param uri Uri or Definition name to forward. - * @param request Current page request. + * Do a forward using request dispatcher. Uri is a valid uri. If response + * has already been commited, do an include instead. + * + * @param uri Uri or Definition name to forward. + * @param request Current page request. * @param response Current page response. - * @throws IOException If something goes wrong during writing the - * definition. + * + * @throws IOException If something goes wrong during writing the + * definition. * @throws ServletException If something goes wrong during the evaluation - * of the definition + * of the definition */ protected void doForward( String uri, @@ -165,18 +162,19 @@ protected void doForward( } /** - * Overloaded method from Struts' RequestProcessor. - * Forward or redirect to the specified destination by the specified - * mechanism. - * This method catches the Struts' actionForward call. It checks if the + * Overloaded method from Struts' RequestProcessor. Forward or redirect to + * the specified destination by the specified mechanism. + *

This method catches the Struts' actionForward call. It checks if the * actionForward is done on a Tiles definition name. If true, process the - * definition and insert it. If false, call the original parent's method. - * @param request The servlet request we are processing. + * definition and insert it. If false, call the original parent's + * method.

+ * + * @param request The servlet request we are processing. * @param response The servlet response we are creating. - * @param forward The ActionForward controlling where we go next. + * @param forward The ActionForward controlling where we go next. * - * @exception IOException if an input/output error occurs. - * @exception ServletException if a servlet exception occurs. + * @throws IOException if an input/output error occurs. + * @throws ServletException if a servlet exception occurs. */ protected void processForwardConfig( HttpServletRequest request, @@ -205,21 +203,23 @@ protected void processForwardConfig( } /** - * Catch the call to a module relative forward. - * If the specified uri is a tiles definition name, insert it. - * Otherwise, parent processing is called. - * Do a module relative forward to specified uri using request dispatcher. - * Uri is relative to the current module. The real uri is computed by - * prefixing the module name. - * This method is used internally and is not part of the public - * API. It is advised to not use it in subclasses. - * @param uri Module-relative URI to forward to. - * @param request Current page request. + * Catch the call to a module relative forward. If the specified uri is a + * tiles definition name, insert it. Otherwise, parent processing is + * called. Do a module relative forward to specified uri using request + * dispatcher. Uri is relative to the current module. The real uri is + * computed by prefixing the module name. + *

This method is used internally and is not part of the public + * API. It is advised to not use it in subclasses.

+ * + * @param uri Module-relative URI to forward to. + * @param request Current page request. * @param response Current page response. - * @throws IOException If something goes wrong during writing the - * definition. + * + * @throws IOException If something goes wrong during writing the + * definition. * @throws ServletException If something goes wrong during the evaluation - * of the definition + * of the definition + * * @since Struts 1.1 */ protected void internalModuleRelativeForward( @@ -239,15 +239,18 @@ protected void internalModuleRelativeForward( * Do a module relative include to specified uri using request dispatcher. * Uri is relative to the current module. The real uri is computed by * prefixing the module name. - * This method is used internally and is not part of the public - * API. It is advised to not use it in subclasses. - * @param uri Module-relative URI to forward to. - * @param request Current page request. + *

This method is used internally and is not part of the public + * API. It is advised to not use it in subclasses.

+ * + * @param uri Module-relative URI to forward to. + * @param request Current page request. * @param response Current page response. - * @throws IOException If something goes wrong during writing the - * definition. + * + * @throws IOException If something goes wrong during writing the + * definition. * @throws ServletException If something goes wrong during the evaluation - * of the definition + * of the definition + * * @since Struts 1.1 */ protected void internalModuleRelativeInclude( From 0521c024b172d792dbb112ff3f64dcaabfa1ec27 Mon Sep 17 00:00:00 2001 From: ste-gr <84541644+ste-gr@users.noreply.github.com> Date: Wed, 15 May 2024 04:00:56 +0200 Subject: [PATCH 2/2] Restore RedeployableActionServlet and ReloadDefinitionsAction --- .../tiles2/RedeployableActionServlet.java | 81 +++++++++++++++++++ .../actions/ReloadDefinitionsAction.java | 72 +++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 tiles2/src/main/java/org/apache/struts/tiles2/RedeployableActionServlet.java create mode 100644 tiles2/src/main/java/org/apache/struts/tiles2/actions/ReloadDefinitionsAction.java diff --git a/tiles2/src/main/java/org/apache/struts/tiles2/RedeployableActionServlet.java b/tiles2/src/main/java/org/apache/struts/tiles2/RedeployableActionServlet.java new file mode 100644 index 000000000..0a9ddc661 --- /dev/null +++ b/tiles2/src/main/java/org/apache/struts/tiles2/RedeployableActionServlet.java @@ -0,0 +1,81 @@ +/* + * $Id$ + * + * 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.struts.tiles2; + +import javax.servlet.ServletException; + +import org.apache.struts.Globals; +import org.apache.struts.action.ActionServlet; +import org.apache.struts.action.RequestProcessor; +import org.apache.struts.config.ModuleConfig; + +/** + * WebLogic (at least v6 and v7) attempts to serialize the TilesRequestProcessor + * when re-deploying the Webapp in development mode. The TilesRequestProcessor + * is not serializable, and loses the Tiles definitions. This results in + * NullPointerException and/or NotSerializableException when using the app after + * automatic redeploy. + *

+ * This bug report proposes a workaround for this problem, in the hope it will + * help others and maybe motivate an actual fix. + *

+ *

+ * The attached class extends the Struts Action servlet and fixes the problem by + * reloading the Tiles definitions when they have disappeared. + *

+ *

+ * For background discussion see + * STR-1937. + *

+ * + * @since 1.2.1 + */ +public class RedeployableActionServlet extends ActionServlet { + private static final long serialVersionUID = -3681534284719373420L; + + /** + * The request processor for Tiles definitions. + */ + private TilesRequestProcessor tileProcessor; + + protected synchronized RequestProcessor getRequestProcessor( + final ModuleConfig config) throws ServletException { + + if (tileProcessor != null) { + final TilesRequestProcessor processor = + (TilesRequestProcessor) super.getRequestProcessor(config); + return processor; + } + + // reset the request processor + final String requestProcessorKey = Globals.REQUEST_PROCESSOR_KEY + + config.getPrefix(); + getServletContext().removeAttribute(requestProcessorKey); + + // create a new request processor instance + final TilesRequestProcessor processor = + (TilesRequestProcessor) super.getRequestProcessor(config); + + tileProcessor = processor; + + return processor; + } +} \ No newline at end of file diff --git a/tiles2/src/main/java/org/apache/struts/tiles2/actions/ReloadDefinitionsAction.java b/tiles2/src/main/java/org/apache/struts/tiles2/actions/ReloadDefinitionsAction.java new file mode 100644 index 000000000..99770d707 --- /dev/null +++ b/tiles2/src/main/java/org/apache/struts/tiles2/actions/ReloadDefinitionsAction.java @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * 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.struts.tiles2.actions; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; + +/** + * This standard Action is for compatibility with + * {@code struts-tiles}. The configuration is now reloaded automatically. + */ +public class ReloadDefinitionsAction extends Action { + private static final long serialVersionUID = -7402180335252956248L; + + /** + * Process the specified HTTP request, and create the corresponding HTTP + * response (or forward to another web component that will create it), with + * provision for handling exceptions thrown by the business logic. + * + * @param mapping The ActionMapping used to select this instance + * @param form The optional ActionForm bean for this request (if any) + * @param request The HTTP request we are processing + * @param response The HTTP response we are creating + * + * @return The forward object. + * + * @throws Exception if the application business logic throws an exception + * + * @since Struts 1.1 + */ + public ActionForward execute(final ActionMapping mapping, + final ActionForm form, final HttpServletRequest request, + final HttpServletResponse response) throws Exception { + + response.setContentType("text/plain"); + + final PrintWriter writer = response.getWriter(); + + writer.println("OK"); + + writer.flush(); + writer.close(); + + return null; + } +} \ No newline at end of file