Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Overview

Frequently, we find ourselves tasked with designing applications that must deliver localized messages within a multilingual environment. In such scenarios, delivering messages in the user’s selected language is a common practice.

When we receive client requests to a REST web service, we must ensure the incoming client requests meet the predefined validation rules before processing them. Validations aim to maintain data integrity and enhance system security. The service is responsible for providing informative messages to indicate what’s wrong with the request whenever the validation fails.

In this tutorial, we’ll explore the implementation of delivering localized validation messages in a REST web service.

2. Essential Steps

Our journey begins with utilizing resource bundles as a repository for storing localized messages. We’ll then integrate resource bundles with Spring Boot which allows us to retrieve localized messages in our application.

After that, we’ll jump on to web service creation containing request validation. This showcases how localized messages are utilized in the event of a validation error during a request.

Finally, we’ll explore different kinds of localized message customization. These include overriding the default validation messages, defining our own resource bundle to provide custom validation messages, and creating a custom validation annotation for dynamic message generation.

Through these steps, we’ll refine our understanding of delivering precise and language-specific feedback in multilingual applications.

3. Maven Dependency

Before we get started, let’s add the Spring Boot Starter Web and Spring Boot Starter Validation dependencies for web development and Java Bean Validation to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

The latest version of these can be found on Maven Central.

4. Localized Messages Storage

In Java application development, property files commonly function as repositories for localized messages in internationalized applications. It’s considered a conventional approach to localization. It’s often named a property resource bundle.

These files are plain text documents comprising key-value pairs. The key functions as an identifier for message retrieval, while the associated value holds the localized message in the corresponding language.

In this tutorial, we’ll create two property files.

CustomValidationMessages.properties is our default property file where the file name doesn’t contain any locale name. The application always falls back to its default language whenever the client specifies a locale that isn’t supported:

field.personalEmail=Personal Email
validation.notEmpty={field} cannot be empty
validation.email.notEmpty=Email cannot be empty

We’d like to create an additional Chinese language property file as well – CustomValidationMessages_zh.properties. The application language switches to Chinese whenever the client specifies either zh or variants such as zh-tw as the locale:

field.personalEmail=個人電郵
validation.notEmpty={field}不能是空白
validation.email.notEmpty=電郵不能留空

We must ensure that all property files are encoded in UTF-8. This becomes particularly crucial when handling messages that include non-Latin characters like Chinese, Japanese, and Korean. This assurance guarantees that we’ll display all messages accurately without the risk of corruption.

5. Localized Messages Retrieval

Spring Boot simplifies the localized message retrieval through the MessageSource interface. It resolves messages from resource bundles in the application and enables us to obtain messages for different locales without additional effort.

We must configure the provider of MessageSource in Spring Boot before we can make use of it. In this tutorial, we’ll use ReloadableResourceBundleMessageSource as the implementation.

It’s capable of reloading message property files without server restart. This is very useful when we’re in the initial stage of application development when we want to see the message changes without redeploying the whole application.

We have to align the default encoding with the UTF-8 encoding that we’re using for our property files:

@Configuration
public class MessageConfig {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:CustomValidationMessages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
}

6. Bean Validation

In the validation process, a Data Transfer Object (DTO) named User is used, which contains an email field. We’ll apply Java Bean Validation to validate this DTO class. The email field is annotated with @NotEmpty to make sure it isn’t an empty string. This annotation is a standard Java Bean Validation annotation:

public class User {
	
    @NotEmpty
    private String email;

    // getters and setters
}

7. REST Service

In this section, we’ll create a REST service, UserService, which is responsible for updating specific user information via the PUT method based on the request body:

@RestController
public class UserService {

