From 2926c8352b0320d0ae72d42d832c62fe435c6a8e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 19:47:24 +0000
Subject: [PATCH 1/7] Initial plan
From b28d1b8eded83dd35c7976279ad2377f940ca3b6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 19:55:10 +0000
Subject: [PATCH 2/7] Upgrade Spring Framework to 5.3.18 with compatibility
layer
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
oai-pmh_data_provider/pom.xml | 10 +-
pom.xml | 18 +--
treebase-web/pom.xml | 7 ++
.../ShortPathUrlFilenameViewController.java | 24 +++-
.../multiaction/MultiActionController.java | 57 ++++++++++
.../view/velocity/VelocityConfigurer.java | 88 +++++++++++++++
.../view/velocity/VelocityViewResolver.java | 103 ++++++++++++++++++
7 files changed, 291 insertions(+), 16 deletions(-)
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
diff --git a/oai-pmh_data_provider/pom.xml b/oai-pmh_data_provider/pom.xml
index 766504b0..0d4243d7 100644
--- a/oai-pmh_data_provider/pom.xml
+++ b/oai-pmh_data_provider/pom.xml
@@ -39,31 +39,31 @@
org.springframework
spring-core
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-beans
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-context
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-webmvc
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-test
- 4.3.30.RELEASE
+ 5.3.18
test
diff --git a/pom.xml b/pom.xml
index 745b12f3..b4ff633b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -75,55 +75,55 @@
org.springframework
spring-core
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-beans
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-context
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-jdbc
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-orm
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-tx
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-webmvc
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-context-support
- 4.3.30.RELEASE
+ 5.3.18
org.springframework
spring-test
- 4.3.30.RELEASE
+ 5.3.18
test
diff --git a/treebase-web/pom.xml b/treebase-web/pom.xml
index 930fe65d..5413ba15 100644
--- a/treebase-web/pom.xml
+++ b/treebase-web/pom.xml
@@ -340,6 +340,13 @@
velocity-tools-view
1.1
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ 2.3
+
com.sun.jersey
diff --git a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
index b6d88bb6..fc660d87 100644
--- a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
+++ b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
@@ -2,7 +2,6 @@
package org.cipres.treebase.web.controllers;
import org.springframework.web.servlet.mvc.UrlFilenameViewController;
-import org.springframework.web.util.WebUtils;
/**
* A subclass of Spring UrlFilenameViewController. The UrlFilenameViewController class in Spring 2
@@ -34,7 +33,28 @@ public ShortPathUrlFilenameViewController() {
*/
@Override
protected String extractViewNameFromUrlPath(String pUri) {
- return WebUtils.extractFilenameFromUrlPath(pUri);
+ return extractFilenameFromUrlPath(pUri);
+ }
+
+ /**
+ * Extract the filename from the given URL path.
+ * This replaces the removed WebUtils.extractFilenameFromUrlPath method.
+ */
+ private String extractFilenameFromUrlPath(String urlPath) {
+ int begin = urlPath.lastIndexOf('/') + 1;
+ int end = urlPath.indexOf(';');
+ if (end == -1) {
+ end = urlPath.indexOf('?');
+ if (end == -1) {
+ end = urlPath.length();
+ }
+ }
+ String filename = urlPath.substring(begin, end);
+ int dotIndex = filename.lastIndexOf('.');
+ if (dotIndex != -1) {
+ filename = filename.substring(0, dotIndex);
+ }
+ return filename;
}
}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
new file mode 100644
index 00000000..e5a12471
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
@@ -0,0 +1,57 @@
+package org.springframework.web.servlet.mvc.multiaction;
+
+import java.lang.reflect.Method;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.AbstractController;
+
+/**
+ * Custom MultiActionController for Spring 5.x compatibility.
+ * This class provides multi-action controller functionality that was removed from Spring 5.x.
+ *
+ * Note: This is a simplified implementation that maintains backward compatibility.
+ * In Spring 5.x, the recommended approach is to use @Controller with @RequestMapping.
+ */
+public class MultiActionController extends AbstractController {
+
+ @Override
+ protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ String methodName = getMethodName(request);
+ Method method = findMethod(methodName);
+
+ if (method == null) {
+ throw new NoSuchMethodException("No method found with name: " + methodName);
+ }
+
+ return (ModelAndView) method.invoke(this, request, response);
+ }
+
+ /**
+ * Determine the method name from the request.
+ * Default implementation looks for a "method" parameter.
+ */
+ protected String getMethodName(HttpServletRequest request) {
+ String methodName = request.getParameter("method");
+ if (methodName == null || methodName.isEmpty()) {
+ // Fallback to a default method name
+ methodName = "defaultMethod";
+ }
+ return methodName;
+ }
+
+ /**
+ * Find a method by name that matches the MultiActionController signature.
+ */
+ protected Method findMethod(String methodName) {
+ try {
+ return getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
+ } catch (NoSuchMethodException e) {
+ // Method not found
+ return null;
+ }
+ }
+}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
new file mode 100644
index 00000000..97943dfb
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
@@ -0,0 +1,88 @@
+package org.springframework.web.servlet.view.velocity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.VelocityException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.web.context.ServletContextAware;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Custom VelocityConfigurer for Spring 5.x compatibility.
+ * This class provides Velocity template engine configuration that was removed from Spring 5.x.
+ */
+public class VelocityConfigurer implements InitializingBean, ResourceLoaderAware, ServletContextAware {
+
+ private VelocityEngine velocityEngine;
+ private String resourceLoaderPath;
+ private Properties velocityProperties;
+ private ResourceLoader resourceLoader;
+ private ServletContext servletContext;
+
+ public void setResourceLoaderPath(String resourceLoaderPath) {
+ this.resourceLoaderPath = resourceLoaderPath;
+ }
+
+ public void setVelocityProperties(Properties velocityProperties) {
+ this.velocityProperties = velocityProperties;
+ }
+
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ public VelocityEngine getVelocityEngine() {
+ return this.velocityEngine;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ this.velocityEngine = createVelocityEngine();
+ }
+
+ protected VelocityEngine createVelocityEngine() throws Exception {
+ VelocityEngine velocityEngine = new VelocityEngine();
+
+ Properties props = new Properties();
+
+ // Set default properties - use string literals instead of constants
+ props.setProperty("resource.loaders", "webapp");
+ props.setProperty("resource.loader.webapp.class",
+ "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+
+ if (resourceLoaderPath != null) {
+ // Configure file resource loader for webapp paths
+ props.setProperty("resource.loaders", "file");
+ props.setProperty("resource.loader.file.class",
+ "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
+
+ String path = resourceLoaderPath;
+ if (servletContext != null && !path.startsWith("/")) {
+ path = "/" + path;
+ }
+ if (servletContext != null) {
+ path = servletContext.getRealPath(path);
+ }
+ props.setProperty("resource.loader.file.path", path);
+ }
+
+ // Add any custom properties
+ if (velocityProperties != null) {
+ props.putAll(velocityProperties);
+ }
+
+ velocityEngine.init(props);
+ return velocityEngine;
+ }
+}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
new file mode 100644
index 00000000..f60a244d
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
@@ -0,0 +1,103 @@
+package org.springframework.web.servlet.view.velocity;
+
+import java.io.StringWriter;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.view.AbstractUrlBasedView;
+
+/**
+ * Custom VelocityViewResolver for Spring 5.x compatibility.
+ * This class provides Velocity view resolution that was removed from Spring 5.x.
+ */
+public class VelocityViewResolver implements ViewResolver, InitializingBean {
+
+ private VelocityEngine velocityEngine;
+ private String prefix = "";
+ private String suffix = ".vm";
+ private String contentType = "text/html;charset=UTF-8";
+ private String encoding = "UTF-8";
+
+ public void setVelocityEngine(VelocityEngine velocityEngine) {
+ this.velocityEngine = velocityEngine;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = (prefix != null ? prefix : "");
+ }
+
+ public void setSuffix(String suffix) {
+ this.suffix = (suffix != null ? suffix : "");
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (this.velocityEngine == null) {
+ throw new IllegalArgumentException("Property 'velocityEngine' is required");
+ }
+ }
+
+ @Override
+ public View resolveViewName(String viewName, Locale locale) throws Exception {
+ return new VelocityView(prefix + viewName + suffix);
+ }
+
+ private class VelocityView implements View {
+ private final String templatePath;
+
+ public VelocityView(String templatePath) {
+ this.templatePath = templatePath;
+ }
+
+ @Override
+ public String getContentType() {
+ return contentType;
+ }
+
+ @Override
+ public void render(Map model, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ response.setContentType(getContentType());
+
+ Context velocityContext = new VelocityContext();
+
+ // Add model attributes to Velocity context
+ if (model != null) {
+ for (Map.Entry entry : model.entrySet()) {
+ velocityContext.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ // Add request, response, and session to context for compatibility
+ velocityContext.put("request", request);
+ velocityContext.put("response", response);
+ if (request.getSession(false) != null) {
+ velocityContext.put("session", request.getSession());
+ }
+
+ // Merge template
+ StringWriter writer = new StringWriter();
+ velocityEngine.mergeTemplate(templatePath, encoding, velocityContext, writer);
+
+ response.getWriter().write(writer.toString());
+ }
+ }
+}
From f20a0f2729e049ae5694ccdb4648c522c4b169d7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 20:02:12 +0000
Subject: [PATCH 3/7] Remove deprecated @TransactionConfiguration for Spring
5.x compatibility
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
.../src/test/java/org/cipres/treebase/dao/AbstractDAOTest.java | 2 --
.../java/org/cipres/treebase/service/AbstractServiceTest.java | 2 --
2 files changed, 4 deletions(-)
diff --git a/treebase-core/src/test/java/org/cipres/treebase/dao/AbstractDAOTest.java b/treebase-core/src/test/java/org/cipres/treebase/dao/AbstractDAOTest.java
index 1b57184f..a3078215 100644
--- a/treebase-core/src/test/java/org/cipres/treebase/dao/AbstractDAOTest.java
+++ b/treebase-core/src/test/java/org/cipres/treebase/dao/AbstractDAOTest.java
@@ -18,7 +18,6 @@
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@@ -39,7 +38,6 @@
"classpath:applicationContext-dao.xml",
"classpath:applicationContext-service.xml"
})
-@TransactionConfiguration(defaultRollback = true)
@Transactional
public abstract class AbstractDAOTest {
diff --git a/treebase-core/src/test/java/org/cipres/treebase/service/AbstractServiceTest.java b/treebase-core/src/test/java/org/cipres/treebase/service/AbstractServiceTest.java
index 0e68a8c3..bc3c469f 100644
--- a/treebase-core/src/test/java/org/cipres/treebase/service/AbstractServiceTest.java
+++ b/treebase-core/src/test/java/org/cipres/treebase/service/AbstractServiceTest.java
@@ -5,7 +5,6 @@
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -23,7 +22,6 @@
"classpath:applicationContext-dao.xml",
"classpath:applicationContext-service.xml"
})
-@TransactionConfiguration(defaultRollback = true)
@Transactional
public abstract class AbstractServiceTest {
From 964fcd3c65ba35050eb23b26b4aa5a2ecf87a238 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 20:05:31 +0000
Subject: [PATCH 4/7] Address code review feedback: Add missing properties and
improve error handling
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
.../ShortPathUrlFilenameViewController.java | 11 +++++
.../mvc/multiaction/MethodNameResolver.java | 19 ++++++++
.../multiaction/MultiActionController.java | 31 +++++++++----
.../NoSuchRequestHandlingMethodException.java | 24 ++++++++++
.../ParameterMethodNameResolver.java | 45 +++++++++++++++++++
.../view/velocity/VelocityConfigurer.java | 32 ++++++++-----
.../view/velocity/VelocityViewResolver.java | 28 ++++++++++++
7 files changed, 171 insertions(+), 19 deletions(-)
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MethodNameResolver.java
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/NoSuchRequestHandlingMethodException.java
create mode 100644 treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/ParameterMethodNameResolver.java
diff --git a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
index fc660d87..55429a8a 100644
--- a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
+++ b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
@@ -41,6 +41,10 @@ protected String extractViewNameFromUrlPath(String pUri) {
* This replaces the removed WebUtils.extractFilenameFromUrlPath method.
*/
private String extractFilenameFromUrlPath(String urlPath) {
+ if (urlPath == null || urlPath.isEmpty()) {
+ return "";
+ }
+
int begin = urlPath.lastIndexOf('/') + 1;
int end = urlPath.indexOf(';');
if (end == -1) {
@@ -49,6 +53,13 @@ private String extractFilenameFromUrlPath(String urlPath) {
end = urlPath.length();
}
}
+
+ // Ensure valid bounds
+ if (begin >= end || begin >= urlPath.length()) {
+ // Return the path as-is if we can't extract a valid filename
+ return urlPath.startsWith("/") ? urlPath.substring(1) : urlPath;
+ }
+
String filename = urlPath.substring(begin, end);
int dotIndex = filename.lastIndexOf('.');
if (dotIndex != -1) {
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MethodNameResolver.java b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MethodNameResolver.java
new file mode 100644
index 00000000..adc4f2e1
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MethodNameResolver.java
@@ -0,0 +1,19 @@
+package org.springframework.web.servlet.mvc.multiaction;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Interface for method name resolvers used by MultiActionController.
+ * This interface was removed in Spring 5.x but is recreated here for backward compatibility.
+ */
+public interface MethodNameResolver {
+
+ /**
+ * Return the method name for the given request.
+ *
+ * @param request the current HTTP request
+ * @return the name of the method to invoke
+ * @throws NoSuchRequestHandlingMethodException if no method name could be determined
+ */
+ String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException;
+}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
index e5a12471..1fc963a6 100644
--- a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/MultiActionController.java
@@ -16,6 +16,25 @@
*/
public class MultiActionController extends AbstractController {
+ private MethodNameResolver methodNameResolver;
+
+ /**
+ * Set the MethodNameResolver to use for determining the handler method name.
+ */
+ public void setMethodNameResolver(MethodNameResolver methodNameResolver) {
+ this.methodNameResolver = methodNameResolver;
+ }
+
+ /**
+ * Get the current MethodNameResolver.
+ */
+ public MethodNameResolver getMethodNameResolver() {
+ if (this.methodNameResolver == null) {
+ this.methodNameResolver = new ParameterMethodNameResolver();
+ }
+ return this.methodNameResolver;
+ }
+
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
@@ -31,16 +50,10 @@ protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpSer
}
/**
- * Determine the method name from the request.
- * Default implementation looks for a "method" parameter.
+ * Determine the method name from the request using the configured MethodNameResolver.
*/
- protected String getMethodName(HttpServletRequest request) {
- String methodName = request.getParameter("method");
- if (methodName == null || methodName.isEmpty()) {
- // Fallback to a default method name
- methodName = "defaultMethod";
- }
- return methodName;
+ protected String getMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
+ return getMethodNameResolver().getHandlerMethodName(request);
}
/**
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/NoSuchRequestHandlingMethodException.java b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/NoSuchRequestHandlingMethodException.java
new file mode 100644
index 00000000..d33951d8
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/NoSuchRequestHandlingMethodException.java
@@ -0,0 +1,24 @@
+package org.springframework.web.servlet.mvc.multiaction;
+
+/**
+ * Exception thrown when no handler method can be found for a request.
+ * This exception was removed in Spring 5.x but is recreated here for backward compatibility.
+ */
+public class NoSuchRequestHandlingMethodException extends Exception {
+
+ private final String methodName;
+
+ public NoSuchRequestHandlingMethodException(String methodName) {
+ super("No handler method '" + methodName + "' found");
+ this.methodName = methodName;
+ }
+
+ public NoSuchRequestHandlingMethodException(String message, String methodName) {
+ super(message);
+ this.methodName = methodName;
+ }
+
+ public String getMethodName() {
+ return methodName;
+ }
+}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/ParameterMethodNameResolver.java b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/ParameterMethodNameResolver.java
new file mode 100644
index 00000000..413d2bf1
--- /dev/null
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/mvc/multiaction/ParameterMethodNameResolver.java
@@ -0,0 +1,45 @@
+package org.springframework.web.servlet.mvc.multiaction;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Implementation of MethodNameResolver that determines the method name from a request parameter.
+ * This class was removed in Spring 5.x but is recreated here for backward compatibility.
+ */
+public class ParameterMethodNameResolver implements MethodNameResolver {
+
+ public static final String DEFAULT_PARAM_NAME = "action";
+
+ private String paramName = DEFAULT_PARAM_NAME;
+ private String defaultMethodName;
+
+ /**
+ * Set the name of the parameter that contains the method name.
+ * Default is "action".
+ */
+ public void setParamName(String paramName) {
+ this.paramName = paramName;
+ }
+
+ /**
+ * Set the default method name to use when no parameter is specified.
+ */
+ public void setDefaultMethodName(String defaultMethodName) {
+ this.defaultMethodName = defaultMethodName;
+ }
+
+ @Override
+ public String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
+ String methodName = request.getParameter(this.paramName);
+
+ if (methodName == null || methodName.trim().isEmpty()) {
+ if (this.defaultMethodName != null) {
+ return this.defaultMethodName;
+ }
+ throw new NoSuchRequestHandlingMethodException(
+ "No method name found in request parameter '" + this.paramName + "'", "");
+ }
+
+ return methodName;
+ }
+}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
index 97943dfb..8e3de1dd 100644
--- a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
@@ -56,11 +56,6 @@ protected VelocityEngine createVelocityEngine() throws Exception {
Properties props = new Properties();
- // Set default properties - use string literals instead of constants
- props.setProperty("resource.loaders", "webapp");
- props.setProperty("resource.loader.webapp.class",
- "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
-
if (resourceLoaderPath != null) {
// Configure file resource loader for webapp paths
props.setProperty("resource.loaders", "file");
@@ -68,13 +63,30 @@ protected VelocityEngine createVelocityEngine() throws Exception {
"org.apache.velocity.runtime.resource.loader.FileResourceLoader");
String path = resourceLoaderPath;
- if (servletContext != null && !path.startsWith("/")) {
- path = "/" + path;
- }
if (servletContext != null) {
- path = servletContext.getRealPath(path);
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ String realPath = servletContext.getRealPath(path);
+ // Handle case where getRealPath returns null (e.g., running from WAR)
+ if (realPath != null) {
+ path = realPath;
+ } else {
+ // Fallback to classpath loader if real path cannot be determined
+ props.setProperty("resource.loaders", "classpath");
+ props.setProperty("resource.loader.classpath.class",
+ "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ }
+ }
+
+ if (props.getProperty("resource.loaders").equals("file")) {
+ props.setProperty("resource.loader.file.path", path);
}
- props.setProperty("resource.loader.file.path", path);
+ } else {
+ // Set default classpath loader when no path is specified
+ props.setProperty("resource.loaders", "classpath");
+ props.setProperty("resource.loader.classpath.class",
+ "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
}
// Add any custom properties
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
index f60a244d..24a93c6e 100644
--- a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
@@ -26,6 +26,8 @@ public class VelocityViewResolver implements ViewResolver, InitializingBean {
private String suffix = ".vm";
private String contentType = "text/html;charset=UTF-8";
private String encoding = "UTF-8";
+ private boolean exposeRequestAttributes = false;
+ private boolean exposeSessionAttributes = false;
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
@@ -47,6 +49,14 @@ public void setEncoding(String encoding) {
this.encoding = encoding;
}
+ public void setExposeRequestAttributes(boolean exposeRequestAttributes) {
+ this.exposeRequestAttributes = exposeRequestAttributes;
+ }
+
+ public void setExposeSessionAttributes(boolean exposeSessionAttributes) {
+ this.exposeSessionAttributes = exposeSessionAttributes;
+ }
+
@Override
public void afterPropertiesSet() throws Exception {
if (this.velocityEngine == null) {
@@ -86,6 +96,24 @@ public void render(Map model, HttpServletRequest request, HttpServlet
}
}
+ // Add request attributes if configured
+ if (exposeRequestAttributes && request != null) {
+ java.util.Enumeration attrNames = request.getAttributeNames();
+ while (attrNames.hasMoreElements()) {
+ String attrName = attrNames.nextElement();
+ velocityContext.put(attrName, request.getAttribute(attrName));
+ }
+ }
+
+ // Add session attributes if configured
+ if (exposeSessionAttributes && request != null && request.getSession(false) != null) {
+ java.util.Enumeration attrNames = request.getSession().getAttributeNames();
+ while (attrNames.hasMoreElements()) {
+ String attrName = attrNames.nextElement();
+ velocityContext.put(attrName, request.getSession().getAttribute(attrName));
+ }
+ }
+
// Add request, response, and session to context for compatibility
velocityContext.put("request", request);
velocityContext.put("response", response);
From a204e2876155371f1dd7186ad74c77b2b46bc75f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 20:08:53 +0000
Subject: [PATCH 5/7] Improve bounds checking and refactor loader configuration
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
.../ShortPathUrlFilenameViewController.java | 2 +-
.../view/velocity/VelocityConfigurer.java | 37 ++++++++-----------
2 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
index 55429a8a..789f9b9b 100644
--- a/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
+++ b/treebase-web/src/main/java/org/cipres/treebase/web/controllers/ShortPathUrlFilenameViewController.java
@@ -55,7 +55,7 @@ private String extractFilenameFromUrlPath(String urlPath) {
}
// Ensure valid bounds
- if (begin >= end || begin >= urlPath.length()) {
+ if (begin < 0 || begin >= urlPath.length() || end > urlPath.length() || begin >= end) {
// Return the path as-is if we can't extract a valid filename
return urlPath.startsWith("/") ? urlPath.substring(1) : urlPath;
}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
index 8e3de1dd..9e12dae0 100644
--- a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
@@ -56,37 +56,32 @@ protected VelocityEngine createVelocityEngine() throws Exception {
Properties props = new Properties();
+ // Determine loader type and path
+ String loaderType = "classpath";
+ String loaderClass = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
+ String loaderPath = null;
+
if (resourceLoaderPath != null) {
- // Configure file resource loader for webapp paths
- props.setProperty("resource.loaders", "file");
- props.setProperty("resource.loader.file.class",
- "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
-
String path = resourceLoaderPath;
if (servletContext != null) {
if (!path.startsWith("/")) {
path = "/" + path;
}
String realPath = servletContext.getRealPath(path);
- // Handle case where getRealPath returns null (e.g., running from WAR)
+ // Use file loader if real path is available
if (realPath != null) {
- path = realPath;
- } else {
- // Fallback to classpath loader if real path cannot be determined
- props.setProperty("resource.loaders", "classpath");
- props.setProperty("resource.loader.classpath.class",
- "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ loaderType = "file";
+ loaderClass = "org.apache.velocity.runtime.resource.loader.FileResourceLoader";
+ loaderPath = realPath;
}
}
-
- if (props.getProperty("resource.loaders").equals("file")) {
- props.setProperty("resource.loader.file.path", path);
- }
- } else {
- // Set default classpath loader when no path is specified
- props.setProperty("resource.loaders", "classpath");
- props.setProperty("resource.loader.classpath.class",
- "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ }
+
+ // Set loader configuration
+ props.setProperty("resource.loaders", loaderType);
+ props.setProperty("resource.loader." + loaderType + ".class", loaderClass);
+ if (loaderPath != null) {
+ props.setProperty("resource.loader." + loaderType + ".path", loaderPath);
}
// Add any custom properties
From f1314eb3d9f103ef663ed3321741b5e1efbed850 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 20:28:52 +0000
Subject: [PATCH 6/7] Add Velocity compatibility classes to OAI-PMH module
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
.../data_provider_web/pom.xml | 6 +
.../view/velocity/VelocityConfigurer.java | 95 +++++++++++++
.../view/velocity/VelocityViewResolver.java | 131 ++++++++++++++++++
3 files changed, 232 insertions(+)
create mode 100644 oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
create mode 100644 oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
diff --git a/oai-pmh_data_provider/data_provider_web/pom.xml b/oai-pmh_data_provider/data_provider_web/pom.xml
index 8254d24b..e39def6d 100644
--- a/oai-pmh_data_provider/data_provider_web/pom.xml
+++ b/oai-pmh_data_provider/data_provider_web/pom.xml
@@ -301,6 +301,12 @@
velocity-tools-view
1.1
+
+
+ org.apache.velocity
+ velocity-engine-core
+ 2.3
+
org.cipres.treebase
treebase-core
diff --git a/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
new file mode 100644
index 00000000..9e12dae0
--- /dev/null
+++ b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
@@ -0,0 +1,95 @@
+package org.springframework.web.servlet.view.velocity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.VelocityException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.web.context.ServletContextAware;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Custom VelocityConfigurer for Spring 5.x compatibility.
+ * This class provides Velocity template engine configuration that was removed from Spring 5.x.
+ */
+public class VelocityConfigurer implements InitializingBean, ResourceLoaderAware, ServletContextAware {
+
+ private VelocityEngine velocityEngine;
+ private String resourceLoaderPath;
+ private Properties velocityProperties;
+ private ResourceLoader resourceLoader;
+ private ServletContext servletContext;
+
+ public void setResourceLoaderPath(String resourceLoaderPath) {
+ this.resourceLoaderPath = resourceLoaderPath;
+ }
+
+ public void setVelocityProperties(Properties velocityProperties) {
+ this.velocityProperties = velocityProperties;
+ }
+
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ public VelocityEngine getVelocityEngine() {
+ return this.velocityEngine;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ this.velocityEngine = createVelocityEngine();
+ }
+
+ protected VelocityEngine createVelocityEngine() throws Exception {
+ VelocityEngine velocityEngine = new VelocityEngine();
+
+ Properties props = new Properties();
+
+ // Determine loader type and path
+ String loaderType = "classpath";
+ String loaderClass = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
+ String loaderPath = null;
+
+ if (resourceLoaderPath != null) {
+ String path = resourceLoaderPath;
+ if (servletContext != null) {
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ String realPath = servletContext.getRealPath(path);
+ // Use file loader if real path is available
+ if (realPath != null) {
+ loaderType = "file";
+ loaderClass = "org.apache.velocity.runtime.resource.loader.FileResourceLoader";
+ loaderPath = realPath;
+ }
+ }
+ }
+
+ // Set loader configuration
+ props.setProperty("resource.loaders", loaderType);
+ props.setProperty("resource.loader." + loaderType + ".class", loaderClass);
+ if (loaderPath != null) {
+ props.setProperty("resource.loader." + loaderType + ".path", loaderPath);
+ }
+
+ // Add any custom properties
+ if (velocityProperties != null) {
+ props.putAll(velocityProperties);
+ }
+
+ velocityEngine.init(props);
+ return velocityEngine;
+ }
+}
diff --git a/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
new file mode 100644
index 00000000..24a93c6e
--- /dev/null
+++ b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
@@ -0,0 +1,131 @@
+package org.springframework.web.servlet.view.velocity;
+
+import java.io.StringWriter;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.view.AbstractUrlBasedView;
+
+/**
+ * Custom VelocityViewResolver for Spring 5.x compatibility.
+ * This class provides Velocity view resolution that was removed from Spring 5.x.
+ */
+public class VelocityViewResolver implements ViewResolver, InitializingBean {
+
+ private VelocityEngine velocityEngine;
+ private String prefix = "";
+ private String suffix = ".vm";
+ private String contentType = "text/html;charset=UTF-8";
+ private String encoding = "UTF-8";
+ private boolean exposeRequestAttributes = false;
+ private boolean exposeSessionAttributes = false;
+
+ public void setVelocityEngine(VelocityEngine velocityEngine) {
+ this.velocityEngine = velocityEngine;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = (prefix != null ? prefix : "");
+ }
+
+ public void setSuffix(String suffix) {
+ this.suffix = (suffix != null ? suffix : "");
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public void setExposeRequestAttributes(boolean exposeRequestAttributes) {
+ this.exposeRequestAttributes = exposeRequestAttributes;
+ }
+
+ public void setExposeSessionAttributes(boolean exposeSessionAttributes) {
+ this.exposeSessionAttributes = exposeSessionAttributes;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (this.velocityEngine == null) {
+ throw new IllegalArgumentException("Property 'velocityEngine' is required");
+ }
+ }
+
+ @Override
+ public View resolveViewName(String viewName, Locale locale) throws Exception {
+ return new VelocityView(prefix + viewName + suffix);
+ }
+
+ private class VelocityView implements View {
+ private final String templatePath;
+
+ public VelocityView(String templatePath) {
+ this.templatePath = templatePath;
+ }
+
+ @Override
+ public String getContentType() {
+ return contentType;
+ }
+
+ @Override
+ public void render(Map model, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ response.setContentType(getContentType());
+
+ Context velocityContext = new VelocityContext();
+
+ // Add model attributes to Velocity context
+ if (model != null) {
+ for (Map.Entry entry : model.entrySet()) {
+ velocityContext.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ // Add request attributes if configured
+ if (exposeRequestAttributes && request != null) {
+ java.util.Enumeration attrNames = request.getAttributeNames();
+ while (attrNames.hasMoreElements()) {
+ String attrName = attrNames.nextElement();
+ velocityContext.put(attrName, request.getAttribute(attrName));
+ }
+ }
+
+ // Add session attributes if configured
+ if (exposeSessionAttributes && request != null && request.getSession(false) != null) {
+ java.util.Enumeration attrNames = request.getSession().getAttributeNames();
+ while (attrNames.hasMoreElements()) {
+ String attrName = attrNames.nextElement();
+ velocityContext.put(attrName, request.getSession().getAttribute(attrName));
+ }
+ }
+
+ // Add request, response, and session to context for compatibility
+ velocityContext.put("request", request);
+ velocityContext.put("response", response);
+ if (request.getSession(false) != null) {
+ velocityContext.put("session", request.getSession());
+ }
+
+ // Merge template
+ StringWriter writer = new StringWriter();
+ velocityEngine.mergeTemplate(templatePath, encoding, velocityContext, writer);
+
+ response.getWriter().write(writer.toString());
+ }
+ }
+}
From 84d5e7b691ef90e6952dbc91578b68652c669915 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 23 Dec 2025 20:48:33 +0000
Subject: [PATCH 7/7] Auto-wire VelocityEngine from VelocityConfigurer bean
Co-authored-by: rvosa <106490+rvosa@users.noreply.github.com>
---
.../view/velocity/VelocityViewResolver.java | 20 ++++++++++++++++++-
.../view/velocity/VelocityViewResolver.java | 20 ++++++++++++++++++-
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
index 24a93c6e..eb5332c3 100644
--- a/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
+++ b/oai-pmh_data_provider/data_provider_web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
@@ -11,6 +11,8 @@
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
@@ -19,7 +21,7 @@
* Custom VelocityViewResolver for Spring 5.x compatibility.
* This class provides Velocity view resolution that was removed from Spring 5.x.
*/
-public class VelocityViewResolver implements ViewResolver, InitializingBean {
+public class VelocityViewResolver implements ViewResolver, InitializingBean, ApplicationContextAware {
private VelocityEngine velocityEngine;
private String prefix = "";
@@ -28,6 +30,7 @@ public class VelocityViewResolver implements ViewResolver, InitializingBean {
private String encoding = "UTF-8";
private boolean exposeRequestAttributes = false;
private boolean exposeSessionAttributes = false;
+ private ApplicationContext applicationContext;
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
@@ -57,8 +60,23 @@ public void setExposeSessionAttributes(boolean exposeSessionAttributes) {
this.exposeSessionAttributes = exposeSessionAttributes;
}
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
@Override
public void afterPropertiesSet() throws Exception {
+ // If velocityEngine is not set, try to get it from VelocityConfigurer
+ if (this.velocityEngine == null && this.applicationContext != null) {
+ try {
+ VelocityConfigurer configurer = this.applicationContext.getBean(VelocityConfigurer.class);
+ this.velocityEngine = configurer.getVelocityEngine();
+ } catch (Exception e) {
+ // VelocityConfigurer bean not found or error getting engine
+ }
+ }
+
if (this.velocityEngine == null) {
throw new IllegalArgumentException("Property 'velocityEngine' is required");
}
diff --git a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
index 24a93c6e..eb5332c3 100644
--- a/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
+++ b/treebase-web/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
@@ -11,6 +11,8 @@
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
@@ -19,7 +21,7 @@
* Custom VelocityViewResolver for Spring 5.x compatibility.
* This class provides Velocity view resolution that was removed from Spring 5.x.
*/
-public class VelocityViewResolver implements ViewResolver, InitializingBean {
+public class VelocityViewResolver implements ViewResolver, InitializingBean, ApplicationContextAware {
private VelocityEngine velocityEngine;
private String prefix = "";
@@ -28,6 +30,7 @@ public class VelocityViewResolver implements ViewResolver, InitializingBean {
private String encoding = "UTF-8";
private boolean exposeRequestAttributes = false;
private boolean exposeSessionAttributes = false;
+ private ApplicationContext applicationContext;
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
@@ -57,8 +60,23 @@ public void setExposeSessionAttributes(boolean exposeSessionAttributes) {
this.exposeSessionAttributes = exposeSessionAttributes;
}
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
@Override
public void afterPropertiesSet() throws Exception {
+ // If velocityEngine is not set, try to get it from VelocityConfigurer
+ if (this.velocityEngine == null && this.applicationContext != null) {
+ try {
+ VelocityConfigurer configurer = this.applicationContext.getBean(VelocityConfigurer.class);
+ this.velocityEngine = configurer.getVelocityEngine();
+ } catch (Exception e) {
+ // VelocityConfigurer bean not found or error getting engine
+ }
+ }
+
if (this.velocityEngine == null) {
throw new IllegalArgumentException("Property 'velocityEngine' is required");
}