Spring 4 REST + CORS Integration using @CrossOrigin Annotation + XML + Filter Example

By Arvind Rai, February 07, 2017
This page will walk through Spring 4 REST and CORS integration using @CrossOrigin annotation, XML and Filter example. Browser restricts cross-origin HTTP request initiated from within scripts such as JavaScript, jQuery using AJAX because of security reason. Cross-Origin-Resource-Sharing (CORS) is the specification by W3C that allows HTTP request initiated from within scripts in safer way. CORS defines how the browser should be allowed using script to access different origin than the origin it has been served. In our application we can have the scenario such as our user interface can use CSS stylesheets, scripts, images and download links from different origins. Our code application can access a REST web service that is deployed on different origins. So in all these scenarios there is security threat to access different origin but cross origin resource sharing is also required. Hence W3C has provided a CORS specification that needs to be followed by browser and server both in order to perform cross origin resource sharing in safer way. In Cross-Origin-Resource-Sharing browser can send a pre-flight request to cross-origin i.e. different domain to check if request can be served or not before sending actual request. Once the pre-flight request is successful, then actual request is sent to cross-origin to get response.
In spring application using spring 4.2 and onwards, we can use @CrossOrigin annotation in our REST web service controller class to configure CORS. We can also configure global CORS in JavaConfig as well as XML configuration. Here on this page we will provide all the details and steps to use CORS using @CrossOrigin annotation and global CORS using JavaConfig and XML configuration. We will also provide the example to integrate java filter for CORS in our spring application. To test our REST web service application, we will create a client application in which we will have a jQuery code that will use AJAX call to access our REST application resource. Both applications will be deployed on different origins to test the CORS configuration. Now find the complete example step by step.

Software Used

We are using following software in our example.
1. Java 8
2. Spring 4.3
3. Gradle 3.3
4. Tomcat 8.0
5. Eclipse Mars

Pre-flight Requests

In Cross-Origin-Resource-Sharing (CORS) there are two types of requests, pre-flight requests and actual requests. Before sending actual request a pre-flight request is sent to the cross-origin in order to check if actual request is safe to send. Here cross-origin is a different domain than the domain from which it was served. Pre-flight request sends an HTTP request by the OPTIONS method to the cross-origin.
If actual request is a GET, HEAD and POST and Content-Type header for POST method is application/x-www-form-urlencoded, multipart/form-data and text/plain then there is no need to send a pre-flight request. In all other cases, browser sends a pre-flight request to cross-origin before actual request.
Suppose a client served from abc123.com domain wants to perform a DELETE request against a resource at xyz123.com domain. A preflight request will be sent with OPTIONS request. It will use the following request header.
OPTIONS /resource/abcd
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: http://abc123.com 
We observer that client served from abc123.com is asking to cross-origin server xyz123.com if it can perform DELETE request using Access-Control-Request-Method header. If the cross-origin server allows the request then it will respond to preflight request as below response header.
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: http://abc123.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 48000 
We observer here that cross-origin server responded with allowed method names using Access-Control-Allow-Methods header with the maximum age 48000 seconds using Access-Control-Max-Age. Here maximum age of 48000 seconds means that during this time POST, GET, OPTIONS, DELETE methods are allowed for the requested resource and no need to send pre-flight request for actual request. Once the maximum age expired then pre-flight request must be issued again before any actual request.

CORS HTTP Response Headers

Find the HTTP response headers that server sends back for access control requests defined by CORS specification.
Access-Control-Allow-Origin: This header specifies the URI that can be accessed by resource. If this header is not specified then by default all origins are allowed. If the value (*) is specified then all origins are allowed in the same way as default.
Access-Control-Allow-Methods: This header is used to specify methods to allow when accessing the resource. The methods can be GET, POST etc. If this header is not used then by default GET, POST and HEAD HTTP methods are allowed. If the HTTP methods has been specified to this header then only specified HTTP methods will be allowed and not the default. If we use (*) then all the HTTP methods will be allowed.
Access-Control-Allow-Headers: This header specifies response headers to pre-flight request that can be used by actual request. According to CORS specification we need not to list headers if that is one of the headers i.e. Cache-Control, Content-Language, Expires, Last-Modified, or Pragma. By default all headers are allowed. If we specify (*) then all headers will be allowed in the same way as default.
Access-Control-Expose-Headers: Using this header, server tells the browser about its whitelist headers. This is used by cross-origin server to send headers in the response of pre-flight request. These specified headers are those headers that will be used in actual response by cross-origin for an actual request. It does not support (*). No need to specify headers if it is one of the headers i.e. Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, or Pragma. We can specify here our custom headers. By default there is empty list of headers.
Access-Control-Allow-Credentials: This header takes input as boolean value and if its value is true then response to the request can be exposed to the page. The credentials are cookies, authorization headers or TLS client certificates. If the value is false then no credentials are sent by cross-origin.
Access-Control-Max-Age: This header defines the maximum age in seconds for cache to be alive for a pre-flight request. Once the maximum age is over then a pre-flight request will be sent again to cross-origin.

