Servlet WebServlet multiple urlPattern - servlets

I must write a servlet that should do multiple operations according to the button I press on the html page.
I have one button that is a Insert into the Db, another is a Delete, another is a Select.
So I would like my servlet will do all those three operations in the doGet method.
My clue was to put
#WebServlet("select", "insert", "delete")
public class MyServlet extends HttpServlet {
...
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getServletPath()!=null?request.getServletPath():"";
switch(path){
case "/select":
...
break;
switch(path){
case "/insert":
...
break;
switch(path){
case "/delete":
...
break;
then, into the javascript file it would have been (for select)
var req={
method: 'GET',
url: 'http://localhost:8080/AngularDb/select',
}
$http(req);
and into the web.xml
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
But all this doesn't work.
May you tell me what is wrong?

Related

how to get a path variable value in servlet

I want to get the path variable in servlet. Assume the url is www.demo.com/123/demo. I want to get the 123 value from the path without doing any string manipulation operation.
Note: the following servlet doesn't have any web.xml configurations. My code is:
#WebServlet(urlPatterns = { "/demo" })
public class DemoServlet extends HttpServlet {
public DemoServlet()
{
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
sysout("demo");
}
}
The portion of the URL you are referring to is the "context". Use request.getContextPath() to get this. In the case of your example, this would return /123. If you want exactly 123 you would have to remove the leading slash.
From the documentation:
Returns the portion of the request URI that indicates the context of
the request. The context path always comes first in a request URI. The
path starts with a "/" character but does not end with a "/"
character. For servlets in the default (root) context, this method
returns "". The container does not decode this string.

Jetty 9.3.6 and Servlet WebAppContext getServletContext() returns null

I am missing something with this I am sure. But I have spent the last few days searching and unfortunately I have not found an answer that seems to fit.
I have a Servlet that extents HttpServlet and overrides init() "not init(ContextConfig)" and in the init() function getServletContext is always returning null. This was not the case while I was using Springs 4.0.x and Jetty 8.1.x I would guess I am doing something wrong but at a loss as to what it is. I have generally removed Springs from the test code, but it still gets null.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<display-name>MyServlet</display-name>
<servlet-name>MyServlet</servlet-name>
<servlet-class>servlet.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
JavaConfig Starter partial:
WebAppContext root = new WebAppContext();
root.setDescriptor("./WEB-INF/web.xml");
root.setDisplayName("Root Context");
root.setSessionHandler(sesh); //Persist Session across restarts of context
root.setHandler(csh);
root.setMaxFormContentSize(10000000);
// Cron Servlet
System.out.println("Checking root ServletContext ");
if (root.getServletContext() == null)
System.out.println("ServletContext is null");
//ServletHolder test = new ServletHolder(new MyServlet());
//test.setDisplayName("test");
//test.setName("test");
//root.addServlet(test, "/the");
root.setResourceBase(new File("./jsp").getPath());
server.setHandler(root);
//Start the server
server.start();
server.join();
And the servlet:
package servlet;
import java.io.*;
import org.apache.log4j.Logger;
import javax.servlet.*;
import javax.servlet.http.*;
public class MyServlet extends HttpServlet {
static Logger log = Logger.getLogger(MyServlet.class);
private static final long serialVersionUID = 1L;
public void init() throws ServletException {
// Initialization code...
log.info("MyServlet init()");
super.init();
ServletContext sc = getServletContext();
if (sc == null)
log.info("54: Conext returned null");
}
public void destroy() {
log.info("MyServlet destroy()");
}
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setHeader("Server", "GoAway");
doProcess(req, resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setHeader("Server", "GoAway");
doProcess(req, resp);
}
private void doProcess(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter out = resp.getWriter();
// setup no cache
resp.setContentType("text/html");
resp.getWriter().println("<html><head><META HTTP-EQUIV=\"refresh\" content=\"0;URL=/\"></head><body>\n</body>\n</html>");
resp.getWriter().close();
out.close();
return;
}
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Server", "GoAway");
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
}
So this is something I stripped out of a larger application to figure out what I was doing wrong. so somethings might still be un-needed. You can see in the Javaconfig I have tried creating the servlet container there as well, but the results are the same.
So from inside the Start code the servletContext is not null.
but from inside the MyServlet init() code it is always returning null.
I really am not sure what I am doing wrong.
Thanks for your help.
o FYI included Jar's
commons-beanutils-1.9.2.jar
commons-codec-1.9.jar
commons-io-2.2.jar
commons-logging-1.2.jar
javax.el-2.2.6.jar
javax.el-api-2.2.5.jar
javax.mail-1.5.3.jar
javax.servlet-api-3.1.0.jar
jetty-http-9.3.6.v20151106.jar
jetty-io-9.3.6.v20151106.jar
jetty-security-9.3.6.v20151106.jar
jetty-server-9.3.6.v20151106.jar
jetty-servlet-9.3.6.v20151106.jar
jetty-util-9.3.6.v20151106.jar
jetty-webapp-9.3.6.v20151106.jar
jetty-xml-9.3.6.v20151106.jar
log4j-1.2.17.jar
org.apache.jasper.glassfish-2.2.2.v201112011158.jar
slf4 j-api-1.7.13.jar
spring-aop-4.2.3.RELEASE.jar
spring-beans-4.2.3.RELEASE.jar
spring-context-4.2.3.RELEASE.jar
spring-context-support-4.2.3.RELEASE.jar
spring-core-4.2.3.RELEASE.jar
spring-expression-4.2.3.RELEASE.jar
spring-tx-4.2.3.RELEASE.jar
spring-web-4.2.3.RELEASE.jar
Update 2015.12.10:
So I played around a bit with different Jetty Versions. The original code was using 8.1.17 and I decided to upgrade it to 9.3.6. So I downgraded it to 9.3.5, but had the same results. Then I downgraded to 9.2.14 and the problem was resolved. So Either this is a bug in Jetty 9.3.x ( which would seem unlikely as someone would be using this) or with 9.3 their is a different way to configure it. I looked for documentation about it be it all shows the same way that I am doing it.

Spring 4 upgrade broke error page filter chain

Scenario:
We have an interceptor that looks for bogus attributes in URLs and throws a NoSuchRequestHandlingMethodException if it finds one. We then display a custom 404 page.
All pages go through the same filter chain to set up the local request state, log some information, and then display the requested page. In Spring 4, it stopped going through the filter chain for the 404 page in this case. It still goes through it if you go to a completely bogus page, and the 404 works, but when we throw the NoSuchRequestHandlingMethodException, the filters don't happen.
Spring 3:
1. Runs the filter chain for the main request
2. We throw NoSuchRequestHandlingMethodException
3. Filter chain finishes
4. New filter chain starts
5. We log the error page metrics
6. We display a nice 404 page to the customer
Spring 4:
1. Runs the filter chain for the main request
2. We throw NoSuchRequestHandlingMethodException
3. Filter chain finishes
4. We try to log the error page metrics, but NPE since a second filter chain never started
5. We display a terrible blank page to the customer
Filter code in web.xml:
<!-- The filter that captures the HttpServletRequest and HttpServletResponse-->
<filter>
<filter-name>ServletObjectFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>xxxxxxx.servletObjectFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ServletObjectFilter</filter-name>
<servlet-name>springmvc</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
...
<error-page>
<error-code>404</error-code>
<location>/errors/404</location>
</error-page>
Filter code:
public void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain chain )
throws ServletException, IOException {
try {
getServletContainer().setServletObjects( request, response );
chain.doFilter( request, response );
} finally {
getServletContainer().removeAll();
}
ServletContainer:
static final ThreadLocal< HttpServletRequest > REQUESTS = new ThreadLocal< HttpServletRequest >();
static final ThreadLocal< HttpServletResponse > RESPONSES = new ThreadLocal< HttpServletResponse >();
public void setServletObjects( HttpServletRequest request, HttpServletResponse response ) {
REQUESTS.set( request );
RESPONSES.set( response );
}
public void removeAll() {
REQUESTS.remove();
RESPONSES.remove();
}
Code that then fails:
public class RequestResponseAwareBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization( Object bean, String beanName ) {
...
if ( bean instanceof RequestAware ) {
HttpServletRequest request = getServletContainer().getRequest();
if ( request == null ) {
throw new IllegalStateException( "The request object is NULL" );
}
RequestAware requestAware = (RequestAware) bean;
requestAware.setRequest( request );
}
}
I "solved" the problem by splitting up my error page #Controller into two, one where they're the targets of internal redirects and don't get the filter chain, and one where they are directly loaded, and do get the filter chain. I then added the redirect #Controller to the interceptor blacklist, so it doesn't require any logic or data from the filters. It solved this specific problem, but I'm worried that something else in my codebase also relies on this behavior.

web.xml error-page location redirect is not going through my filter definitions

In my web.xml I've done the following error-page mappings, but when they are invoked those invoked requests are not passing through the filter definitions specified in web.xml file.
<error-page>
<error-code>403</error-code>
<location>/error.vm?id=403</location>
</error-page>
<error-page>
<error-code>400</error-code>
<location>/error.vm?id=400</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.vm?id=404</location>
</error-page>
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/servlet-exception.vm</location>
</error-page>
My application is using spring-mvc and I want to handle the handler not found condition from spring mvc. My application is an multi tenant application where some filters are responsible for setting some information related to the schema.
The requests are reaching in my error.vm controller but since they are passing through the filter I'm not able to determine the theme and SecurityContext etc.
How to solve this problem?
Thank you.
Instead of using web.xml's error pages you could use a servlet filter. The servlet filter could be used to catch all exceptions, or just a particular exception such as org.springframework.web.portlet.NoHandlerFoundException. (Is that what you mean by "handler not found" exception?)
The filter would look something like this:
package com.example;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import org.springframework.web.portlet.NoHandlerFoundException;
public class ErrorHandlingFilter implements Filter {
public void init(FilterConfig config) throws ServletException { }
public void destroy() { }
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
try {
chain.doFilter(request, response);
} catch (NoHandlerFoundException e) {
// Or you could catch Exception, Error, Throwable...
// You probably want to add exception logging code here.
// Putting the exception into request scope so it can be used by the error handling page
request.setAttribute("exception", e);
// You probably want to add exception logging code here.
request.getRequestDispatcher("/WEB-INF/view/servlet-exception.vm").forward(request, response);
}
}
}
Then, set this up in web.xml with the help of Spring's DelegatingFilterProxy:
<filter>
<filter-name>errorHandlingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>errorHandlingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And then finally, turn the filter into a spring bean inside your spring context xml:
<bean id="errorHandlingFilter" class="com.example.ErrorHandlingFilter" />
You might have to experiment with the order of the filter in the filter chain so that failed requests still go through the other filters you mentioned. If you're having trouble with that, a variation would be to do an HTTP redirect instead of a forward, like this:
try {
chain.doFilter(request, response);
} catch (NoHandlerFoundException e) {
request.getSession().setAttribute("exception", e);
response.sendRedirect("/servlet-exception.vm");
}
That would force the browser to request your error handling page as a new http request, which might make it easier to ensure it goes through all of the right filters first. If you need the original exception object, then you could put it in the session instead of the request.
maybe
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>ERROR</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

Servlet + redirection

I need some suggestions. I have defined servlet mapping as
<servlet-mapping>
<servlet-name>My Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
However there are some static html files. So i have mapped them to the default servlet to serve the static html files
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
However, i want the user to have access to them only when the user has logged in. The welcome page is Login.html. If the user tries to access any other static file and has not logged in i.e there is not session then i should redirect user to the login page. But with current mapping the user is able to access index.html file as the request is served by default servlet.
Please suggest .
Your intent is to have a front controller servlet, not to replace the default servlet. So you should actually not be mapping your front controller servlet on /.
You should map the controller servlet on a more specific URL pattern, such as /app/*. To keep URLs transparent, your best bet is to create a filter which determines the request URI and continues the chain on static content like HTML and dispatches the remnant to the controller servlet.
E.g.
String uri = request.getRequestURI();
if (uri.endsWith(".html")) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher("/app" + uri).forward(request, response);
}
You can extend the DefaultServlet of your web server.The extended servlet will be your front controller. In the doGET or doPOST method forward your static pages to the super class. DefaultServlet is the servlet that is mapped to url "/" by default. I have used it with jetty server but it can be implemented in tomcat as well.
public class FrontController extends DefaultServlet {
#Override
public void init() throws UnavailableException {
super.init();
}
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String uri = request.getRequestURI();
/*
* if request is trying to access inside /static then use the default
* servlet. YOU CAN USE YOUR OWN BUSINESS LOGIC TO FORWARD REQUESTS
* TO DEFAULTSERVLET
*/
if (uri.startsWith("/static/")) {
super.doGet(request, response);
return;
} else {
// else use your custom action handlers
}
}
}
In the above code samples I have forwarded all the requests starting with /static/ to the default servlet to process. In this way you can map the FrontController to "/" level .
<servlet>
<description></description>
<display-name>FrontController</display-name>
<servlet-name>FrontController</servlet-name>
<servlet-class>FrontController</servlet-class>
<servlet-mapping>
<servlet-name>FrontController</servlet-name>
<url-pattern>/</url-pattern>

Resources