Como lidar com CORS usando JAX-RS com Jersey

Estou desenvolvendo um aplicativo cliente de script java, no lado do servidor eu preciso lidar com o CORS, todos os serviços que eu escrevi no JAX-RS com o JERSEY. Meu código:

@CrossOriginResourceSharing(allowAllOrigins = true) @GET @Path("/readOthersCalendar") @Produces("application/json") public Response readOthersCalendar(String dataJson) throws Exception { //my code. Edited by gimbal2 to fix formatting return Response.status(status).entity(jsonResponse).header("Access-Control-Allow-Origin", "*").build(); } 

A partir de agora, estou recebendo o erro No header ‘Access-Control-Allow-Origin’ está presente no recurso solicitado. A origem ‘ http: // localhost: 8080 ‘ não tem, portanto, access permitido. ”

Por favor me ajude com isso.

Obrigado e cumprimentos Buddha Puneeth

Não tenho conhecimento de nenhum suporte CORS padrão com Jersey. @CrossOriginResourceSharing , até onde eu sei, é uma anotação CXF. Então eu não tenho certeza de como você está usando esta anotação com Jersey.

Com Jersey, para lidar com o CORS, normalmente uso um ContainerResponseFilter . O ContainerResponseFilter para Jersey 1 e 2 são um pouco diferentes. Como você não mencionou qual versão está usando, postarei os dois.

Jersey 2

 import java.io.IOException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; @Provider public class CORSFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException { response.getHeaders().add("Access-Control-Allow-Origin", "*"); response.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); response.getHeaders().add("Access-Control-Allow-Credentials", "true"); response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); } } 

Se você usar a varredura de pacotes para descobrir provedores e resources, a anotação @Provider deverá cuidar da configuração para você. Caso contrário, você precisará registrá-lo explicitamente com a subclass ResourceConfig ou Application .

Exemplo de código para registrar explicitamente o filtro com o ResourceConfig :

 final ResourceConfig resourceConfig = new ResourceConfig(); resourceConfig.register(new CORSFilter()); final final URI uri = ...; final HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(uri, resourceConfig); 

Jersey 1

 import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerResponse; import com.sun.jersey.spi.container.ContainerResponseFilter; public class CORSFilter implements ContainerResponseFilter { @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { response.getHttpHeaders().add("Access-Control-Allow-Origin", "*"); response.getHttpHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true"); response.getHttpHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); return response; } } 

configuração web.xml, você pode usar

  com.sun.jersey.spi.container.ContainerResponseFilters com.yourpackage.CORSFilter  

Ou ResourceConfig você pode fazer

 resourceConfig.getContainerResponseFilters().add(new CORSFilter()); 

Ou digitalização de pacotes com a anotação @Provider .


EDITAR

Por favor, note que o exemplo acima pode ser melhorado. Você precisará saber mais sobre como o CORS funciona. Por favor, veja aqui . Por um lado, você receberá os headers de todas as respostas. Isso pode não ser desejável. Você pode precisar apenas lidar com a pré-impressão (ou OPTIONS). Se você quiser ver um filtro CORS implementado melhor, você pode verificar o código-fonte do RESTeasy CorsFilter

A outra resposta pode ser estritamente correta, mas enganosa. A parte que falta é que você pode misturar filtros de diferentes fonts juntos. Mesmo que o Jersey não forneça o filtro CORS (não é um fato que verifiquei, mas confio na outra resposta), você pode usar o filtro CORS do próprio tomcat .

Eu estou usando com sucesso com Jersey. Eu tenho minha própria implementação do filtro de autenticação básica, por exemplo, junto com o CORS. O melhor de tudo é que o filtro CORS é configurado em XML da Web, não em código.

A resposta da peeskillet está correta. Mas recebo este erro quando atualizo a página da web (ela está funcionando apenas na primeira carga):

 The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'http://127.0.0.1:8080' is therefore not allowed access. 

Então, ao invés de usar add method para adicionar headers para resposta, eu uso put method. Esta é minha aula

 public class MCORSFilter implements ContainerResponseFilter { public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; public static final String ACCESS_CONTROL_ALLOW_ORIGIN_VALUE = "*"; private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_VALUE = "true"; public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; public static final String ACCESS_CONTROL_ALLOW_HEADERS_VALUE = "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With, Accept"; public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; public static final String ACCESS_CONTROL_ALLOW_METHODS_VALUE = "GET, POST, PUT, DELETE, OPTIONS, HEAD"; public static final String[] ALL_HEADERs = { ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS }; public static final String[] ALL_HEADER_VALUEs = { ACCESS_CONTROL_ALLOW_ORIGIN_VALUE, ACCESS_CONTROL_ALLOW_CREDENTIALS_VALUE, ACCESS_CONTROL_ALLOW_HEADERS_VALUE, ACCESS_CONTROL_ALLOW_METHODS_VALUE }; @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { for (int i = 0; i < ALL_HEADERs.length; i++) { ArrayList value = new ArrayList<>(); value.add(ALL_HEADER_VALUEs[i]); response.getHttpHeaders().put(ALL_HEADERs[i], value); //using put method } return response; } } 

E adicione essa class ao init-param no web.xml

  com.sun.jersey.spi.container.ContainerResponseFilters com.yourpackage.MCORSFilter  

Remover anotação ” @CrossOriginResourceSharing(allowAllOrigins = true)

Então retorne a resposta como abaixo:

 return Response.ok() .entity(jsonResponse) .header("Access-Control-Allow-Origin", "*") .build(); 

Mas o jsonResponse deve replace por um object POJO!

Para resolver isso para o meu projeto eu usei a resposta de Micheal e cheguei a isto:

   org.apache.tomcat.maven tomcat7-maven-plugin 2.2   run-embedded  run  pre-integration-test  ${maven.tomcat.port} true ${project.basedir}/tomcat/context.xml  ${maven.tomcat.web-xml.file}     

O filtro CORS é o filtro de exemplo básico do site do tomcat.

Editar :
A variável maven.tomcat.web-xml.file é uma propriedade pom defined para o projeto e contém o caminho para o arquivo web.xml (localizado dentro do meu projeto)

Usando o JAX-RS, você pode simplesmente adicionar a anotação @CrossOrigin(origin = yourURL) ao seu controlador de resources. No seu caso, seria @CrossOrigin(origin = "http://localhost:8080") mas você também poderia usar @CrossOrigin(origin = "*") para permitir que qualquer requisição @CrossOrigin(origin = "*") pelo seu webservice.
Você pode verificar isso para mais informações.