Issue
I have two different java projects and I need them to interact with each other. The first one named RESTfulWebServer is a dynamic web project which contains the basic HTTP GET PUT POST requests in a java class named UserServices. It just prints one line statements right now on console(output window in netbeans), so nothing complex.
The other project named ClientProject is also a dynamic web project which contains a simple jsp page containing javascript code. It is supposed to make call to the RESTfulWebServer project and print the output line on console(output window in netbeans) the same way the RESTfulWebServer project does when a simple GET request is made to it.
This is the part where the problem arises. When I run the ClientProject the javascript function is being called properly (as I checked by printing an alert message), but it is not making the DELETE HTTP request to the RESTfulWebServer as it is supposed to.
Both the codes are attached below:
RESTfulWebServer (UserServices.java)
package com.service.user;
import javax.ws.rs.*;
@Path("/user/service")
public class UserServices {
@GET
public void getUser()
{
System.out.println("Inside get user method");
}
@POST
public void updateUser()
{
System.out.println("Inside update user method");
}
@DELETE
public void deleteUser()
{
System.out.println("Inside DELETE user method");
}
}
ClientProject (clientfile.jsp)
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Update User</title>
<script>
function loadResponse()
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("DELETE","http://localhost:8080/app/user/service",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv">The response text would come here</div>
<button type ="button" onclick="loadResponse()">submit</button>
</body>
</html>
The clientfile is supposed to print on console "Inside DELETE user method" but nothing is showed on console after "Build successful" message
What am I doing wrong? Also I am making use of TomCat server and doing this in NetBeans and I have to work on this IDE solely for some reason (kindly do not suggest to move to any other IDE and check it) if there is any mistake in my code or anything else pleaseee mention it?
Solution
First of all starting with requesting URL http://localhost:8080/app/user/service
when it falls in class level annotation - there are three methods so which one to pick so, needed to provide method level annotations as well for better approach.
@Path("/user/service")
public class UserServices {
@Path("/getUser")
@GET
public void getUser() { System.out.println("Inside GET method"); }
@Path("/updateUser")
@POST
public void updateUser() { System.out.println("Inside UPDATE method"); }
@Path("/deleteUser")
@DELETE
public void deleteUser() { System.out.println("Inside DELETE method"); }
}
Now coming towards something important which is necessary to make project(RestWebServer) accept requests from another project(Client Projects/app) which is hosted on separate domain, i.e. CORS (Cross Origin Resource Sharing)
CORS, in a nutshell, is a security check implemented like when an application requests for resources from or make server calls to another domain, these requests get blocked by browsers. Moreover you are using XMLHttpRequest
which forces same-origin policy i.e. request should generate from same domain where resources are residing so in order to make requests allow cross domain accessing we implement CORS Filter logic on server side to allow methods (P,G,P,D) to get executed.
So add a class like this in your WebService Project in package where UserServices
class is:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CORSFilter implements Filter {
public CORSFilter() { }
public void init(FilterConfig fConfig) throws ServletException { }
public void destroy() { }
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
((HttpServletResponse)response).addHeader("Access-Control-Allow-Origin", "*");
((HttpServletResponse)response).addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
chain.doFilter(request, response);
}
}
Now time to use this Filter
in web.xml
<web-app ....>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class><package name -must be complete>.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
clientFile.jsp
Now call method like this from view page with just method annotation added
xmlhttp.open('DELETE','http://localhost:8080/app/user/service/deleteUser',true);
Last thing you will have to make two server instances of Tomcat to deploy, name them Service and Client Server respectively for your convenience while making them. Let the Service one have all default config but you will have to change all three Port number for Client Server to avoid binding error. For this simply double click on server (Client) see Ports heading and change ports.
All done, it should run now, tested as well. Hope this will help you and other thread readers as well.
Answered By - mfaisalhyder