Spring: Java Configuration

Spring is most popular framework for building web applications in Java ecosystem. Spring Framework can be configured either in XML, or with Java code. This page shows how to configure various Spring modules with Java. We will start with a simple application and in every section we will be adding one more Spring module to it.

If you are interested in how to do all the same things with XML configuration, this page can help you: Spring_MVC:_Tutorial

Spring MVC edit

  1. Create .\pom.xml:
  2. <project>
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>mygroup</groupId>
    	<artifactId>SpringMvcJavaConfig</artifactId>
    	<version>0.1</version>
    	<packaging>war</packaging>
    	
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<maven.compiler.source>18</maven.compiler.source>
    		<maven.compiler.target>18</maven.compiler.target>
    
    		<spring.version>6.0.3</spring.version>
    		<jetty-maven-plugin.version>11.0.12</jetty-maven-plugin.version>
    	</properties>
    	
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>jakarta.servlet</groupId>
    			<artifactId>jakarta.servlet-api</artifactId>
    			<version>6.0.0</version>
    			<scope>provided</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.eclipse.jetty</groupId>
    					<artifactId>jetty-maven-plugin</artifactId>
    					<version>${jetty-maven-plugin.version}</version>
    				</plugin>
    			</plugins>
    		</pluginManagement>
    	</build>
    	
    </project>
    
  3. Create .\src\main\java\myapp\config\WebInit.java:
  4. package myapp.config;
    
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
    import jakarta.servlet.ServletRegistration;
    import jakarta.servlet.ServletContext;
    
    public class WebInit implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext container) {
            var context = new AnnotationConfigWebApplicationContext();
            context.setConfigLocation("myapp.config");
    
            container.addListener(new ContextLoaderListener(context));
    
            ServletRegistration.Dynamic dispatcher = container
              .addServlet("dispatcher", new DispatcherServlet(context));
            
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/");
        }
    }
    
  5. Create .\src\main\java\myapp\config\WebConfig.java:
  6. package myapp.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"myapp"})
    public class WebConfig implements WebMvcConfigurer {
    }
    
  7. Create .\src\main\java\myapp\controller\MainController.java:
  8. package myapp.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class MainController {
    	@GetMapping("/raw")
    	@ResponseBody
    	public String greetRaw() {
    		return "hello there! UTF-8 не работает 😕";
    	}
    }
    
  9. mvn clean jetty:run and curl http://localhost:8080/raw:
  10. hello there! UTF-8 ?? ???????? ?


Sources:


JSP edit

  1. Add this bean to WebConfig.java:
  2. import org.springframework.web.servlet.view.InternalResourceViewResolver;
    import org.springframework.context.annotation.Bean;
    // ...
    @Bean
    InternalResourceViewResolver internalResourceViewResolver() {
    	var resolver = new InternalResourceViewResolver("/WEB-INF/jsp/", "");
    	resolver.setViewNames("*.jsp");
    	return resolver;
    }
    
  3. Add this method to MainController.java:
  4. @GetMapping("/jsp")
    public String greetJsp(ModelMap model) {
    	model.put("msg", "jsp сообщение 🪂");
    	return "greeting.jsp";
    }
    
  5. Create .\src\main\webapp\WEB-INF\jsp\greeting.jsp:
  6. <%@page pageEncoding="UTF-8" %>
    <html>
    	<head>
    		<title>Welcome</title>
    	</head>
    	<body>
    		<p>🚀 This is a complete ${msg}.</p>
    	</body>
    </html>
    
  7. Visit http://localhost:8080/jsp.

Sources:



Thymeleaf edit

  1. Add this dependency to pom.xml:
  2. <dependency>
    	<groupId>org.thymeleaf</groupId>
    	<artifactId>thymeleaf-spring6</artifactId>
    	<version>3.1.1.RELEASE</version>
    </dependency>
    
  3. Add this beans to WebConfig.java:
  4. import org.thymeleaf.spring6.SpringTemplateEngine;
    import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
    import org.thymeleaf.spring6.view.ThymeleafViewResolver;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.thymeleaf.templatemode.TemplateMode;
    // ...
    @Autowired
    private ApplicationContext applicationContext;
    @Bean
    public SpringResourceTemplateResolver templateResolver(){
    	var templateResolver = new SpringResourceTemplateResolver();
    	templateResolver.setApplicationContext(this.applicationContext);
    	templateResolver.setPrefix("/WEB-INF/thy/");
    	templateResolver.setSuffix(".html");
    	templateResolver.setCacheable(false);
    	return templateResolver;
    }
    
    @Bean
    public SpringTemplateEngine templateEngine(){
    	var templateEngine = new SpringTemplateEngine();
    	templateEngine.setTemplateResolver(templateResolver());
    	templateEngine.setEnableSpringELCompiler(true);
    	return templateEngine;
    }
    @Bean
    public ThymeleafViewResolver viewResolver(){
    	var viewResolver = new ThymeleafViewResolver();
    	viewResolver.setTemplateEngine(templateEngine());
    	viewResolver.setCharacterEncoding("UTF-8");
    	// viewResolver.setOrder(1);
    	// viewResolver.setViewNames(new String[] {".html", ".xhtml"});
    	return viewResolver;
    }
    
  5. Add this method to MainController.java:
  6. @GetMapping("/thy")
    public String greetThy(ModelMap model) {
    	model.put("msg", "прыгает через ленивую собаку🐶");
    	return "hello.html";
    }
    
  7. Create .\src\main\webapp\WEB-INF\thy\hello.html:
  8. <html xmlns:th="http://www.thymeleaf.org">
    	<head>
    		<title>Welcome</title>
    	</head>
    	<body>
    		🦊The quick brown fox <label th:text="${msg}"></label>
    	</body>
    </html>
    
  9. Visit http://localhost:8080/thy.

Sources:


CSS edit

  1. Add this method to WebConfig.java:
  2. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    \\ ...
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
            .addResourceLocations("/resources/", "classpath:/static/");
    }
    
  3. Create src\main\webapp\resources\css\styles.css:
  4. body {
    	background-color: LightGrey;
    }
    
  5. To your greeting.jsp/<html>/<head> page add this line:
  6. <link rel="stylesheet" href="/resources/css/styles.css" />
    
  7. To your hello.html/<html>/<head> add this line:
  8. <link rel="stylesheet" th:href="@{/resources/css/styles.css}" />
    

Now background of these pages will turn to grey.

Sources:


Spring Security edit

  1. Add these dependencies to your pom.xml:
  2. <spring-security.version>6.0.1</spring-security.version>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-web</artifactId>
    	<version>${spring-security.version}</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-config</artifactId>
    	<version>${spring-security.version}</version>
    </dependency>
    
  3. Create .\src\main\java\myapp\security\SecurityInitialization.java:
  4. package myapp.security;
    
    import org.springframework.security.web.context.*;
    
    public class SecurityInitialization extends AbstractSecurityWebApplicationInitializer {
    	public SecurityInitialization() { }
    }
    
  5. Create .\src\main\java\myapp\security\SecurityConfiguration.java:
  6. package myapp.security;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    import org.springframework.security.web.SecurityFilterChain;
    import static org.springframework.security.config.Customizer.withDefaults;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration {
    
    	@Bean
    	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    		http
    			.authorizeHttpRequests((authorize) -> authorize
    					.anyRequest().authenticated()
    					// .requestMatchers("/jsp/**").hasRole("USER")
    					// .anyRequest().permitAll()
    			)
    			.httpBasic(withDefaults())
    			.formLogin(withDefaults());
    		return http.build();
    	}
    
    	@Bean
    	public UserDetailsService userDetailsService() {
    		UserDetails user = User.withDefaultPasswordEncoder()
    				.username("user")
    				.password("1234")
    				.roles("USER")
    				.build();
    		return new InMemoryUserDetailsManager(user);
    	}
    }
    
  • To register multiple users, just create new UserDetails and pass it to the constructor as well, it accepts varargs.

Now you will have to log in to view any page of your web application.


Sources:



Spring Security + Thymeleaf edit

  1. To your pom.xml add this dependency:
  2. <dependency>
    	<groupId>org.thymeleaf.extras</groupId>
    	<artifactId>thymeleaf-extras-springsecurity6</artifactId>
    	<version>3.1.0.RELEASE</version>
    </dependency>
    
  3. In WebConfig#templateEngine() register new dialect:
  4. import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
    // ...
    templateEngine.addDialect(new SpringSecurityDialect());
    
  5. To your hello.html/<html>/<body> add this line:
  6. <p>Your name is <label th:text="${#authentication.name}" />, if I'm not mistaken. 🔑</p>
    
  7. Visit http://localhost:8080/thy, if you're logged in, your username will be displayed.

Sources:


Spring Security + JSP edit

  1. Add this dependency to your pom.xml:
  2. <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-taglibs</artifactId>
    	<version>${spring-security.version}</version>
    </dependency>
    
  3. Add this line above <html> tag in greeting.jsp:
  4. <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
    
  5. Add this line in greeting.jsp/<html>/<body>:
  6. <p>Here is your username: <sec:authentication property="name" />.</p>
    
  7. Visit http://localhost:8080/jsp, if you're logged in your username will be displayed.