CORS using @CrossOrigin Annotation

Spring 4.2 has introduced @CrossOrigin annotation to handle Cross-Origin-Resource-Sharing (CORS). This annotation is used at class level as well as method level in RESTful Web service controller. @CrossOrigin annotation is used at method level with @RequestMapping annotation. If we are using @CrossOrigin at class and method level both then there will be combined effect. @CrossOrigin has following optional elements.
allowCredentials: This attribute defines the value for Access-Control-Allow-Credentials response header. The default value is true .
allowedHeaders: This attribute defines the values for Access-Control-Allow-Headers response header as comma separated. By default all requested headers are allowed.
exposedHeaders: This attribute defines the values for Access-Control-Expose-Headers response header as comma separated. By default, an empty exposed header list is used.
maxAge: This attribute defines the value for Access-Control-Max-Age response header. By default its value is 1800 seconds.
methods: This attribute defines the values for Access-Control-Allow-Methods response header as comma separated. By default methods attribute takes the value of @RequestMapping method. If @RequestMapping has defined POST method then this will be the value of methods attribute. If we specify methods attribute value in @CrossOrigin annotation then the default method will be overridden.
origins: This attribute defines the values for Access-Control-Allow-Origin response header as comma separated. By default all origins are allowed.

We use @CrossOrigin annotation as follows.
@CrossOrigin(origins = {"http://localhost:8585", "http://localhost:8787"},
                      maxAge = 4800, allowCredentials = "false") 
The above configuration will allow cross origin http://localhost:8585 and http://localhost:8787 . A pre-flight request will be valid for 4800 seconds. Find the project structure in eclipse.
Spring 4 REST + CORS Integration using @CrossOrigin Annotation + XML + Filter Example
Now find our REST web service controller.
PersonController.java
package com.concretepage.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.concretepage.domain.Person;
import com.concretepage.service.PersonService;
@CrossOrigin(origins = {"http://localhost:8585"}, maxAge = 4800, allowCredentials = "false")
@RestController
@RequestMapping("info")
public class PersonController {
	@Autowired
	private PersonService service;
	@CrossOrigin(origins = {"http://localhost:8787"}, maxAge = 6000)
	@RequestMapping("home")
	public List<Person> showData() {
		List<Person> list = service.getAllPerson();
		return list;
 	}
	@RequestMapping("nexthome")
	public List<Person> showDataNext() {
		List<Person> list = service.getAllPerson();
		return list;
 	}
} 
We observe following points from the above controller.
1. Class has been annotated using @CrossOrigin with origins, maxAge and allowCredentials attributes. So all the methods of this class annotated with @RequestMapping will follow CORS accordingly.
2.The method showData() has also been annotated with @CrossOrigin . The values of origins will be merged and the value of maxAge will be overridden by local @CrossOrigin annotation used on the method. Hence for the showData() method, origins will be http://localhost:8585 and http://localhost:8787 and the value of maxAge will be 6000 seconds.
3. The method showDataNext() will use the configuration of @CrossOrigin annotated at class level. The origins value will be http://localhost:8585 and maxAge value will be 4800 seconds.
4.The value of allowCredentials attribute of @CrossOrigin annotated at class level will be applied on every method of the class annotated with @RequestMapping .

