>Velocity version? The latest version ie 2.0.
>When you say you "shut down the container (tomcat)", >can you be more specific? Do you bounce the >application, or do you >terminate Tomcat and the JVM, >etc.? Terminate tomcat shutdown.sh and then restart it. >Did you write your own WebappResourceLoader (and if >so, why)? Its a bit application so I do have my own version. I did read on a list that it was an issue. Think Nathan answered the post??? Maybe I have missed something in the code? public class WebappResourceLoader extends ResourceLoader { private static Log log = LogFactory.getLog(WebappResourceLoader.class); // The root paths for templates (relative to webapp's root). protected String[] paths = null; protected HashMap<String, String> templatePaths = null; protected ServletContext servletContext = null; /** * This is abstract in the base class, so we need it. NOTE: this expects * that the ServletContext has already been placed in the runtime's * application attributes under its full class name (i.e. * "javax.servlet.ServletContext"). * * @param configuration * the configuration */ @Override public void init(ExtProperties configuration) { if (log.isDebugEnabled()) log.debug("WebappResourceLoader: initialization starting."); // get configured paths paths = configuration.getStringArray("path"); if (paths == null || paths.length == 0) { paths = new String[1]; paths[0] = "/"; } else { // make sure the paths end with a "/" for (int i = 0; i < paths.length; i++) { if (!paths[i].endsWith("/")) { paths[i] += "/"; } if (log.isDebugEnabled()) log.debug("WebappResourceLoader: added template path - '" + paths[i] + "'"); } } // Try out default servletContext = EventsContext.getServletContext(); // get the ServletContext if (servletContext == null) { Object obj = rsvc .getApplicationAttribute(ServletContext.class.getName() ); if (obj instanceof ServletContext) { servletContext = (ServletContext) obj; } else { log.error( "WebappResourceLoader: unable to retrieve ServletContext"); } } if (log.isDebugEnabled()) { for (int i = 0; i < paths.length; i++) { log.debug("Servlet Context = " + servletContext.getRealPath(paths[i])); } } // init the template paths map templatePaths = new HashMap<String, String>(); if (log.isDebugEnabled()) log.debug("WebappResourceLoader: initialization complete."); } /** * Get an InputStream so that the Runtime can build a template with it. * * @param name * name of template to get * @param encoding * the encoding * * @return InputStream containing the template * * @throws ResourceNotFoundException * if template not found in classpath. */ @Override public Reader getResourceReader(String name, String encoding) throws ResourceNotFoundException { // public synchronized InputStream getResourceStream(String name) // throws ResourceNotFoundException { InputStream result = null; Exception exception = null; if (name == null || name.length() == 0) { throw new ResourceNotFoundException( "WebappResourceLoader: No template name provided"); } // names are <template>:<deviceType> // loading events_macros.vm etc will not have the type so only check for // one. String[] split = name.split(":", 2); if (split.length < 1) { throw new ResourceNotFoundException("Invalid ThemeRL key " + name); } String savedPath = (String) templatePaths.get(name); if (savedPath != null) { result = servletContext.getResourceAsStream(savedPath + split[0]); } if (result == null) { for (int i = 0; i < paths.length; i++) { String path = paths[i] + split[0]; try { result = servletContext.getResourceAsStream(path); // save the path and exit the loop if we found the template if (result != null) { templatePaths.put(name, paths[i]); break; } } catch (NullPointerException npe) { // no servletContext was set, whine about it! throw npe; } catch (Exception e) { // only save the first one for later throwing if (exception == null) { if (log.isDebugEnabled()) { log.debug("WebappResourceLoader: Could not load " + path, e); } exception = e; } } } } // If we never found the template if (result == null) { String msg = "WebappResourceLoader: Resource '" + name + "' not found on class path."; // convert to a general Velocity ResourceNotFoundException if (exception == null) { throw new ResourceNotFoundException(msg); } else { msg += " Due to: " + exception; throw new ResourceNotFoundException(msg, exception); } } return new BufferedReader(new InputStreamReader(result)); } /** * Gets the cached file. * * @param rootPath * the root path * @param fileName * the file name * * @return the cached file */ private File getCachedFile(String rootPath, String fileName) { // We do this when we cache a resource, so do it again to ensure a match while (fileName.startsWith("/")) { fileName = fileName.substring(1); } String savedPath = (String) templatePaths.get(fileName); // names are <template>:<deviceType> // loading events_macros.vm etc will not have the type so only check for // one. String[] split = fileName.split(":", 2); return new File(rootPath + savedPath, split[0]); } /** * Checks to see if a resource has been deleted, moved or modified. When * using the resource.loader.cache=true option * * @param resource * Resource The resource to check for modification * * @return boolean True if the resource has been modified */ public boolean isSourceModified(Resource resource) { String rootPath = servletContext.getRealPath("/"); if (rootPath == null) { // RootPath is null if the servlet container cannot translate the // virtual path to a real path for any reason (such as when the // content is being made available from a .war archive) return false; } // first, try getting the previously found file String fileName = resource.getName(); File cachedFile = getCachedFile(rootPath, fileName); if (!cachedFile.exists()) { // then the source has been moved and/or deleted return true; } /* * Check to see if the file can now be found elsewhere before it is * found in the previously saved path */ File currentFile = null; for (int i = 0; i < paths.length; i++) { currentFile = new File(rootPath + paths[i], fileName); if (currentFile.canRead()) { // stop at the first resource found (just like in // getResourceStream()) break; } } // If the current is the cached and it is readable if (cachedFile.equals(currentFile) && cachedFile.canRead()) { // then (and only then) do we compare the last modified values return (cachedFile.lastModified() != resource.getLastModified()); } else { // We found a new file for the resource or the resource is no longer // readable. return true; } } /** * Checks to see when a resource was last modified * * @param resource * Resource the resource to check * * @return long The time when the resource was last modified or 0 if the * file can't be read */ public long getLastModified(Resource resource) { String rootPath = servletContext.getRealPath("/"); if (rootPath == null) { // RootPath is null if the servlet container cannot translate the // virtual path to a real path for any reason (such as when the // content is being made available from a .war archive) return 0; } File cachedFile = getCachedFile(rootPath, resource.getName()); if (cachedFile.canRead()) { return cachedFile.lastModified(); } else { return 0; } } } On 4 January 2017 at 16:04, Christopher Schultz < ch...@christopherschultz.net> wrote: > Greg, > > On 1/4/17 8:43 AM, Greg Huber wrote: > > The was one issue that has been around for ages, and I am not sure if it > is > > possible to fix it. > > > > If I have added a new macro into a velocity template file loaded via a > > resource loader, I have to shut down the container (tomcat) and restart > for > > it to be picked up. I will allow the contents of the macro to be changed > > but not a new macro. I did try to see if I could fix it but without much > > success. > > > > my velocity.properties : > > .. > > webapp.resource.loader.description=Webapp Resource Loader > > webapp.resource.loader.class=rendering.velocity.WebappResourceLoader > > webapp.resource.loader.cache=true > > webapp.resource.loader.path=/WEB-INF/velocity,/WEB-INF/ > velocity/templates,/WEB-INF/velocity/templates/feeds,/WEB- > INF/velocity/templates/emails > > ... > > > > If you are now familiar with the code you might be in a better position > to > > see why I have to shut down for it to be picked up. > > Velocity version? > > When you say you "shut down the container (tomcat)", can you be more > specific? Do you bounce the application, or do you terminate Tomcat and > the JVM, etc.? > > Did you write your own WebappResourceLoader (and if so, why)? > > -chris > >