Skip to content
Podbrushkin edited this page Jan 26, 2023 · 15 revisions

Welcome to the SpringMvc-JavaConfig wiki!

Spring MVC

  1. Create .\pom.xml:
<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>
  1. Create .\src\main\java\myapp\config\WebInit.java:
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("/");
    }
}
  1. Create .\src\main\java\myapp\config\WebConfig.java:
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 {
}
  1. Create .\src\main\java\myapp\controller\MainController.java:
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 не работает 😕";
	}
}
  1. mvn clean jetty:run and curl http://localhost:8080/raw:
hello there! UTF-8 ?? ???????? ?

Sources

JSP

  1. Add this bean to WebConfig.java:
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;
}
  1. Add this method to MainController.java:
@GetMapping("/jsp")
public String greetJsp(ModelMap model) {
	model.put("msg", "jsp сообщение 🪂");
	return "greeting.jsp";
}
  1. Create .\src\main\webapp\WEB-INF\jsp\greeting.jsp:
<%@page pageEncoding="UTF-8" %>
<html>
	<head>
		<title>Welcome</title>
	</head>
	<body>
		<p>🚀 This is a complete ${msg}.</p>
	</body>
</html>
  1. Visit http://localhost:8080/jsp.

Sources

Thymeleaf

  1. Add this dependency to pom.xml:
<dependency>
	<groupId>org.thymeleaf</groupId>
	<artifactId>thymeleaf-spring6</artifactId>
	<version>3.1.1.RELEASE</version>
</dependency>
  1. Add this beans to WebConfig.java:
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;
}
  1. Add this method to MainController.java:
@GetMapping("/thy")
public String greetThy(ModelMap model) {
	model.put("msg", "прыгает через ленивую собаку🐶");
	return "hello.html";
}
  1. Create .\src\main\webapp\WEB-INF\thy\hello.html:
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<title>Welcome</title>
	</head>
	<body>
		🦊The quick brown fox <label th:text="${msg}"></label>
	</body>
</html>
  1. Visit http://localhost:8080/thy.

Sources

CSS

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

Now background of these pages will turn to grey.

Sources

Spring Security

  1. Add these dependencies to your pom.xml:
<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>
  1. Create .\src\main\java\myapp\security\SecurityInitialization.java:
package myapp.security;

import org.springframework.security.web.context.*;

public class SecurityInitialization extends AbstractSecurityWebApplicationInitializer {
	public SecurityInitialization() { }
}
  1. Create .\src\main\java\myapp\security\SecurityConfiguration.java:
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

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

Spring Security + JSP

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

Logging

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:
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
	<version>2.19.0</version>
</dependency>
  1. Create .\src\main\resources\log4j2.xml:
<?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>
  1. 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:
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-slf4j-impl</artifactId>
	<version>2.19.0</version>
</dependency>
  1. In any of your classes, use slf4j interface:
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

  1. To WebConfig.java add these beans and an interceptor:
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);
}
  1. Create src\main\resources\messages_en.properties:
welcome=You are welcome!
  1. Create src\main\resources\messages_ru.properties:
welcome=Добро пожаловать!
  1. In your Thymeleaf template *.html/<html>/<body> add this line:
<h2 th:text="#{welcome}">Welcome</h2>
  1. In your greeting.jsp add these lines:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<...>
<h2><spring:message code="welcome" /></h2>
  1. Visit these pages and change language of message by appending ?lang=ru or ?lang=en parameters to URL.

Sources

Aspects

  1. Add this dependency to your pom.xml:
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
	<version>${spring.version}</version>
</dependency>
  1. To WebConfig.java add this annotation:
import org.springframework.context.annotation.EnableAspectJAutoProxy;
// ...
@EnableAspectJAutoProxy
public class WebConfig implements WebMvcConfigurer {
  1. Create .\src\main\java\myapp\aop\LoggingAspect.java:
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

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:
<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>
  1. Add this bean to WebConfig.java:
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();
}
  1. Create .\src\main\resources\schema.sql:
create table if not exists Message (
	id int auto_increment unique not null,
	content varchar(255) not null
);
  1. Create .\src\main\resources\data.sql:
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

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:
package myapp.model;
public record Message(Long id, String content) {}
  1. Create .\src\main\java\myapp\service\MessageService.java:
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);
	}}
  1. Create src\main\java\myapp\repository\MessageJdbcDaoImpl.java:
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());
	}
}
  1. In your MainController.java add this imports, class variable and a method:
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";
}
  1. 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

  1. Add this dependency to pom.xml:
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.14.1</version>
</dependency>
  1. Add this method to WebConfig.java:
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);
}
  1. Create .\src\main\java\myapp\rest\MainRest.java:
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);
	}
}
  1. In SecurityConfiguration#securityFilterChain() add csrf().disable() statement like that:
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

At this point you should have a working dataSource bean.

  1. Add these dependencies to pom.xml:
<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>
  1. Add these beans and class-level annotation to WebConfig.java:
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