Key Terminology of Web Services
Characteristics of Web Services
Architecture of Web Services
Types of Web Services
Web Services Components
SOAP vs RESTful Web Services
RESTful - Spring Boot
Introduction to RESTful Web Services With Spring Boot
Initializing a RESTful Web Services
Spring Boot Auto Configuration and Dispatcher Servlet
Enhancing the Hello World Service with a Path Variable
Implementing the POST Method to create User Resource
Implementing Exception Handling- 404 Resource Not Found
Implementing Generic Exception Handling for all Resources
Implementing DELETE Method to Delete a User Resource
Implementing Validations for RESTful Services
Implementing HATEOAS for RESTful Services
Internationalization of RESTful Services
Content Negotiation Implementing Support for XML
Configuring Auto Generation of Swagger Documentation
Introduction to Swagger Documentation Format
Enhancing Swagger Documentation with Custom Annotations
Monitoring APIs with Spring Boot Actuator
Implementing Static Filtering for RESTful Services
Implementing Dynamic Filtering for RESTful Services
Versioning RESTful Web Services-Basic Approach With URIs
Implementing Basic Authentication with Spring Security
Connecting RESTful Services to JPA
Updating GET Methods on User Resource to Use JPA
Updating POST and DELETE methods on UserResource to use JPA
Creating Post Entity and Many to One Relationship with User Entity
Implementing a GET service to retrieve all Posts of a User
Implementing POST Service to Create a Post for a User
Richardson Maturity Model
RESTful Web Services Best Practice
Internationalization of RESTful Services
In this section, we will discuss the Internationalization of the RESTful Web Services.
Internationalization
Internationalization is the process of designing web applications or services in such a way that it can provide support for various countries, various languages automatically without making the changes in the application. It is also known as
I18N
because the word internationalization has total 18 characters starting from
I
to
N
.
Localization is performed by adding locale-specific components such as translated text, data describing locale-specific behavior, etc. It supports full integration into the classes and packages that provide language-or-culture-dependent functionality.
Java provides the foundation for internationalization for desktop and server applications. There are following important internationalized areas of functionality.
Text Representation:
Java is based on the Unicode character set, and several libraries implement the Unicode standard.
Locale identification and localization:
Locale in Java are identifiers that can be used to request locale-specific behavior in different areas of functionality. Localization is supported by ResourceBundle class. The class provides access to local specific objects, including strings.
Date and time handling:
Java provides various calendars. It supports conversion to and from calendar independent Date objects. Java supports all the time zones in the world.
Text processing:
It includes character analysis, case mapping, string comparison, breaking text into words, formatting numbers, dates, and time values into strings or parsing them back from strings. Most of these functions are locale-dependent.
Character encoding:
It supports converting text between Unicode and other character encodings when reading incoming text from the streams or writing outgoing text to the streams.
We need to configure two things to make the service internationalized.
LocaleResolver
ResourceBundleMessageSource
Default Locale is Locale.US. If somebody does not specify the location, it returns the default locale. We also need to customize the ResourceBundle. It has a list of properties that are to be internationalized. We will store the properties in ResourceBundle.
ResourceBundleMessageSource
is a Spring MVC concept for handling properties. After that, we will use MessageSource, and a header called Accept-Language.
Let's configure the internationalization.
Step 1:
Open
RestfulWebServicesApplication.java
file.
Step 2:
Configure a Bean for
default
locale.
@Bean
public LocaleResolver localeResolver()
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
Note: Import import org.springframework.web.servlet.LocaleResolver package while importing LocaleResolver.
Step 3:
Now, we will store properties in a specific file called
messages.properties
.
Right-click on
src/main/resources
folder -> New -> File -> Provide the file name:
messages.properties
. It contains the default locale message.
messages.properties
good.morning.message=Good Morning
Step 4:
Create another property file with the name
messages_fr.properties
for French locale. It contains a message for the French locale.
messages_fr.properties
good.morning.message=Bonjour
Step 5:
Read properties and customize them based on the input accept header. Open the RestfulWebServicesApplication.java and configure another Bean for
ResourceBundle
.
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource bundleMessageSource()
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
RestfulWebServicesApplication.java
package com.javatpoint.server.main;
import java.util.Locale;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@SpringBootApplication
public class RestfulWebServicesApplication
public static void main(String[] args)
SpringApplication.run(RestfulWebServicesApplication.class, args);
//configuring default locale
@Bean
public LocaleResolver localeResolver()
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource messageSource()
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
Step 6:
Update the service to use these sources. Open the
HelloWorldController.java
and autowired the MessageSource.
@Autowired
private MessageSource messageSource;
HelloWorldController.java
package com.javatpoint.server.main.helloworld;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Configuration;
@Configuration
//Controller
@RestController
public class HelloWorldController
@Autowired
private MessageSource messageSource;
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
return "Hello World";
@GetMapping(path="/hello-world-bean")
//method- which returns "Hello World"
public HelloWorldBean helloWorldBean()
return new HelloWorldBean("Hello World");//constructor of HelloWorldBean
//passing a path variable
//hello-world/path-variable/javatpoint
@GetMapping(path="/hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name)
return new HelloWorldBean(String.format("Hello World, %s",name)); //%s replace the name
//internationalization
@GetMapping(path="/hello-world-internationalized")
public String helloWorldInternationalized(@RequestHeader(name="Accept-Language", required=false) Locale locale)
return messageSource.getMessage("good.morning.message", null, locale);
Step 7:
Open the REST client
Postman
and perform the following changes:
Select the
GET
request.
Type the URI http://localhost:8080/hello-world-internationalized
Click on
Headers
tab and type:
Click on the Send button.
It returns the US locale message
Good Morning
.
Now we change the RequestHeader us to fr and send a GET request again.
It returns the French locale message
Bonjour
.
Again, change the RequestHeader fr to other RequestHeader, say
nl
. It returns the default locale (US) message
Good Morning
.
Let's create a property file
message_nl.properties
for RequestHeader
nl
. It contains a message Goede Morgen in the
Dutch
language.
messages_nl.properties
good.morning.message=Goede Morgen
Again send a
GET
request that returns the message,
Goede Morgen
.
Simplify the Internationalization
Now we will simplify the implementation of internationalization, which we have done above. In the previous implementation, we have accepted locale (a RequestHeader) as a parameter to the REST controller method. If we add this to every method that has to be internationalized, it will increase the cost. Spring provides an alternative way to get it from the
LocaleContextHolder
.
Let's implement the LocaleContextHolder instead of RequestHeader.
Step 1:
Open the
HelloWorldController.java
and change the return type of the helloWorldInternationalized() method.
return messageSource.getMessage("good.morning.message", null, LocaleContextHolder.getLocale());
HelloWorldController.java
package com.javatpoint.server.main.helloworld;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.i18n.LocaleContextHolder;
@Configuration
//Controller
@RestController
public class HelloWorldController
@Autowired
private MessageSource messageSource;
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
return "Hello World";
@GetMapping(path="/hello-world-bean")
//method- which returns "Hello World"
public HelloWorldBean helloWorldBean()
return new HelloWorldBean("Hello World");//constructor of HelloWorldBean
//passing a path variable
//hello-world/path-variable/javatpoint
@GetMapping(path="/hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name)
return new HelloWorldBean(String.format("Hello World, %s",name)); //%s replace the name
//internationalization
@GetMapping(path="/hello-world-internationalized")
public String helloWorldInternationalized(@RequestHeader(name="Accept-Language", required=false) Locale locale)
return messageSource.getMessage("good.morning.message", null, LocaleContextHolder.getLocale());
Step 2:
Open
RestfulWebServicesApplication.java
and change SessionLocaleResolver to AcceptHeaderLocaleResolver. LocaleResolver implementation uses the primary locale specified in the "accept-language" header of the HTTP request (locale send by the client browser).
RestfulWebServicesApplication.java
package com.javatpoint.server.main;
import java.util.Locale;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@SpringBootApplication
public class RestfulWebServicesApplication
public static void main(String[] args)
SpringApplication.run(RestfulWebServicesApplication.class, args);
//configuring default locale
@Bean
public LocaleResolver localeResolver()
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource messageSource()
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
The advantage of AcceptHeaderLocaleResolver is that we do not require to configure request header as a parameter in every controller method.
Step 3:
Open the REST client Postman and send a GET request by setting the key as Accept-Language and value as fr. It returns the message Bonjour.
Now uncheck the RequestHeader, change the value fr to en. It returns the default locale (US) message Good Morning.
Step 4:
Move to RestfulWebServicesApplication.java. Remove the ResourceBundleMessageSource() method and configure it in the
application.properties
file.
Step 5:
Open application.properties file and configure the message basename instead of creating a separate bean in RestfulWebServicesApplication.java.
application.properties
logging.level.org.springframework=info
spring.messages.basename=messages
Step 6:
Repeat step 3.
Click here to download Internationalization of RESTful Services project
Click here to download Before Removing- ResourceBundleMessageSource project
Click here to download After Removing- ResourceBundleMessageSource project
Next Topic
Content Negotiation Implementing Support for XML