Find other classes used in the CORS demo using @CrossOrigin annotation.
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'
war.archiveName 'spring-app.war'
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.5.1.RELEASE'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.5.1.RELEASE'    
}  
AppConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan("com.concretepage")
@EnableWebMvc
public class AppConfig {

} 
WebAppInitializer.java
package com.concretepage.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
} 
Person.java
package com.concretepage.domain;
public class Person {
	private int id;
	private String name;
	public Person(int id, String name) {
		this.id = id;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public String getName() {
		return name;
	}
} 
PersonService.java
package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.concretepage.domain.Person;
@Service
public class PersonService {
   public List<Person> getAllPerson() {
	   List<Person> list = new ArrayList<>();
	   list.add(new Person(1, "Mahesh"));
	   list.add(new Person(2, "Ram"));
	   list.add(new Person(3, "Krishna"));
	   return list;
   }
} 
If a client that domain is not listed in origins attributes of @CrossOrigin annotation in our REST web service controller, then the client will not be able to access resource. In the browser console of client we get following messages.
GET XHR http://localhost:8080/spring-app/info/home [HTTP/1.1 403 Forbidden 89ms]
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/spring-app/info/home. (Reason: CORS header 'Access-Control-Allow-Origin' missing). 


Global CORS using JavaConfig

Spring provides global CORS configuration using JavaConfig that will be applied for all REST web service controllers in our project. We can control global CORS using path pattern. Spring WebMvcConfigurerAdapter provides a method named as addCorsMappings() and in java configuration we need to override this method to configure CORS as follows.
@Override
public void addCorsMappings(CorsRegistry registry) {
	registry.addMapping("/**");
} 
The above code will allow CORS for all URL with default CORS response headers settings. If we want to override default configuration then we can do as follows.
AppConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@ComponentScan("com.concretepage")
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addCorsMappings(CorsRegistry registry) {
	  registry.addMapping("/info/**")
	   	  .allowedOrigins("http://localhost:8585", "http://localhost:8787")
		  .allowedMethods("POST", "GET",  "PUT", "OPTIONS", "DELETE")
		  .allowedHeaders("X-Auth-Token", "Content-Type")
		  .exposedHeaders("custom-header1", "custom-header2")
		  .allowCredentials(false)
		  .maxAge(4800);
	}
} 
CorsRegistry plays the role of registering CorsRegistration with given path pattern. registry.addMapping() returns the instance of spring CorsRegistration which consists the methods that configures CORS response headers. Now find the methods of CorsRegistration class.
allowedOrigins(): It specifies the allowed origins. By default it allows all origins. If we pass (*) then it will allow all origins in the same way as default.
allowedMethods(): It specifies the HTTP methods. If we use (*) then all HTTP methods will be allowed. By default GET, POST and HEAD HTTP methods are allowed. If we specify HTTP methods then only specified HTTP methods will be allowed and not the default.
allowedHeaders(): It specifies response headers to pre-flight request that can be used by actual request. According to CORS specification we need not to list headers if that is one of the headers i.e. Cache-Control, Content-Language, Expires, Last-Modified, or Pragma. By default all headers are allowed. If we specify (*) then all headers will be allowed in the same way as default.
exposedHeaders(): This is used by cross-origin server to send headers in the response of pre-flight request. These specified headers are those headers that will be used in actual response by cross-origin for an actual request. It does not support (*). No need to specify headers if it is one of the headers i.e. Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, or Pragma. We can specify here our custom headers. By default there is empty list of headers.
allowCredentials(): By default this value is true and the credentials such as cookies, authorization headers or TLS client certificates are allowed to actual request. We need to pass false value to change the behavior.
maxAge(): It configures the expiry time for pre-flight request cache. Default value is 1800 seconds.

Find the REST web service controller class used in our example.
PersonController.java
package com.concretepage.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.concretepage.domain.Person;
import com.concretepage.service.PersonService;
@RestController
@RequestMapping("info")
public class PersonController {
	@Autowired
	private PersonService service;
	@RequestMapping("home")
	public List<Person> showData() {
		List<Person> list = service.getAllPerson();
		return list;
 	}
} 

Global CORS using XML Configuration

Global CORS configuration can be performed using XML configuration. Spring provides spring MVC cors elements that is used as follows.
<mvc:cors>
   <mvc:mapping path="/info/**"
	allowed-origins="http://localhost:8585, http://localhost:8787"/>

   <mvc:mapping path="/nextinfo/**"
	allowed-origins="http://localhost:8989" />
</mvc:cors> 
For more than one path patterns we can use more than one mapping elements. Find the project structure in eclipse.
Spring 4 REST + CORS Integration using @CrossOrigin Annotation + XML + Filter Example
Now find the spring application context file used in our example.
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">            

   <context:component-scan base-package="com.concretepage"/>
   <mvc:annotation-driven />
   <mvc:cors>
	<mvc:mapping path="/info/**"
		allowed-origins="http://localhost:8585, http://localhost:8787"
		allowed-methods="POST, GET, PUT, OPTIONS, DELETE"
		allowed-headers="X-Auth-Token, Content-Type"
		exposed-headers="custom-header1, custom-header2"
		allow-credentials="false"
		max-age="4800" />
        </mvc:cors>
