Finding template files in velocity - java

My webapp cannot find its template file. I have read the material in this article, but it doesn't seem to solve the problem. My velocity.properties file, which is installed into my WEB-INF directory, contains the lines
resource.loader=class
resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
and the Java servlet is
package test;
import java.io.*;
import javax.servlet.http.*;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.VelocityViewServlet;
import org.apache.velocity.app.Velocity;
import org.apache.commons.lang.StringEscapeUtils;
public class Recipes extends VelocityViewServlet {
public Template handleRequest(HttpServletRequest request,
HttpServletResponse response,
Context context) {
Velocity.init();
Template template=null;
try {
context.put("recipeList","r1");
template = Velocity.getTemplate("Recipes.vm");
} catch (Exception e) {
System.err.println("Exception caught: " + e.getMessage());
}
return template;
}
}
When I navigate to that URL, it fails. I've tried placing the vm file in the WEB-INF directory, in the classes subdirectory, in the lib directory, and in a jar in the lib directory. After things fail, catalina.out contains
Jan 12, 2013 6:35:25 PM org.apache.velocity.runtime.log.CommonsLogLogChute log
SEVERE: ResourceManager : unable to find resource 'Recipes.vm' in any resource loader.
Exception caught: Unable to find resource 'Recipes.vm'
and in localhost.log
Jan 12, 2013 6:35:25 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet recipes threw exception
java.lang.NullPointerException
at org.apache.velocity.tools.view.VelocityView.performMerge(VelocityView.java:942)
at org.apache.velocity.tools.view.VelocityView.merge(VelocityView.java:902)
at org.apache.velocity.tools.view.VelocityViewServlet.mergeTemplate(VelocityViewServlet.java:318)
at org.apache.velocity.tools.view.VelocityViewServlet.doRequest(VelocityViewServlet.java:220)
at org.apache.velocity.tools.view.VelocityViewServlet.doGet(VelocityViewServlet.java:182)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
Can someone explain to me what is going on? Thanks.

You should be using:
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
The resource loader "type" precedes the property name defining the loader class.
See the Velocity Developer Guide to Resource Loaders. Note that the answer you link to points at the correct docs but doesn't (appear) to include the correct config
(All this said, are you sure that's how you're supposed to use the VelocityViewServlet? I thought you'd normally request the *.vm file, do something like a fillContext, and be done with it.)
You're calling Velocity.init() from within a VelocityViewServlet, which is most likely not what you want to do. That aside, from the docs:
initialize the Velocity runtime engine, using the default properties of the Velocity distribution
If you do the following, the configuration I show works:
String propFile = getServletContext().getRealPath("/WEB-INF/velocity.properties");
Velocity.init(propFile);
That said, I'm not convinced you're going about this the right way, but I could be mistaken--I've never used it in a standalone web app before, but this doesn't strike me as being correct.
If nothing else, I'd at least move some stuff into a base class, like:
public abstract class BaseVelocityServlet extends VelocityViewServlet {
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
Velocity.init(getServletContext().getRealPath("/WEB-INF/velocity.properties"));
}
#Override
protected Template getTemplate(HttpServletRequest request, HttpServletResponse response) {
return Velocity.getTemplate(getTemplateName());
}
public abstract String getTemplateName();
}
Then each URL's servlet can just fill the context and provide a template name:
public class Recipes extends BaseVelocityServlet {
#Override
protected void fillContext(Context context, HttpServletRequest request) {
context.put("recipeList", "r1");
}
#Override
public String getTemplateName() {
return "Recipes.vm";
}
}
Again, I'm not convinced this is right; I'm still under the impression that it should be finding the config file under WEB-INF by default, but for me, at least, it's not.

Related

NoClassDefFoundError in Tomcat 7

