Servlet mapping: url pattern problems - spring-mvc

I'm trying to set up a servlet mapping so that urls in the form "/getFile/{fileId}" will be mapped by my DispatcherServlet "dispatcher".
If I set up my web.xml as below only "/getFile" will be mapped, I can't append the fileId or it breaks.
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/getFile</url-pattern>
</servlet-mapping>
So I would have thought that I should use
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/getFile/*</url-pattern>
</servlet-mapping>
But this doesn't work at all.
The method I'm trying to call is
#RequestMapping(value = "/getFile/{documentId}", method = RequestMethod.GET)
public void getFile(#PathVariable int documentId, HttpServletResponse response) throws Exception {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDB userDB = UserDBService.getUser(user.getUsername());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Document document = DocumentService.getDocument(documentId);
String extension = document.getExtension();
try {
String path = ApplicationPropertiesConstants.SAFESITE_DOCUMENTS_DIRECTORY + userDB.getSite().getId() + "\\" + documentId + "." + extension;
InputStream is = new FileInputStream(path);
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/png");
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (IllegalArgumentException e) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
Any idea what I'm doing wrong?
Edit: it's not a duplicate as below because I do not have a servlet mapping of just "/". Thus there is no default fall back mapping.
My full mapping.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/getFile/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>

Right so I fixed it by using the url
/getFile/getFile/{documentId}
on my client side.

Related

HTTP Status 405 – Method Not Allowed in Apache Tomcat Server [duplicate]

This question already has answers here:
HTTP Status 405 - HTTP method is not supported by this URL
(2 answers)
Closed 1 year ago.
I am encountering HTTP Status 405 – Method Not Allowed error in my Java Backend.
I am using Apache Tomcat Server
Type Status Report
Message HTTP method GET is not supported by this URL
Description The method received in the request-line is known by the origin server but not supported by the target resource.
Here is the screenshot:
My Web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Backend</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:3000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>BatchDisplay</servlet-name>
<servlet-class>com.hello.BatchDisplay</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BatchDisplay</servlet-name>
<url-pattern>/BatchDisplay.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>com.hello.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/AddServlet.do</url-pattern>
</servlet-mapping>
</web-app>
When I am executing Post request from Postman, I am getting this error.
My Java backend code:
package com.hello;
import java.io.*;
import java.sql.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class AddServelet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request,HttpServletRequest response) throws ServletException
{
try {
String custNumber=request.getParameter("cust_number");
String nameCustomer=request.getParameter("name_customer");
String invoiceID=request.getParameter("invoice_id");
Double TotalOpenAmount=Double.parseDouble(request.getParameter("total_open_amount"));
String dueinDATE=request.getParameter("due_in_date");
String Notes=request.getParameter("notes");
System.out.print("Acquiring Connection");
Connection connection = DriverManager.getConnection("com.mysql.jdbc.Driver", "root", "abcd");
System.out.print("Connected Successfully");
String sql="INSERT INTO invoice
invoice_details(cust_number,name_customer,invoice_id,total_open_amount,due_in_date,notes)
VALUES (?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, nameCustomer);
statement.setString(2, custNumber);
statement.setString(3, invoiceID);
statement.setDouble(4, TotalOpenAmount);
statement.setString(5, dueinDATE);
statement.setString(6, Notes);
statement.executeUpdate();
}
catch(SQLException e){
e.printStackTrace();
}
finally
{
}
}
}
I really don't know why is it giving such an error.
Please suggest me a way to debug it.
You need to override doGet method if u wanna call by GET method;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String custNumber=request.getParameter("cust_number");
String nameCustomer=request.getParameter("name_customer");
String invoiceID=request.getParameter("invoice_id");
Double TotalOpenAmount=Double.parseDouble(request.getParameter("total_open_amount"));
String dueinDATE=request.getParameter("due_in_date");
String Notes=request.getParameter("notes");
System.out.print("Acquiring Connection");
Connection connection = DriverManager.getConnection("com.mysql.jdbc.Driver", "root", "abcd");
System.out.print("Connected Successfully");
String sql="INSERT INTO invoice
invoice_details(cust_number,name_customer,invoice_id,total_open_amount,due_in_date,notes)
VALUES (?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, nameCustomer);
statement.setString(2, custNumber);
statement.setString(3, invoiceID);
statement.setDouble(4, TotalOpenAmount);
statement.setString(5, dueinDATE);
statement.setString(6, Notes);
statement.executeUpdate();
}
catch(SQLException e){
e.printStackTrace();
}
finally
{
}
}
When you need to use GET method: override doGet(HttpServletRequest request, HttpServletResponse response), POST- doPost(HttpServletRequest request, HttpServletResponse response), both - doGet and doPost

Spring-MVC 3.0 Controller error: HTTP Status 400

since my application is on the Spring-MVC 3.0 framework, what is the problem of below controller that getting the "Http Status 400" error?
package com.maskkk.controller;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
#Controller
public class FileDownloadController
{
#RequestMapping(value="/spring/download")
public void downloadPDFResource( HttpServletRequest request,
HttpServletResponse response,
#PathVariable("fileName") String fileName
)
{
//If user is not authorized - he should be thrown out from here itself
//Authorized user will download the file
//String dataDirectory = request.getServletContext().getRealPath("/WEB-
INF/downloads/pdf/");
String dataDirectory =
request.getServletContext().getRealPath("fileupload");
Path file = Paths.get(dataDirectory, fileName);
if (Files.exists(file))
{
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment;
filename="+fileName);
try
{
Files.copy(file, response.getOutputStream());
response.getOutputStream().flush();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
And my web.xml is below:
<web-app 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"
version="3.0">
<welcome-file-list>
<welcome-file>dashboard.jsp</welcome-file>
<welcome-file>form.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- log4j2-begin -->
<listener>
<listener-
class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-
class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-
class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<!-- log4j2-end -->
<!-- 编码处理过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-
class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-
class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 这里的servlet-name和上面的要一致. -->
<servlet-name>spring</servlet-name>
<!-- 这里就是url的匹配规则, / 就是匹配所有 -->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
The above controller is for downloading the file from the web site. And this controller is not active when I type the "http://localhost:8888/Upload/spring/download.do" on the url and press enter.
So, what is the problem?
Any suggestions would be very appreciated!
You specify a path variable in your Spring MVC code with #PathVariable("fileName") String fileName and you should resolve this when you call your endpoint. The structure of your endpoint should look the following /../spring/download/{fileName} where the {fileName} replaces a variable in your URL. A valid URL could look like the following: http://localhost:8888/Upload/spring/download/yourFileName. Change the endpoint method to the following if you need this path variable:
#RequestMapping(value="/Upload/spring/download/{fileName}")
public void downloadPDFResource( HttpServletRequest request, HttpServletResponse response, #PathVariable("fileName") String fileName) {
// do your logic
}

Eclipse: ServletConfig object returns NULL on calling getServletConfig()

this is my code . Please help me solve this problem . I m new to servlet and i m trying my best to solve it but i m unable .
public class InsertData extends GenericServlet{
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
PrintWriter pw = null ;
ServletConfig conf = getServletConfig(); // This is giving null everytime i m checked it in webpage
String str = cont.getInitParameter("username");
pw = response.getWriter();
pw.println("<html><body><b>conf</b></body><html>");
}
}
and this is my web.xml file :
<web-app>
<servlet>
<servlet-name>s1</servlet-name>
<servlet-class>InsertData</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>mydb</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>s1</servlet-name>
<url-pattern>/InsertData</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>home.html</welcome-file>
</welcome-file-list>
</web-app>

Migrate Cometd 2 to Cometd3 in Glassfish- Handshake fail

I migrated my cometd from 2 to 3 and come across some problem:
Handshake never succeed, and there's no error messages.
I tried all I can do but still in vain.
Here's my Code:
ConfigurationServlet:
#Override
public void init() throws ServletException {
logger.info("start prepare echoService...");
// Grab the Bayeux object
BayeuxServer bayeuxServer = (BayeuxServer) getServletContext().getAttribute(BayeuxServer.ATTRIBUTE);
bayeuxServer.createChannelIfAbsent(NODE_CHANNEL, new ServerChannel.Initializer() { //1030829 change createIfAbsend to createChannelIfAbsent
#Override
public void configureChannel(ConfigurableServerChannel channel) {
channel.setPersistent(true);
}
});
EchoService echoService = new EchoService(bayeuxServer);
logger.info("...prepare echoService done");
}
EchoService:
public EchoService(BayeuxServer bayeuxServer) {
super(bayeuxServer, "echo");
//for what?
logger.info("=============enter echoService constructor=============");
addService("/echo", "processEcho");
addService(CometdProperties.COMETD_CHANNEL_WEB, "processReq");
logger.info("=============leaving echoService constructor=============");
isEchoServiceStarted = true;
}
public void processEcho(ServerSession remote, ServerMessage message) {
remote.deliver(getServerSession(), "/echo", message.getData());
}
public void processReq(ServerSession remote, ServerMessage message) {
//do something...
}
InitConnect in my client:
public boolean initConnect(String channel, ClientSessionChannel.MessageListener ml) {
HClogger.info("=============initConnect=============Listener:" + ml);
HttpClient httpClient = new HttpClient();
try {
httpClient.start();
} catch (Exception ex) {
HClogger.error(ex.toString());
if(connCnt<10){//Retry 9 times.
connCnt++;
return initConnect(channel,ml);
}
return false;
}
HClogger.info("*********************************try connect to server...");
Map<String, Object> options = new HashMap<>();
ClientTransport longPool = new LongPollingTransport(options, httpClient);
bayeuxClient = new BayeuxClient(CometdProperties.COMETD_DEFAULTURL, longPool);
bayeuxClient.handshake();
boolean handshaken = bayeuxClient.waitFor(10000, BayeuxClient.State.CONNECTED);
if (handshaken) {
HClogger.info("connected to server ok...");
bayeuxClient.getChannel(channel).subscribe(ml);
HClogger.info("subscribed to " + channel + " channel.");
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
HClogger.error("Error when sleep after subscribe.", ex);
}
HClogger.info("=============HandleClient subscribe done.=============");
return true;
} else {
HClogger.info("=============HandleClient handshake fail.=============");
if(connCnt<10){//Retry 9 times.
connCnt++;
return initConnect(channel,ml);
}
return false;
}
}
Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometDServlet</servlet-class>
<init-param>
<param-name>timeout</param-name>
<param-value>300000</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet>
<servlet-name>ConfigurationServlet</servlet-name>
<servlet-class>org.astri.ims.ccs.webcommand.ConfigurationServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ConfigurationServlet</servlet-name>
<url-pattern>/ConfigurationServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
And here's what I add in my lib:
bayeux-api-3.0.1.jar
cometd-java-client-3.0.1.jar
cometd-java-common-3.0.1.jar
cometd-java-server-2.0.1.jar
jackson-mapper-asl-1.9.12.jar
javax.servlet-3.1.jar
jetty-client-9.2.2v20140723.jar
jetty-http-9.2.2v20140723.jar
jetty-io-9.2.2v20140723.jar
jetty-jmx-9.2.2v20140723.jar
jetty-server-9.2.2v20140723.jar
jetty-servlet-9.2.2v20140723.jar
jetty-util-9.2.2v20140723.jar
jetty-util-ajax-9.2.2v20140723.jar
Is there anything wrong in my code or configuration?
Update
I added a listener to the meta_channel, and I got this while handshaking:
{"id":"3","failure":{"message":{"id":"3","supportedConnectionTypes":["long-polling"],"channel":"/meta/handshake","version":"1.0"},"exception":"java.util.concurrent.TimeoutException: Total timeout elapsed","connectionType":"long-polling"},"subscription":null,"successful":false,"channel":"/meta/handshake"}
It turns out there is a bug in glassfish4.
Thanks for #sbordet who investigate and find out what's going on.
For detail information, please visit here.
For those who want to use CometD3, Jetty is suggested container.
For those who have no choice but to use glassfish, Cometd2.X works.
I've tried with cometd2.9.1, 3.0.0 and 3.0.1 in glassfish4, the result is
2.9.1 works in glassfish4 while 3.0.0 and 3.0.1 not.

#MultipartConfig override in web.xml

So I have this servlet :
#WebServlet(name = "StudentRegistrationUsn", urlPatterns = {"/university/student/registration"})
#MultipartConfig(maxFileSize = 10*1024*1024,maxRequestSize = 20*1024*1024,fileSizeThreshold = 5*1024*1024)
public class ActionRegistrationServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//handle file upload
}
Everything works fine, files are uploading.
Then I try to override the fileSize and Threshold in web.xml:
<servlet>
<servlet-name>StudentRegistrationUsn</servlet-name>
<multipart-config>
<max-file-size>10485760</max-file-size>
<max-request-size>20971520</max-request-size>
<file-size-threshold>5242880</file-size-threshold>
</multipart-config>
</servlet>
When I do that, tomcat crashes and whenever I try to access that servlet it gives the following exception:
The server encountered an internal error that prevented it from fulfilling this request.
exception
java.lang.NullPointerException
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
java.lang.ClassLoader.loadClass(ClassLoader.java:356)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1629)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:461)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1813)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:722)
The <servlet-class> is missing in web.xml. This exception is basically caused because the name of the to-be-loaded class is null.
In fact, you need to redefine everything, including the URL patterns.
<servlet>
<servlet-name>StudentRegistrationUsn</servlet-name>
<servlet-class>com.example.StudentRegistrationUsn</servlet-class>
<multipart-config>
<max-file-size>10485760</max-file-size>
<max-request-size>20971520</max-request-size>
<file-size-threshold>5242880</file-size-threshold>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>StudentRegistrationUsn</servlet-name>
<url-pattern>/university/student/registration</url-pattern>
</servlet-mapping>

Resources