</beans>  
Find the attribute description.
path : It specifies the path pattern that will be used in CORS.
allowed-origins: It specifies comma separated list of origins. By default all origins are supported. If we specify (*) then all origins are supported in the same way as default.
allowed-methods: It specifies comma separated HTTP methods. By default GET, HEAD and POST HTTP methods are allowed. If we have specified HTTP methods then only those HTTP methods are allowed. If we use (*) then all HTTP methods are allowed.
allowed-headers: It specifies comma separated headers that is used by actual request after pre-flight request. If we use (*) then all headers are allowed.
exposed-headers: It specifies comma separated headers. These specified headers are those headers that will be used in actual response by cross-origin for an actual request after pre-flight request. It does not support (*). No need to specify headers if it is one of the headers i.e. Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, or Pragma. By default there is empty list of headers.
allow-credentials: It decides whether user credentials are supported or not. By default the value is true.
max-age: This is the maximum age for a pre-flight request cache after which a pre-flight request should be sent again. The default value is 1800 seconds.

Now find the web.xml used in the example.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

        <display-name>Spring 4 REST Example</display-name> 
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>  

CORS using Java Filter

Spring can use basic java filter to configure CORS. We will implement java Filter and configure CORS headers to response object in doFilter() method. Here I will provide JavaConfig and XML configuration both. First let us create our Filter implementation class.
CORSFilter.java
package com.concretepage.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class CORSFilter implements Filter {
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
        	HttpServletResponse httpResponse = (HttpServletResponse) response;
	        httpResponse.setHeader("Access-Control-Allow-Origin", "http://localhost:8585");
	        httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        	httpResponse.setHeader("Access-Control-Allow-Headers", "X-Auth-Token, Content-Type");
	        httpResponse.setHeader("Access-Control-Expose-Headers", "custom-header1, custom-header2");
        	httpResponse.setHeader("Access-Control-Allow-Credentials", "false");
	        httpResponse.setHeader("Access-Control-Max-Age", "4800");
	        System.out.println("---CORS Configuration Completed---");
	        chain.doFilter(request, response);
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
	@Override
	public void destroy() {
	}
} 
Now we will configure filter in our JavaConfig and XML. We can set path pattern in filter mapping. In our example we have allowed all path patterns. Find the files used in our example.
1. Using JavaConfig
AppConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan("com.concretepage")
@EnableWebMvc
public class AppConfig {

} 
WebAppInitializer.java
package com.concretepage.config;
import javax.servlet.Filter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.concretepage.filter.CORSFilter;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
        @Override
        protected Filter[] getServletFilters() {
    	        Filter [] filters = {new CORSFilter()};
    	        return filters;
        }
} 

2. Using XML Configuration
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">            

   <context:component-scan base-package="com.concretepage"/>
   <mvc:annotation-driven />

</beans>  
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

        <display-name>Spring 4 REST Example</display-name> 
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<filter>
		<filter-name>CORS</filter-name>
		<filter-class>com.concretepage.filter.CORSFilter</filter-class>
	</filter>
	<filter-mapping>
	        <filter-name>CORS</filter-name>
	        <url-pattern>/*</url-pattern>
	</filter-mapping>	  
</web-app>  

Create Client Application

To test the application, we are creating a HTML file and a JS file as follows.
index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Spring CORS Integration</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script src="show-data.js"> </script>
    </head>
    <body>
        <div>
            <div class="result"></div>
        </div>
    </body>
</html>  
show-data.js
$(document).ready(function() {
	$.ajax({
		url: "http://localhost:8080/spring-app/info/home"
	}).then(function(data) {
	  var items = [];
	  $.each( data, function( key, val ) {
		items.push("Id: "+val.id +", Name: "+val.name+">br/<");
	  });
          $('.result').append(items);
	});
}); 
Here we are using AJAX to call our REST web service and then displaying the result. We will deploy client code and REST web service code with two different server ports in our local machine so that we can test CORS configuration.

Test Application

To test the application we are using two instances of tomcat with different server ports. In one tomcat instance we are deploying REST web service code with port 8080 and in another tomcat instance we are deploying client project with port 8585 . Find all the steps to run and test the application.
1. Download the REST web service code by the link given below on this page.
2. Go to the root directory of the project using command prompt and build the project using gradle command
gradle clean build
3. Deploy the REST web service WAR in the first instance of tomcat with port 8080. Now our REST web service can be accessed with following URL.
http://localhost:8080/spring-app/info/home 
4. Now download the client project and deploy it in second instance of tomcat with port 8585.
5. Now run the client application with the URL
http://localhost:8585 
We can see that our client code is accessing a web service that is deployed in cross-origin. In our REST web service, we have configured Cross-Origin-Resource-Sharing (CORS) for the URL http://localhost:8585 and hence client application will successfully access our REST web service. We will get following output.
Spring 4 REST + CORS Integration using @CrossOrigin Annotation + XML + Filter Example


I am done now. Happy Spring Leaning!

References

HTTP access control (CORS)
W3C: Cross-Origin Resource Sharing
Understanding CORS
Enabling Cross Origin Requests for a RESTful Web Service

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us