We are facing a weird issue in production. Ours is a web application deployed in Tomcat 7. We are using Antisamy-1.5.3.jar for XSS prevention.Each user request is intercepted by a filter which scans the requests for any malicious content.
This setup was all fine in Tomcat 6 for more than a year. We migrated to Tomcat 7. Users get NoClassDefFoundError on and off when they open the app(not consistent) but when Tomcat is restarted it works fine.
Below is the flow where exception is thrown
User request is intercepted by AntiSamyFilter and scan method on owasp.validator.html.AntiSamy class(AntiSamy internal class) is called.
Below is the code for scan method
public CleanResults scan(String taintedHTML, Policy policy)
throws ScanException, PolicyException
{
return new AntiSamyDOMScanner(policy).scan(taintedHTML);
}
When AnitSamyDOMScanner class is referenced in the code above, static init block of super class of AntiSamyDOMScanner – AbstractAntiSamyScanner is called which is as below
private static ResourceBundle getResourceBundle() {
try {
return ResourceBundle.getBundle("AntiSamy", Locale.getDefault()); }
catch (MissingResourceException mre) {
}
return ResourceBundle.getBundle("AntiSamy", new Locale("en", "US"));
}
This is where the exception is thrown because, tomcat for some reason can’t load resource bundle – AntiSamy_en_US.properties file present inside the jar file at the root level.
Since this is error in static block, ExceptionInInitializer is thrown ultimately leading to NoClassDefFoundError.
Below are the two exception when looked at together – we can see that NoClassDefFoundError is caused due to exception in static init block of AbstractAntiSamyScanner.
SEVERE: Servlet.service() for servlet [jsp] in context with path [/app] threw exception [javax.servlet.ServletException: java.lang.NoClassDefFoundError: Could not initialize class org.owasp.validator.html.scan.AntiSamyDOMScanner] with root cause
java.lang.NoClassDefFoundError: Could not initialize class org.owasp.validator.html.scan.AntiSamyDOMScanner
at org.owasp.validator.html.AntiSamy.scan(AntiSamy.java:93)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:124)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
java.lang.NoClassDefFoundError: Could not initialize class org.owasp.validator.html.scan.AntiSamyDOMScanner StackTrace: javax.servlet.ServletException: java.lang.NoClassDefFoundError: Could not initialize class org.owasp.validator.html.scan.AntiSamyDOMScanner at
WE have tried copying the Antisamy.properties under Tomcat lib and also WEB-INF/classes but it didnt work.
Any thoughts on what could cause the AbstractAntiSamyScanner not find the resource bundle within the jar?

How to get path in spring to access configuration file

I have written a Spring program where the following classes, interfaces and xml files are in different packages. I use Eclipse Kepler.
SelectClient.java
package com.rajeev.spring.action;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.rajeev.spring.DAOI.Select;
/**
* #author rajeev
*
*
*/
public class SelectClient {
/**
* #param args
*/
public static void main(String[] args) {
String path=System.getProperty("user.dir");
System.out.println(path+"/src/com/rajeev/spring/DAOImpl/SelectCfg.xml");
Resource resource=new ClassPathResource(path+"/src/com/rajeev/spring/DAOImpl/SelectCfg.xml");
XmlBeanFactory beanFactory=new XmlBeanFactory(resource);
Object object=beanFactory.getBean("sb");
Select select=(Select)object;
System.out.println("emp name is:"+select.fetchName(101));
}
}
The problem is that when I execute the SelectClient.java, it is giving following error
E:\javahyd\eclipse\Spring_DataSource_Object_Inject/src/com/rajeev/spring/DAOImpl/SelectCfg.xml
Jan 17, 2014 11:41:43 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [E:/javahyd/eclipse/Spring_DataSource_Object_Inject/src/com/rajeev/spring/DAOImpl/SelectCfg.xml]
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [E:/javahyd/eclipse/Spring_DataSource_Object_Inject/src/com/rajeev/spring/DAOImpl/SelectCfg.xml]; nested exception is java.io.FileNotFoundException: class path resource [E:/javahyd/eclipse/Spring_DataSource_Object_Inject/src/com/rajeev/spring/DAOImpl/SelectCfg.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.xml.XmlBeanFactory.(XmlBeanFactory.java:78)
at org.springframework.beans.factory.xml.XmlBeanFactory.(XmlBeanFactory.java:66)
at com.rajeev.spring.action.SelectClient.main(SelectClient.java:26)
Caused by: java.io.FileNotFoundException: class path resource [E:/javahyd/eclipse/Spring_DataSource_Object_Inject/src/com/rajeev/spring/DAOImpl/SelectCfg.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:158)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328)
... 4 more
The above exception, is due to the path. When I use the same path in run(windows+r) the particular file it is opening. I dont want to keep my configuration file out of any packages.
ClassPathResource is used to refer the path of the resource in the classpath. The path argument passed in the ClassPathResource refers to the absolute path within the class path.So, use
Resource resource=new ClassPathResource("com/rajeev/spring/DAOImpl/SelectCfg.xml");
Try to use FileSystemResource to mention absolute path in the filesystem
Use FileSystemResource instead of ClassPathResource resource and give complete path e.g Resource resource=new FileSystemResource("C://path/to//your//config.xml");