    @PutMapping(value = "/user", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<UpdateUserResponse> updateUser(
      @RequestBody @Valid User user,
      BindingResult bindingResult) {

        if (bindingResult.hasFieldErrors()) {

            List<InputFieldError> fieldErrorList = bindingResult.getFieldErrors().stream()
              .map(error -> new InputFieldError(error.getField(), error.getDefaultMessage()))
              .collect(Collectors.toList());

            UpdateUserResponse updateResponse = new UpdateUserResponse(fieldErrorList);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(updateResponse);
        }
        else {
            // Update logic...
            return ResponseEntity.status(HttpStatus.OK).build();
        }
    }

}

7.1. Locale Selection

It’s a common practice to employ the Accept-Language HTTP header to define the client’s language preference.

We can obtain the locale from the Accept-Language header in the HTTP request by using the LocaleResolver interface in Spring Boot. In our case, we don’t have to explicitly define a LocaleResolver. Spring Boot provides a default one for us.

Our service then returns the appropriate localized messages in accordance with this header. In situations where the client designates a language that our service doesn’t support, our service simply adopts English as the default language.

7.2. Validation

We annotate User DTO with @Valid in the updateUser(…) method. This indicates that Java Bean Validation validates the object when the REST web service is called. Validation occurs behind the scenes. We’ll examine the validation outcomes via the BindingResult object.

Whenever there is any field error, which is determined by bindingResult.hasFieldErrors(), Spring Boot fetches the localized error message for us according to the current locale and encapsulates the message into a field error instance.

We’ll iterate each field error in BindingResult and collect them into a response object, and send the response back to the client.

7.3. Response Objects

If validation fails, the service returns an UpdateResponse object containing the validation error messages in the specified language:

public class UpdateResponse {

    private List<InputFieldError> fieldErrors;

    // getter and setter
}

InputFieldError is a placeholder class to store which field contains the error and what the error message is:

public class InputFieldError {

    private String field;
    private String message;

    // getter and setter
}

8. Validation Message Types

Let’s initiate an update request to the REST service /user with the following request body:

{
    "email": ""
}

As a reminder, the User object must contain a non-empty email. Therefore, we expect that this request triggers a validation error.

8.1. Standard Message

We’ll see the following typical response with an English message if we don’t provide any language information in the request:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "must not be empty"
        }
    ]
}

Now, let’s initiate another request with the following accept-language HTTP header:

accept-lanaguage: zh-tw

The service interprets that we’d like to use Chinese. It retrieves the message from the corresponding resource bundle. We’ll see the following response that includes the Chinese validation message:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "不得是空的"
        }
    ]
}

These are standard validation messages provided by the Java Bean Validation. We can find an exhaustive list of messages from the Hibernate validator, which serves as the default validation implementation.

However, the messages we saw don’t look nice. We probably want to change the validation message to provide more clarity. Let’s take a move to modify the standardized messages.

8.2. Overridden Message

We can override default messages defined in Java Bean Validation implementation. All we need to do is define a property file that has the basename ValidationMessages.properties:

jakarta.validation.constraints.NotEmpty.message=The field cannot be empty

With the same basename, we’ll create another property file ValidationMessages_zh.properties for Chinese as well:

jakarta.validation.constraints.NotEmpty.message=本欄不能留空

Upon calling the same service again, the response message is replaced by the one we defined:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "The field cannot be empty"
        }
    ]
}

However, the validation message still looks generic despite overriding the message. The message itself doesn’t reveal which field goes wrong. Let’s proceed to include the field name in the error message.

8.3. Customized Message

In this scenario, we’ll dive into customizing validation messages. We defined all customized messages in the CustomValidationMessages resource bundle earlier.

Then, we’ll apply the new message {validation.email.notEmpty} to the validation annotation to the User DTO. The curly bracket indicates the message is a property key linking it to the corresponding message within the resource bundle:

public class User {
	
    @NotEmpty(message = "{validation.email.notEmpty}")
    private String email;

    // getter and setter
}

We’ll see the following message when we initiate a request to the service:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "Email cannot be empty"
        }
    ]
}

8.4. Interpolated Message

We’ve improved the message significantly by including the field name in the message. However, a potential challenge arises when dealing with many fields. Imagine a scenario where we have 30 fields, and each field requires three different types of validations. This would result in 90 validation messages within each localized resource bundle.

We could utilize message interpolation to address this issue. Interpolated messages operate on placeholders that are replaced dynamically with actual values before presenting them to users. In the scenario that we mentioned before, this approach reduces the number of validation messages to 33, containing 30 field names and three unique validation messages.

Java Bean Validation doesn’t support a validation message with a self-defined placeholder. However, we can define a custom validation that includes additional attributes.

This time, we annotate the User with a new customized annotation @FieldNotEmpty. Based on the existing message attribute, we’ll introduce a new attribute field to indicate the field name:

public class User {

    @FieldNotEmpty(message = "{validation.notEmpty}", field = "{field.personalEmail}")
    private String email;

    // getter and setter
}

Now, let us define @FieldNotEmpty with two attributes:

@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = {FieldNotEmptyValidator.class})
public @interface FieldNotEmpty {

    String message() default "{validation.notEmpty}";

    String field() default "Field";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

@FieldNotEmpty operates as a constraint and uses FieldNotEmptyValidator as the validator implementation:

public class FieldNotEmptyValidator implements ConstraintValidator<FieldNotEmpty, Object> {

    private String message;
    private String field;

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        return (value != null && !value.toString().trim().isEmpty());
    }

}

The isValid(…) method performs the validation logic and simply determines whether the value is not empty. If the value is empty, it retrieves localized messages for the attribute field and message corresponding to the current locale from the request context. The attribute message is interpolated to form a complete message.

Upon execution, we observe the following result:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "{field.personalEmail} cannot be empty"
        }
    ]
}

The message attribute and its corresponding placeholder are successfully retrieved. However, we’re expecting {field.personalEmail} to be replaced by the actual value.

8.5. Custom MessageInterpolator

The problem lies in the default MessageInterpolator. It translates the placeholder for one time only. We need to apply the interpolation to the message again to replace the subsequent placeholder with the localized message. In this case, we have to define a custom message interpolator to replace the default one:

public class RecursiveLocaleContextMessageInterpolator extends AbstractMessageInterpolator {

    private static final Pattern PATTERN_PLACEHOLDER = Pattern.compile("\\{([^}]+)\\}");

    private final MessageInterpolator interpolator;

    public RecursiveLocaleContextMessageInterpolator(ResourceBundleMessageInterpolator interpolator) {
        this.interpolator = interpolator;
    }

    @Override
    public String interpolate(MessageInterpolator.Context context, Locale locale, String message) {
        int level = 0;
        while (containsPlaceholder(message) && (level++ < 2)) {
            message = this.interpolator.interpolate(message, context, locale);
        }
        return message;
    }

    private boolean containsPlaceholder(String code) {
        Matcher matcher = PATTERN_PLACEHOLDER.matcher(code);
        return matcher.find();
    }

}

RecursiveLocaleContextMessageInterpolator is simply a decorator. It reapplies interpolation with the wrapped MessageInterpolator when it detects the message contains any curly bracket placeholder.

We’ve completed the implementation, and it’s time for us to configure Spring Boot to incorporate it. We’ll add two provider methods to MessageConfig:

@Bean
public MessageInterpolator getMessageInterpolator(MessageSource messageSource) {
    MessageSourceResourceBundleLocator resourceBundleLocator = new MessageSourceResourceBundleLocator(messageSource);
    ResourceBundleMessageInterpolator messageInterpolator = new ResourceBundleMessageInterpolator(resourceBundleLocator);
    return new RecursiveLocaleContextMessageInterpolator(messageInterpolator);
}

@Bean
public LocalValidatorFactoryBean getValidator(MessageInterpolator messageInterpolator) {
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setMessageInterpolator(messageInterpolator);
    return bean;
}

The getMessageInterpolator(…) method returns our own implementation. This implementation wraps ResourceBundleMessageInterpolator, which is the default MessageInterpolator in Spring Boot. The getValidator() is for registering the validator to use our customized MessageInterpolator within our web service.

Now, we’re all set, and let’s test it once more. We’ll have the following complete interpolated message with the placeholder replaced by the localized message as well:

{
    "fieldErrors": [
        {
            "field": "email",
            "message": "Personal Email cannot be empty"
        }
    ]
}

9. Conclusion

In this article, we dived into the process of delivering localized messages within multilingual applications.

We began with an outline for all the key steps for a complete implementation, starting from using property files as message repositories and encoding them in UTF-8. Spring Boot integration simplifies message retrieval based on client locale preferences. Java Bean Validation, along with custom annotations and message interpolation, allows for tailored, language-specific error responses.

By incorporating these techniques together, we’re able to provide localized validation responses in REST web services.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – LS – NPI (cat=REST)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Microsoft – NPI (cat=Spring)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

eBook Jackson – NPI EA – 3 (cat = Jackson)