Reputation: 750
I know this question has been asked a million times and there are 5 million answers - some or which are very informative. None of which have solved this problem.
My goal is similar to many of the others - I want to access files - images, svgfiles, templates, etc. in the web app run-time environment. I can make it work if I simply hard wire the directory path. However, I would like to make my servlet portable and use a relative reference to access these resources -if for no other reason I develop in Windows and deploy in Linux.
The basic problem is that getServletContext() is null and I am unable to determine why.
Below is the error message, the code that produced it, followed by environment details. Produces the same error in both development and production. I will be happy to provide any additional details if requested.
Please explain what I need to do to get this working? I will be eternally grateful. Regards
SEVERE: Servlet.service() for servlet [jsp] in context with path [/HelloWorld] threw exception [An exception occurred processing JSP page /hello.jsp at line 19
16: <title>Hello World</title>
17: </head>
18: <body>
19: <%=wtGreet.getGreeting()%>
20: </body>
21: </html>
Stacktrace:] with root cause
java.lang.NullPointerException
at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:125)
at HelloWorld.Greeting.getGreeting(Greeting.java:23)
at org.apache.jsp.hello_jsp._jspService(hello_jsp.java:91)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
HelloWorld application works - produces undesired error - exactly the same as the real thing.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF 8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<jsp:useBean id="wtGreet" scope="page"
class="HelloWorld.Greeting">
<jsp:setProperty name="wtGreet" property="who" value="World"/>
<jsp:setProperty name="wtGreet" property="greet" value="Hello"/>
</jsp:useBean>
<jsp:setProperty name="wtGreet" property="*"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Hello World</title>
</head>
<body>
<%=wtGreet.getGreeting()%>
</body>
</html>
Then Servlet that the jsp calls
package HelloWorld;
import javax.servlet.http.HttpServlet;
public class Greeting extends HttpServlet {
private static final long serialVersionUID = 1298516959968350334L;
private String who;
private String greet;
public void setWho(String who) {
this.who = who;
}
public void setGreet(String greet) {
this.greet = greet;
}
public String getGreeting() {
System.out.println("getServletContext() == null :" + getServletContext().getContextPath());
return "<p>" + this.greet + " " + this.who + "</P>";
}
}
Development Environment Windows Eclipse JEE Apache Tomcat 7 JRE 7
Production Environment Linux Apache Tomcat 7 JRE 8
Upvotes: 3
Views: 13214
Reputation: 750
Even though the final solution is to implement a Model 2 pattern (I will include when finished), there is a good working answer for the question as asked. Thanks to A4L for showing the way.
Working from the understanding that the jsp engine compiles the jsp into a servlet and loads it into the servlet engine, the jsp implicit objects can be used to access an instantiated javax.servlet object.
The HelloWorld example is changed as follows: 1) Remove import javax.servlet.http.HttpServlet; and extends HttpServlet because this does nothing. 2) Add an attribute of type ServletContext and populate the attribute using the setter from the jsp page.
Any object that is available to the servlet can be available to the bean by way of jsp implicit objects.
jsp
{<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<jsp:useBean id="wtGreet" scope="page"
class="HelloWorld.Greeting">
<jsp:setProperty name="wtGreet" property="who" value="World"/>
<jsp:setProperty name="wtGreet" property="greet" value="Hello"/>
</jsp:useBean>
<jsp:setProperty name="wtGreet" property="*"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
<%wtGreet.setSc(application.getContext("/HelloWorld"));%>
<%=wtGreet.getGreeting()%>
</body>
</html>}
Bean
package HelloWorld;
import javax.servlet.ServletContext;
public class Greeting {
private String who;
private String greet;
private ServletContext sc;
public void setSc(ServletContext sc) {
this.sc = sc;
}
public void setWho(String who) {
this.who = who;
}
public void setGreet(String greet) {
this.greet = greet;
}
public String getGreeting() {
return "<p>" + this.greet + " " + this.who + " from \"Context Path\" " + sc.getContextPath() + "</P>";
}
}
Upvotes: 0
Reputation: 17595
Based on the last element of your stack trace
at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:125)
the method getServletContext()
is called and the exception happens in the line 125
in the class javax.servlet.GenericServlet
.
If getServletContext()
had returned null
then the last stack trace element would have been
at HelloWorld.Greeting.getGreeting(Greeting.java:23)
According to this code of javax.servlet.GenericServlet
the method getServletConfig()
is the one returning null
, i.e. you servlet is not configured.
This might be because you are (mis)using a servlet as a bean in your jsp
<jsp:useBean id="wtGreet" scope="page" class="HelloWorld.Greeting">
and that servlet is not properly initialized.
Servlets are not meant to be used like that. You may want to use a simple JavaBean and have it have a method getGreeting()
.
To get the ServletContext
inside your jsp you may use the implicit object application
, See here for other available implicit objects in the jsp.
Upvotes: 4