SpringMvc Instantiating Beans - Singleton

In the under mentioned code i created this because i was getting java.lang.NullPointerException see my error log under. When i implemented this it was fixed and it worked perfectly. However i was told by one of the members here that -
"you are creating new beans for every call to getOfficerRegistrationValidation. this includes recreating the database objects which are every expensive and can cost error if some object are supposed to be created only once (singleton). you should find a way to make OfficerRegistrationValidation reusable and threadsafe so that you can have only one of it and inject this to wherever you want using only IoC"
and i think hes right can someone tell me whats the best way to do this without having to instantiate all my beans again. I just want to instantiate only the certain beans and not run into this problem.
public final class BeanFactory() {
private static ClassPathXmlApplicationContext context;
private static ClassPathXmlApplicationContext getContext() {
if (context== null) {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
return context;
}
public static OfficerRegistrationValidation getOfficerRegistrationValidation() {
return (OfficerRegistrationValidation) getContext().getBean("officerRegistrationValidation");
}
}
In the controller make a call like : `BeanFactory.getOfficerRegistrationValidation().validate(....)
Error Log:
java.lang.NullPointerException
at com.crimetrack.service.OfficerRegistrationValidation.validate(OfficerRegistrationValidation.java:51)
at org.springframework.validation.DataBinder.validate(DataBinder.java:725)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:815)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:367)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
I'm going to hazard a guess at what you are asking about (as your question doesn't provide your motivation for using a beanfactory and doesn't provide enough code to give a complete picture)...
Spring beans are by default instantiated as singletons. So you should be able to configure Spring to create your OfficerRegistrationValidation object using either XML or annotation (#Component) and then get it injected into your controller by using the #Inject annotation.
Annotations are the way to go - just make sure you have the following in your Spring config XML (applicationContext.xml):
<context:component-scan base-package="com.acme.project" />
<mvc:annotation-driven />
Then simply add the #Component annotation to the class declaration of your OfficerRegistrationValidation class:
#Component
public class OfficerRegistrationValidation {
// ...
}
and then in your controller, declare a field for your OfficerRegistrationValidation and annotate it thus:
#Controller
public class MyController {
#Inject
private OfficerRegistrationValidation officerRegistrationValidation;
// ...
}
Now you will have access to the OfficerRegistrationValidation singleton bean in your controller - only ~4 lines of code needed!

ClassNotFoundException with ServletContextlistener

I get an exception whenever I try getting context parameter from we.XML into a ServletContextListener class, I am really having hard times understanding why It is not working,
here's the exception in Apache Tomcat 7.0.11 log :
Oct 21, 2011 1:24:23 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Error configuring application listener of class alaa.ServletContextListener
java.lang.ClassNotFoundException: alaa.ServletContextListener
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
at
org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:415)
at
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4618)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5184)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5179)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Here's a part of my web.xml :
<context-param>
<param-name>catName</param-name>
<param-value>meshmesh</param-value>
</context-param>
<context-param>
<param-name>catBreed</param-name>
<param-value>egyptian</param-value>
</context-param>
<listener>
<listener-class>alaa.CatLisenter</listener-class>
</listener>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
Here's my ServletContextListener.java:
package alaa;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class CatLisenter implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
String name = sc.getInitParameter("catName");
String breed = sc.getInitParameter("catBreed");
Cat maCat = new Cat();
maCat.setName(name);
maCat.setBreed(breed);
sc.setAttribute("cat", maCat);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Here's Cat.java :
package alaa;
public class Cat {
private String name;
private String breed;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
}
many thanks
Try to clear the tomcat work directory and clean. After that, publish your project and run again.
My guess is that you have packaged the servlet-api jar in your webapp (in the WEB-INF/lib) folder and this is causing conflicts since the servlet-api will already be present in the container. Make sure you don't include any servlet-api or jsp-api (or Java EE api) jars in your webapp when you deploy it.
I had the same problem running JUnit in a Tomcat 7 environment and I solved it adding a dependency in maven (pom.xml) like this:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>7.0.54</version>
<scope>provided</scope>
</dependency>
If you are working in Eclipse, Then just clean your project.
Follow this simple step,
Go to Project >
clean...> clean all projects > Ok
I had the same issue when I tried with eclipse LUNA version and tomcat 7. The same code without any extra changes worked in eclipse JUNO with tomcat 7.
Verify the space in disk. When eclipse copy the folder libs if not space in disk this error may occur
I had a similar problem. It Maybe not be related to what you had but it might save someone some time. I had my listener-class wrong in the web descriptor file:)

Specifying relative resource path via Spring XmlWebApplicationContext

The actual question is: Is there a way to get XmlWebApplicationContext to load resources using paths relative to the context location? For clarity's sake, let's say "context location" is the location of the first file specified via setConfigLocation() method.
Detailed explanation is below:
I'm using Spring MVC in web tier and Spring IOC in mid tier. Appropriate contexts are defined hierarchically as described in Spring Documentation: web stuff is defined in my-servlet.xml and services et al are defined in services.xml that's loaded via ContextLoaderListener. Mid tier can be deployed either together with web tier (e.g. the whole thing runs within ServletContainer) or separately (in which case services.xml is replaced by remote-services.xml defining remote stubs). The whole setup works perfectly except for the following problem:
I have certain resources (additional XML files, what have you) located in the same folder as services.xml that need to be accessible by said services. Those resources are specified as dependencies in services.xml using relative paths. When mid tier is deployed standalone that works fine, but not when it's deployed within servlet container. In the latter case mid tier context gets instantiated as XmlWebApplicationContext which loads all resources based of servlet context root meaning I have to prefix everything with /WEB-INF/ which I'd really like to avoid. Using PropertyPlaceholderConfigurer presents a similar problem as well.
I know I can work around this somewhat by having resources load from classpath, but that's not ideal either - for standalone deployment it means I need to add configuration folder to classpath and for web deployment it means everything has to be copied under WEB-INF/classes.
Any ideas?
I've ended up extending Spring's XmlWebApplicationContext to allow relative resource paths. This does what I want, that is allows me to use the same context.xml file no matter whether it's deployed as part of web app or standalone.
For anyone interested source is available below. It's published using SOV (Stack Overflow Voting) license :-) which means you're free to do whatever you want with it as long as you upvote this answer :-)
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
/**
* Extends Spring's default web application context to allow relative
* resource paths. Resources without explicitly specified URL protocol
* and / or leading slash are loaded relative to the first location
* from getConfigLocations().
*/
public class SpringApplicationContext extends XmlWebApplicationContext {
#Override
protected Resource getResourceByPath(String path) {
path = StringUtils.cleanPath(path);
if (path.startsWith("/") || (path.indexOf(':')>0)) {
return super.getResourceByPath(path);
}
try {
return super.getResourceByPath(getConfigLocations()[0])
.createRelative(path);
} catch (IOException E) {
// failed to create relative resource - default to standard implementation
return super.getResourceByPath(path);
}
} // getResourceByPath()
}
I agree that is rather annoying. I get around this by doing what you suggest, which is putting my spring config on the classpath, so even though I still use fully-qualified imports, they work under any environment.
I'm not sure why your classpath config needs to be that complex, though. The files can just under your java source folder alongside the java files, so they get handled the same.
Strange. Your solution does not work for me. Here is mine:
package dmp.springframework.web.context;
import java.io.IOException;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
public class RelativeResourceXmlWebApplicationContext extends XmlWebApplicationContext {
#Override
protected Resource getResourceByPath(String path) {
path = StringUtils.cleanPath(path);
if (path.startsWith("/") || (path.contains(":"))) {
return super.getResourceByPath(path);
}
try {
String newFilename = super.getResourceByPath(getConfigLocations()[0]).getFile().getParentFile().getAbsolutePath();
newFilename = newFilename + "/" + path;
return new FileSystemResource(newFilename);
} catch (IOException E) {
// failed to create relative resource - default to standard implementation
return super.getResourceByPath(path);
}
} // getResourceByPath()
}

Categories