Reputation: 5093
I have a resteasy webservice on a wildfly 10 on the same machine as my angular client.
curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i
works well on it without doing requests twice. At the contrary, when called with angular client, the restWebService is called twice!I tried to add a corsFilter but more than helping me being able to do get requests it didn't help me to solve my problem
package com.solarity.app; // {{ groupId}}.app
import com.solarity.rest.CompanyRestService;
import com.solarity.rest.PersonRestService;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
@ApplicationPath("/")
public class InitApplication extends Application {
/**
*
*/
Set<Object> singletons;
HashSet<Class<?>> webServiceClasses;
public InitApplication() {
super();
webServiceClasses = new HashSet<>();
webServiceClasses.add(PersonRestService.class);
webServiceClasses.add(CompanyRestService.class);
singletons = new LinkedHashSet<>();
singletons.add(this.getCorsFilter());
}
@Override
public Set<Class<?>> getClasses() {
return webServiceClasses;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
private CorsFilter getCorsFilter() {
CorsFilter result = new CorsFilter();
result.getAllowedOrigins().add("http://localhost:4200");
return result;
}
}
I tried to implement an options method into my webservice without success...
package com.solarity.rest; // Note your package will be {{ groupId }}.rest
import com.solarity.entities.CompanyEntity;
import com.solarity.entities.PersonEntity;
import com.solarity.service.CompanyService;
import com.solarity.service.PersonService;
import com.solarity.util.ResponseUtil;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
*
*
*/
@Path("/company")
public class CompanyRestService {
protected Logger logger = LoggerFactory.getLogger(getClass());
private CompanyService companyService = new CompanyService();
@GET // This annotation indicates GET request
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public Response getAll() {
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
this.logger.debug("companyServcfindAll----------------debug");
this.logger.warn("companyServcfindAll----------------WARN");
response = companyService.findAll();
} catch (Exception e) {
errMsg = "Error getting all persons";
logger.error(errMsg, e);
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.GET);
}
/**
* curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i
*
* @param id
* @return
*/
@DELETE
@Path("/{param}")
public Response delete(@PathParam("param") Integer id){
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
logger.debug("Deleting entity", id);
companyService.delete(id);
responseStatus = HttpStatus.SC_OK;
} catch (Exception e) {
errMsg = "Error Deleting Entity:" + id;
logger.error(errMsg, e);
response = errMsg;
responseStatus = HttpStatus.SC_METHOD_FAILURE;
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.DELETE);
}
/**
* Not working
* @return
*/
@OPTIONS
@Path("{path : .*}")
public Response options() {
return Response.ok("")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.build();
}
}//end Class
Here is my ResponseUtils class
package com.solarity.util;
import org.apache.http.HttpStatus;
import javax.ws.rs.core.Response;
public class ResponseUtil {
/**
*
Built to counter a Angular cross-reference problem
Adapted for Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/dlssResteasy1-1.0-SNAPSHOT/person/getPersonsAsJSON. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
source answer https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services?answertab=votes#tab-top
More Documentation about CORS on https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
* @param param the object to send if errorMsg is null
* @param errorMsg if not null sends an error code with error Message
* @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
* @return an altered response which is customized
*/
public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
Response result = null;
int rStatus = responseStatus;
if (errorMsg != null && responseStatus <= 0) {
rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
} else if (errorMsg == null && responseStatus <= 0){
rStatus = HttpStatus.SC_OK;
}
if ( errorMsg == null ) {
result = Response
.status(rStatus)
.entity(param)
.build();
}else{
result = Response.status(rStatus)
.entity(errorMsg)
.build();
}
return result;
}
}
Here is the result of debug into FF
Upvotes: 0
Views: 2937
Reputation: 1349
You can see the traffic with Chrome DevTools in the Network tab
Upvotes: 0
Reputation: 5093
First of all there is a documentation about CORS I HAD TO READ to understand, I couldn't avoid that as I hoped...
Part of the answer of my problem was in fact two calls from Angular.
I didn't understand that everytime a call to subscribe
on an httpclient.put()
is done a call is done!
Calling the subscribe() method executes the observable, which is what initiates the DELETE request.
So What I did was:
methodResult = httpclient.put('someUrl', someData, someHeader).subscribe({ data => { console.log('added') });
abovePutMethod.subscribe( data => { doSomeThingWithComponentRefresh })
So doing only ONE call to subscribe solved my twice call problem
//UrlHelper
public static putHttpRequestOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
//Function call somewhere
const result = this.httpClient.put(url, jsonStringValues, UrlHelper.putHttpRequestOptions);
// InitApplication extends Application
public InitApplication() {
super();
webServiceClasses = new HashSet<>();
webServiceClasses.add(PersonRestService.class);
webServiceClasses.add(CompanyRestService.class);
singletons = new LinkedHashSet<>();
singletons.add(this.getCorsFilter());
}
private CorsFilter getCorsFilter() {
CorsFilter result = new CorsFilter();
result.getAllowedOrigins().add("*");
result.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
result.setCorsMaxAge(86400);//Max in FF 86400=24h https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
//
return result;
}
// RestWebService
@PUT
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public Response put(CompanyEntity entity ){
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
logger.debug("Received entity", entity);
companyService.persist(entity);
responseStatus = HttpStatus.SC_CREATED;
} catch (Exception e) {
errMsg = "Error adding Entity:" + entity;
logger.error(errMsg, e);
response = errMsg;
responseStatus = HttpStatus.SC_METHOD_FAILURE;
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.PUT);
}
// Called on result of all RestWebServices (I'm sure there are better/best practices, feel free to comment me this section)
/**
* @param param the object to send if errorMsg is null
* @param errorMsg if not null sends an error code with error Message
* @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
* @return an altered response which is customized
*/
public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
Response result = null;
int rStatus = responseStatus;
if (errorMsg != null && responseStatus <= 0) {
rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
} else if (errorMsg == null && responseStatus <= 0){
rStatus = HttpStatus.SC_OK;
}
String accessControlAllowMethods = "GET, POST, PUT, DELETE, OPTIONS, HEAD";
if ( errorMsg == null ) {
result = Response
.status(rStatus)
.header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
.header("Access-Control-Allow-Methods", accessControlAllowMethods)
.header("Access-Control-Max-Age", "1728000")
.entity(param)
.build();
}else{
result = Response.status(rStatus)
.header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
.header("Access-Control-Allow-Methods", accessControlAllowMethods)
.header("Access-Control-Max-Age", "1728000")
.entity(errorMsg)
.build();
}
return result;
}
Upvotes: 0
Reputation: 1349
Add to this thread the copy of the OPTIONS request and response ( not the one you created but the one from the package your are using, if you are not using a package , look for one) , to see what is wrong with the configuration.
Add also the next POST,GET,PUT, etc. both the request and response
Upvotes: 1