Sources:


Logging edit

In any of your classes you can use this built-in logger right-away:

import org.apache.commons.logging.*;
// ...
private final Log log = LogFactory.getLog(getClass());

But if you'll want to use log4j2, you'll need to add it's library to dependencies and log4j2.xml to classpath:

  1. Add this dependency to your pom.xml:
  2. <dependency>
    	<groupId>org.apache.logging.log4j</groupId>
    	<artifactId>log4j-core</artifactId>
    	<version>2.19.0</version>
    </dependency>
    
  3. Create .\src\main\resources\log4j2.xml:
  4. <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
    		<Console name="LogToConsoleFull" target="SYSTEM_OUT">
                <PatternLayout pattern="%highlight{[%level] %logger.%method()}{trace=bright cyan} %msg%n"
    				disableAnsi="false" charset="866"/>
            </Console>
    		<Console name="LogToConsole" target="SYSTEM_OUT">
                <PatternLayout pattern="%highlight{[%-20.-40maxLen{%level] %logger{1}.%method()}{}}{trace=bright cyan} %msg%n"
    				disableAnsi="false" charset="866"/>
            </Console>
    		<Console name="LogToConsoleBrief" target="SYSTEM_OUT">
                <PatternLayout pattern="%highlight{[%level] %logger{1.}}{trace=bright cyan} %msg%n"
    				disableAnsi="false" charset="866"/>
            </Console>
    		<Console name="LogToConsoleTiny" target="SYSTEM_OUT">
                <PatternLayout pattern="%highlight{[%level]}{trace=bright cyan} %msg%n"
    				disableAnsi="false" charset="866"/>
            </Console>
        </Appenders>
        <Loggers>
            <Logger name="myapp" level="trace" additivity="false">
                <AppenderRef ref="LogToConsoleTiny"/>
            </Logger>
            <Root level="info">
                <AppenderRef ref="LogToConsoleTiny"/>
            </Root>
        </Loggers>
    </Configuration>
    
  5. In any of your classes, use org.apache.commons.* package to write logs as with the built-in logger, Spring will now use log4j2 under the hood.

But if you'll want to use log4j2 through slf4j interface, here's what you'll need to do:

  1. Remove log4j-core dependency if you have it;
  2. Add this dependency higher than Thymeleaf dependency:
  3. <dependency>
    	<groupId>org.apache.logging.log4j</groupId>
    	<artifactId>log4j-slf4j-impl</artifactId>
    	<version>2.19.0</version>
    </dependency>
    
  4. In any of your classes, use slf4j interface:
  5. import org.slf4j.*;
    // ...
    private final Logger log = LoggerFactory.getLogger(getClass());
    

Now you also can manage Thymeleaf logs as well, since it uses slf4j internally.


Sources:


Internationalization edit

  1. To WebConfig.java add these beans and an interceptor:
  2. import org.springframework.context.support.ResourceBundleMessageSource;
    import org.springframework.web.servlet.i18n.SessionLocaleResolver;
    import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import java.util.Locale;
    // ...
    @Bean
    public ResourceBundleMessageSource messageSource() {
    	var messageSource = new ResourceBundleMessageSource();
    	messageSource.setDefaultEncoding("UTF-8");
    	messageSource.setBasename("messages");
    	return messageSource;
    }
    @Bean
    public SessionLocaleResolver localeResolver() {
    	var localeResolver = new SessionLocaleResolver();
    	localeResolver.setDefaultLocale(Locale.ENGLISH);
    	return localeResolver;
    }
    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
    	var localeChangeInterceptor = new LocaleChangeInterceptor();
    	localeChangeInterceptor.setParamName("lang");
    	registry.addInterceptor(localeChangeInterceptor);
    }
    
  3. Create src\main\resources\messages_en.properties:
  4. welcome=You are welcome!
  5. Create src\main\resources\messages_ru.properties:
  6. welcome=Добро пожаловать!
  7. In your Thymeleaf template *.html/<html>/<body> add this line:
  8. <h2 th:text="#{welcome}">Welcome</h2>
    
  9. In your greeting.jsp add these lines:
  10. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <...>
    <h2><spring:message code="welcome" /></h2>
    
  11. Visit these pages and change language of message by appending ?lang=ru or ?lang=en parameters to URL.

Sources:

Aspects edit

  1. Add this dependency to your pom.xml:
  2. <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aspects</artifactId>
    	<version>${spring.version}</version>
    </dependency>
    
  3. To WebConfig.java add this annotation:
  4. import org.springframework.context.annotation.EnableAspectJAutoProxy;
    // ...
    @EnableAspectJAutoProxy
    public class WebConfig implements WebMvcConfigurer {
    
  5. Create .\src\main\java\myapp\aop\LoggingAspect.java:
  6. package myapp.aop;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.ProceedingJoinPoint; 
    import org.springframework.stereotype.Component;
    import org.slf4j.*;
    
    @Aspect
    @Component
    public class LoggingAspect {
    
    	private final Logger log = LoggerFactory.getLogger(getClass());
    
    	@Around("execution(* *.controller.*.*(..))")
    	public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
    		log.trace("Before {} call", joinPoint.getSignature());
    		var obj = joinPoint.proceed();
    		log.trace("After {} call", joinPoint.getSignature());
    		return obj;
    	}
    }
    
  • Your logging library may differ, consult Logging section on this page;

Now every invocation of every method from *.controller package will be surrounded by corresponding log messages.

DataSource: H2 Embedded Database edit

Regardless of what technology you will choose for your application to interact with database, you will need a datasource bean. For convenience, this project uses embedded H2 database, and this section will show you how to enable it and get it's datasource bean.

  1. Add these dependencies to your pom.xml:
  2. <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-jdbc</artifactId>
    	<version>${spring.version}</version>
    </dependency>
    <dependency>
    	<groupId>com.h2database</groupId>
    	<artifactId>h2</artifactId>
    	<version>2.1.214</version>
    </dependency>
    
  3. Add this bean to WebConfig.java:
  4. import javax.sql.DataSource;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
    // ...
    @Bean
    public DataSource dataSource() {
    	return new EmbeddedDatabaseBuilder()
    		.setType(EmbeddedDatabaseType.H2)
    		.addScript("classpath:schema.sql")
    		.addScript("classpath:data.sql")
    		.build();
    }
    
  5. Create .\src\main\resources\schema.sql:
  6. create table if not exists Message (
    	id int auto_increment unique not null,
    	content varchar(255) not null
    );
    
  7. Create .\src\main\resources\data.sql:
  8. INSERT INTO message (content) VALUES 
    	('Prune juice 🍇'),
    	('Буря мглою небо кроет...')
    ;
    

Now if you will start your application you will see a log:

Starting embedded database: url='jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'

Sources:


JdbcTemplate edit

JdbcTemplate doesn't need any explicit configuration. You'll need only spring-jdbc dependency and datasource bean, which you've already got in previous section. This is an example of how to use JdbcTemplate:

  1. Create .\src\main\java\myapp\model\Message.java:
  2. package myapp.model;
    public record Message(Long id, String content) {}
    
  3. Create .\src\main\java\myapp\service\MessageService.java:
  4. package myapp.service;
    
    import myapp.model.Message;
    import myapp.repository.MessageJdbcDaoImpl;
    import org.springframework.stereotype.Component;
    import org.springframework.beans.factory.annotation.Autowired;
    import java.util.List;
    
    @Component
    public class MessageService {
    	
    	@Autowired
    	private MessageJdbcDaoImpl messageJdbcDao;
    	
    	public List<Message> findAll() {
    		return messageJdbcDao.findAll();
    	}
    	public void save(Message message) {
    		messageJdbcDao.save(message);
    	}}
    
  5. Create src\main\java\myapp\repository\MessageJdbcDaoImpl.java:
  6. package myapp.repository;
    
    import org.springframework.stereotype.Repository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowMapper;
    import myapp.model.Message;
    import javax.sql.DataSource;
    import java.util.List;
    
    @Repository
    public class MessageJdbcDaoImpl {
    	
    	JdbcTemplate jdbcTemplate;
    	
    	private final RowMapper<Message> messageRowMapper = (resultSet, rowNum) -> {
    		return 
    			new Message(resultSet.getLong("id"), resultSet.getString("content"));
    	};
    	
    	@Autowired
    	public MessageJdbcDaoImpl(DataSource dataSource) {
    		jdbcTemplate = new JdbcTemplate(dataSource);
    	}
    
    	public List<Message> findAll() {
    		String query = "select * from Message";
    		
    		List<Message> result = 
    			jdbcTemplate.query(query, messageRowMapper);
    		
    		return result;
    	}
    	public void save(Message message) {
    		var query = "INSERT INTO message (content) VALUES (?)";
    		jdbcTemplate.update(query, message.content());
    	}
    }
    
  7. In your MainController.java add this imports, class variable and a method:
  8. import myapp.service.MessageService;
    import org.springframework.beans.factory.annotation.Autowired;
    import myapp.model.*;
    import org.springframework.web.bind.annotation.RequestParam;
    // ...
    @Autowired
    private MessageService messageService;
    // ...
    @GetMapping("/messages")
    public String messages(ModelMap model) {
    	model.put("msg", messageService.findAll());
    	return "hello.html";
    }
    @GetMapping("/messages/new")
    public String messageSave(@RequestParam(required=true) String content) {
    	messageService.save(new Message(null, content));
    	return "hello.html";
    }
    
  9. Visit https://localhost:8080/messages and you will see contents of your Message table. Create new message by sending it's content as request parameter: https://localhost:8080/messages/new?content=ThisShouldWork

