I have downloaded Jersey Java Rest Api example from https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/post-example.html
When I run this project using 'Run on server', it is accepting the following Rest api commands from Postman and perfectly working fine:
GET http://localhost:9900/jaxrs-post-example/rest/customers
POST http://localhost:9900/jaxrs-post-example/rest/customers
{
"firstName":"David",
"lastName":"Parker",
"school":"CSI",
"standard":"4",
"rollNumber":85
}
When I send same command from ReactJS, the server is showing the following error in ReactJS.
Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
To fix this issue, I have added the following in RestServer.java (Based on How to handle CORS using JAX-RS with Jersey)
@Provider
@PreMatching
public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter {
/**
* Method for ContainerRequestFilter.
*/
@Override
public void filter(ContainerRequestContext request) throws IOException {
// If it's a preflight request, we abort the request with
// a 200 status, and the CORS headers are added in the
// response filter method below.
if (isPreflightRequest(request)) {
request.abortWith(Response.ok().build());
return;
}
}
/**
* A preflight request is an OPTIONS request
* with an Origin header.
*/
private boolean isPreflightRequest(ContainerRequestContext request) {
return request.getHeaderString("Origin") != null
&& request.getMethod().equalsIgnoreCase("OPTIONS");
}
/**
* Method for ContainerResponseFilter.
*/
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response)
throws IOException {
// if there is no Origin header, then it is not a
// cross origin request. We don't do anything.
if (request.getHeaderString("Origin") == null) {
return;
}
// If it is a preflight request, then we add all
// the CORS headers here.
if (isPreflightRequest(request)) {
response.getHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
response.getHeaders().add("Access-Control-Allow-Headers",
// Whatever other non-standard/safe headers (see list above)
// you want the client to be able to send to the server,
// put it in this list. And remove the ones you don't want.
"X-Requested-With, Authorization, " +
"Accept-Version, Content-MD5, CSRF-Token, Content-Type");
}
// Cross origin requests can be either simple requests
// or preflight request. We need to add this header
// to both type of requests. Only preflight requests
// need the previously added headers.
response.getHeaders().add("Access-Control-Allow-Origin", "*");
}
}
Also, I have added the following in web.xml
<web-app>
<display-name>JAX-RS Web Application</display-name>
<servlet>
<servlet-name>jersey-json-example-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.javacodegeeks.rest.jersey.server.CORSFilter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.javacodegeeks.rest.jersey.server</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-json-example-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
When I tried Flask+Python with CORS, the command from ReactJS is perfectly working.
ReactJS change: fetch('http://localhost:5000/jaxrs-post-example/rest/customers',
Flask+Python code:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'xyz'
app.config['CORS_HEADERS'] = 'Content-Type'
#Allow specific origin
cors = CORS(app, resources={r"/jaxrs-post-example/*": {"origins": ["http://localhost:3000"]}})
@app.route('/jaxrs-post-example/rest/customers', methods=['GET', 'POST'])
def getStudent():
print("You are getting getStudent request")
content = request.json
id = content['id']
name = content['name']
address = content['address']
phoneNumber = content['phoneNumber']
print("id = ", id)
print("name = ", name)
print("address = ", address)
print("phoneNumber = ", phoneNumber)
json_object = JFY({"result": "getStudent is called"})
print("json_results = ", json_object)
print("response for getStudent = ", json_object.get_json())
return json_object
The output is perfect
127.0.0.1 - - [08/Sep/2020 21:00:40] "OPTIONS /jaxrs-post-example/rest/customers HTTP/1.1" 200 -
127.0.0.1 - - [08/Sep/2020 21:00:41] "POST /jaxrs-post-example/rest/customers HTTP/1.1" 200 -
You are getting getStudent request
id = 2152
name = David
address = 12,new street
phoneNumber = 8765489011
json_results = <Response 39 bytes [200 OK]>
response for getStudent = {'result': 'getStudent is called'}
Questions:
- How to achieve CORS in Jersey Java (similar to Flask+Python)?
- Please provide a solution for this issue