On client side I'm using Ajax.post (jquery 1.5) with json. On server side I'm using rest resteasy-jaxrs-2.0.1.GA. I found somewhere that i should add couple of headers to server response and I've done with following filter:
public void doFilter( ServletRequest req,
ServletResponse res,
FilterChain filterChain)
throws IOException, ServletException {
MyServletRequestWrapper httpReq = new MyServletRequestWrapper((HttpServletRequest)req);
HttpServletResponse httpRes = (HttpServletResponse)res;
HttpSession session = httpReq.getSession();
httpRes.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (((HttpServletRequest) req).getMethod().equals("OPTIONS")){
httpRes.addHeader(ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, "content-type, x-requested-with, x-requested-by");
}
filterChain.doFilter(httpReq, httpRes);
}
It works fine cause to every single GET response above headers are added. Problem appears when I want to use POST request. When I use Ajax.post, at first server gets OPTIONS request and I've got following error:
Failed executing OPTIONS [REST_PATH]
org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method found for options, return OK with Allow header
To solve above error I was trying to add method invoke with the same path as POST ([REST_PATH]) but with @OPTION annotation. In that case javac told me that symbol :class OPTIONS could not be found, even there is a OPTION.class in attached jaxrs library.
Any ideas to fix it? I would be very grateful for any clues.
This question is quite old, but as a reference for others with similar problems - just recently i came across a nice "CORS Filter" you may want to consider using. It's just a matter of adding the following lines to your web.xml and it works like a charm.
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<servlet-name>MyServletNameGoesHere</servlet-name>
</filter-mapping>
and the maven dependency:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.5.1</version>
</dependency>
When I was trying to call my service with an Angular 2 client RestEasy was responding to the preflight requests with the HTTP status 500 and the following error.
RESTEASY003655: No resource method found for options, return OK with
Allow header
I tried RestEasy's CorsFilter but I'd like to propose a simple alternative. What if you don't want to write code handling the OPTIONS call for each of your endpoints ?
I implemented a simple filter that:
- Applies the CORS header you need to the response.
- Returns the HTTP status code 200 when calling an endpoint with the OPTIONS method. You tell the client that its CORS preflight requests were accepted.
Here is the code. Feel free to refine the filter if you only want to send back a 200 when querying a "real" endpoint.
@Provider
public class CorsFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*"); // If you want to be more restrictive it could be localhost:4200
headers.add("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS"); // You can add HEAD, DELETE, TRACE, PATCH
headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Accept-Language"); // You can add many more
if (requestContext.getMethod().equals("OPTIONS"))
responseContext.setStatus(200);
}}
Make sure to understand CORS too.
The CORS filter may be fine. I would like to point out as you wrote "To solve above error I was trying to add method invoke with the same path as POST ([REST_PATH]) but with @OPTION annotation. In that case javac told me that symbol :class OPTIONS could not be found, " that you had a typo there instead of @OPTIONS
you wrote @OPTION
without the S
:)
There is a built in CORS filter in tomcat.
http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>