REST edit

  1. Add this dependency to pom.xml:
  2. <dependency>
    	<groupId>com.fasterxml.jackson.core</groupId>
    	<artifactId>jackson-databind</artifactId>
    	<version>2.14.1</version>
    </dependency>
    
  3. Add this method to WebConfig.java:
  4. import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import java.util.List;
    import java.nio.charset.Charset;
    // ...
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    	var messageConverter = new MappingJackson2HttpMessageConverter();
    	// messageConverter.setDefaultCharset(Charset.forName("UTF-8")); //doesn't help anyway
    	messageConverters.add(messageConverter);
    }
    
  5. Create .\src\main\java\myapp\rest\MainRest.java:
  6. package myapp.rest;
    
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.GetMapping;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.List;
    import myapp.model.*;
    import myapp.service.MessageService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    @RestController
    @RequestMapping("/rest")
    public class MainRest {
    	
    	@Autowired
    	private MessageService messageService;
    
    	@GetMapping("/messages")
    	List<Message> messages() {
    		return messageService.findAll();
    	}
    	@PostMapping(value="/messages")	//, consumes="application/json;charset=UTF-8"
    	void saveMessage(@RequestBody Message message) {
    		messageService.save(message);
    	}
    }
    
  7. In SecurityConfiguration#securityFilterChain() add csrf().disable() statement like that:
  8. http
    	.authorizeHttpRequests((authorize) -> authorize
    			// .anyRequest().authenticated()
    			// .requestMatchers("/jsp/**").hasRole("USER")
    			.anyRequest().permitAll()
    	)
    	.httpBasic(withDefaults())
    	.formLogin(withDefaults())
    	.csrf().disable();
    return http.build();
    

Now http://localhost:8080/rest/messages will show all your messages in json format, and you can create new messages by sending them to the same address through curl or PowerShell:

curl -X POST --data '{"content":"in curl send latin text only"}' http://localhost:8080/rest/messages --header 'Content-Type: Application/Json'
Invoke-WebRequest -Uri http://localhost:8080/rest/messages -Method POST -ContentType 'application/json;charset=utf-8' -Body '{"content":"In pwsh you can use all UTF8 characters 😀"}'

Hibernate Configuration edit

At this point you should have a working dataSource bean.

  1. Add these dependencies to pom.xml:
  2. <dependency>
    	<groupId>org.hibernate.orm</groupId>
    	<artifactId>hibernate-core</artifactId>
    	<version>6.2.0.CR1</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-orm</artifactId>
    	<version>${spring.version}</version>
    </dependency>
    
  3. Add these beans and class-level annotation to WebConfig.java:
  4. import org.springframework.transaction.annotation.EnableTransactionManagement;
    import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
    import org.springframework.orm.hibernate5.HibernateTransactionManager;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.hibernate.SessionFactory;
    // ...
    @EnableTransactionManagement
    // ...
    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
    	var sessionFactory = new LocalSessionFactoryBean();
    	sessionFactory.setDataSource(dataSource);
    	sessionFactory.setPackagesToScan("myapp.model");
    	// sessionFactory.setHibernateProperties(hibernateProperties());
    	return sessionFactory;
    }
    @Bean
    public PlatformTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
    	var transactionManager = new HibernateTransactionManager();
    	transactionManager.setSessionFactory(sessionFactory);
    	return transactionManager;
    }
    

Now you can create Entity classes with annotations from jakarta.persistence package and use SessionFactory or EntityManager in your dao layer:

import jakarta.persistence.PersistenceContext;
import jakarta.persistence.EntityManager;
@PersistenceContext
EntityManager em;
// or...
import org.hibernate.SessionFactory;
@Autowired
SessionFactory;

Sources: