Merge branch 'eugenp:master' into master

This commit is contained in:
Wynn Teo 2024-02-12 19:09:23 +08:00 committed by GitHub
commit 0b967edb88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 224 additions and 229 deletions

View File

@ -18,6 +18,12 @@
<artifactId>transactions-jdbc</artifactId> <artifactId>transactions-jdbc</artifactId>
<version>${atomikos-version}</version> <version>${atomikos-version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>${atomikos-version}</version>
<classifier>jakarta</classifier>
</dependency>
<dependency> <dependency>
<groupId>com.atomikos</groupId> <groupId>com.atomikos</groupId>
<artifactId>transactions-jms</artifactId> <artifactId>transactions-jms</artifactId>
@ -90,10 +96,10 @@
</dependencies> </dependencies>
<properties> <properties>
<atomikos-version>5.0.6</atomikos-version> <atomikos-version>6.0.0</atomikos-version>
<spring-version>5.1.6.RELEASE</spring-version> <spring-version>6.1.2</spring-version>
<hibernate.version>5.4.3.Final</hibernate.version> <hibernate.version>6.4.2.Final</hibernate.version>
<spring-data-jpa.version>1.11.23.RELEASE</spring-data-jpa.version> <spring-data-jpa.version>3.2.2</spring-data-jpa.version>
<activemq-core.version>5.7.0</activemq-core.version> <activemq-core.version>5.7.0</activemq-core.version>
<derby.version>10.8.1.2</derby.version> <derby.version>10.8.1.2</derby.version>
<jta.version>1.1</jta.version> <jta.version>1.1</jta.version>

View File

@ -1,17 +1,14 @@
package com.baeldung.atomikos.spring.config; package com.baeldung.atomikos.spring.config;
import java.util.Properties;
import javax.transaction.SystemException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
import com.atomikos.icatch.jta.UserTransactionManager; import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jdbc.AtomikosDataSourceBean; import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.baeldung.atomikos.spring.Application; import com.baeldung.atomikos.spring.Application;
import jakarta.transaction.SystemException;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
@Configuration @Configuration
@EnableTransactionManagement @EnableTransactionManagement
@ -46,7 +43,7 @@ public class Config {
} }
@Bean(initMethod = "init", destroyMethod = "close") @Bean(initMethod = "init", destroyMethod = "close")
public UserTransactionManager userTransactionManager() throws SystemException { public UserTransactionManager userTransactionManager() throws jakarta.transaction.SystemException {
UserTransactionManager userTransactionManager = new UserTransactionManager(); UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setTransactionTimeout(300); userTransactionManager.setTransactionTimeout(300);
userTransactionManager.setForceShutdown(true); userTransactionManager.setForceShutdown(true);

View File

@ -29,13 +29,13 @@ public class Application {
String orderId = UUID.randomUUID() String orderId = UUID.randomUUID()
.toString(); .toString();
Inventory inventory = inventoryRepository.findOne(productId); Inventory inventory = inventoryRepository.getReferenceById(productId);
inventory.setBalance(inventory.getBalance() - amount); inventory.setBalance(inventory.getBalance() - amount);
inventoryRepository.save(inventory); inventoryRepository.save(inventory);
Order order = new Order(); Order order = new Order();
order.setOrderId(orderId); order.setOrderId(orderId);
order.setProductId(productId); order.setProductId(productId);
order.setAmount(new Long(amount)); order.setAmount( Long.valueOf(amount));
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator(); Validator validator = factory.getValidator();
Set<ConstraintViolation<Order>> violations = validator.validate(order); Set<ConstraintViolation<Order>> violations = validator.validate(order);

View File

@ -1,6 +1,6 @@
package com.baeldung.atomikos.spring.jpa.config; package com.baeldung.atomikos.spring.jpa.config;
import javax.transaction.SystemException; import jakarta.transaction.SystemException;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,8 +1,8 @@
package com.baeldung.atomikos.spring.jpa.inventory; package com.baeldung.atomikos.spring.jpa.inventory;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Table(name = "INVENTORY") @Table(name = "INVENTORY")

View File

@ -2,7 +2,7 @@ package com.baeldung.atomikos.spring.jpa.inventory;
import java.util.Properties; import java.util.Properties;
import javax.persistence.EntityManagerFactory; import jakarta.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,8 +1,8 @@
package com.baeldung.atomikos.spring.jpa.order; package com.baeldung.atomikos.spring.jpa.order;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.Table; import jakarta.persistence.Table;
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Max;
@Entity @Entity

View File

@ -2,7 +2,7 @@ package com.baeldung.atomikos.spring.jpa.order;
import java.util.Properties; import java.util.Properties;
import javax.persistence.EntityManagerFactory; import jakarta.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -72,7 +72,7 @@ public class ApplicationUnitTest {
private static long getBalance(InventoryRepository inventoryRepository, String productId) throws Exception { private static long getBalance(InventoryRepository inventoryRepository, String productId) throws Exception {
return inventoryRepository.findOne(productId) return inventoryRepository.getReferenceById(productId)
.getBalance(); .getBalance();
} }

View File

@ -15,7 +15,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version> <version>${hibernate.version}</version>
</dependency> </dependency>
@ -25,7 +25,7 @@
<version>${h2.version}</version> <version>${h2.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-spatial</artifactId> <artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version> <version>${hibernate.version}</version>
</dependency> </dependency>
@ -45,7 +45,7 @@
<version>${mariaDB4j.version}</version> <version>${mariaDB4j.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-testing</artifactId> <artifactId>hibernate-testing</artifactId>
<version>${hibernate.version}</version> <version>${hibernate.version}</version>
</dependency> </dependency>
@ -82,6 +82,7 @@
<mysql.version>8.2.0</mysql.version> <mysql.version>8.2.0</mysql.version>
<mariaDB4j.version>2.6.0</mariaDB4j.version> <mariaDB4j.version>2.6.0</mariaDB4j.version>
<geodb.version>0.9</geodb.version> <geodb.version>0.9</geodb.version>
<hibernate.version>6.4.2.Final</hibernate.version>
</properties> </properties>
</project> </project>

View File

@ -9,12 +9,16 @@ import java.util.List;
import jakarta.persistence.OptimisticLockException; import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException; import jakarta.persistence.PersistenceException;
import org.h2.jdbc.JdbcSQLDataException;
import org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException;
import org.h2.jdbc.JdbcSQLSyntaxErrorException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NonUniqueObjectException; import org.hibernate.NonUniqueObjectException;
import org.hibernate.PropertyValueException; import org.hibernate.PropertyValueException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException; import org.hibernate.StaleStateException;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
@ -132,8 +136,8 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() { public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() {
thrown.expectCause(isA(SQLGrammarException.class)); thrown.expectCause(isA(JdbcSQLSyntaxErrorException.class));
thrown.expectMessage("could not prepare statement"); thrown.expectMessage("Table \"PRODUCT\" not found (this database is empty); SQL statement");
Configuration cfg = getConfiguration(); Configuration cfg = getConfiguration();
cfg.addAnnotatedClass(Product.class); cfg.addAnnotatedClass(Product.class);
@ -161,8 +165,8 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() { public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() {
thrown.expectCause(isA(SQLGrammarException.class)); thrown.expectCause(isA(JdbcSQLSyntaxErrorException.class));
thrown.expectMessage("could not prepare statement"); thrown.expectMessage("Table \"NON_EXISTING_TABLE\" not found");
Session session = sessionFactory.openSession(); Session session = sessionFactory.openSession();
NativeQuery<Product> query = session.createNativeQuery("select * from NON_EXISTING_TABLE", Product.class); NativeQuery<Product> query = session.createNativeQuery("select * from NON_EXISTING_TABLE", Product.class);
@ -171,7 +175,7 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void whenDuplicateIdSaved_thenConstraintViolationException() { public void whenDuplicateIdSaved_thenConstraintViolationException() {
thrown.expectCause(isA(ConstraintViolationException.class)); thrown.expectCause(isA(JdbcSQLIntegrityConstraintViolationException.class));
thrown.expectMessage("could not execute statement"); thrown.expectMessage("could not execute statement");
Session session = null; Session session = null;
@ -224,7 +228,7 @@ public class HibernateExceptionUnitTest {
public void givenEntityWithoutId_whenCallingSave_thenThrowIdentifierGenerationException() { public void givenEntityWithoutId_whenCallingSave_thenThrowIdentifierGenerationException() {
thrown.expect(isA(IdentifierGenerationException.class)); thrown.expect(isA(IdentifierGenerationException.class));
thrown.expectMessage("ids for this class must be manually assigned before calling save(): com.baeldung.hibernate.exception.Product"); thrown.expectMessage("Identifier of entity 'com.baeldung.hibernate.exception.ProductEntity' must be manually assigned before calling 'persist()");
Session session = null; Session session = null;
Transaction transaction = null; Transaction transaction = null;
@ -249,8 +253,8 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() { public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() {
thrown.expectCause(isA(DataException.class)); thrown.expectCause(isA(JdbcSQLDataException.class));
thrown.expectMessage("could not prepare statement"); thrown.expectMessage("Data conversion error converting \"wrongTypeId\"");
Session session = sessionFactory.openSession(); Session session = sessionFactory.openSession();
NativeQuery<Product> query = session.createNativeQuery("select * from PRODUCT where id='wrongTypeId'", Product.class); NativeQuery<Product> query = session.createNativeQuery("select * from PRODUCT where id='wrongTypeId'", Product.class);
@ -291,7 +295,7 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void whenDeletingADeletedObject_thenOptimisticLockException() { public void whenDeletingADeletedObject_thenOptimisticLockException() {
thrown.expect(isA(OptimisticLockException.class)); thrown.expect(isA(OptimisticLockException.class));
thrown.expectMessage("Batch update returned unexpected row count from update"); thrown.expectMessage("Row was updated or deleted by another transaction");
thrown.expectCause(isA(StaleStateException.class)); thrown.expectCause(isA(StaleStateException.class));
Session session = null; Session session = null;
@ -327,8 +331,8 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void whenUpdatingNonExistingObject_thenStaleStateException() { public void whenUpdatingNonExistingObject_thenStaleStateException() {
thrown.expectCause(isA(StaleStateException.class)); thrown.expectCause(isA(StaleObjectStateException.class));
thrown.expectMessage("Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: update PRODUCT set description=?, name=? where id=?"); thrown.expectMessage("Row was updated or deleted by another transaction");
Session session = null; Session session = null;
Transaction transaction = null; Transaction transaction = null;
@ -409,9 +413,7 @@ public class HibernateExceptionUnitTest {
@Test @Test
public void givenExistingEntity_whenIdUpdated_thenHibernateException() { public void givenExistingEntity_whenIdUpdated_thenHibernateException() {
thrown.expect(isA(PersistenceException.class)); thrown.expect(isA(HibernateException.class));
thrown.expectCause(isA(HibernateException.class));
thrown.expectMessage("identifier of an instance of com.baeldung.hibernate.exception.Product was altered");
Session session = null; Session session = null;
Transaction transaction = null; Transaction transaction = null;

View File

@ -10,7 +10,7 @@ import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionPr
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider { public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider<String> {
private final Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>(); private final Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
@ -26,6 +26,7 @@ public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnect
.next(); .next();
} }
@Override @Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) { protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
return connectionProviderMap.get(tenantIdentifier); return connectionProviderMap.get(tenantIdentifier);

View File

@ -12,7 +12,7 @@ import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionPr
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider { public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider<String> {
private final ConnectionProvider connectionProvider; private final ConnectionProvider connectionProvider;

View File

@ -179,7 +179,7 @@ public class SaveMethodsIntegrationTest {
.commit(); .commit();
session.beginTransaction(); session.beginTransaction();
assertNull(person.getId()); assertNotNull(person.getId());
assertNotNull(mergedPerson.getId()); assertNotNull(mergedPerson.getId());
} }

View File

@ -20,7 +20,7 @@
<version>${hsqldb.version}</version> <version>${hsqldb.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version> <version>${hibernate.version}</version>
</dependency> </dependency>
@ -34,6 +34,7 @@
<properties> <properties>
<hsqldb.version>2.7.1</hsqldb.version> <hsqldb.version>2.7.1</hsqldb.version>
<h2.version>2.1.214</h2.version> <h2.version>2.1.214</h2.version>
<hibernate.version>6.4.2.Final</hibernate.version>
</properties> </properties>
</project> </project>

View File

@ -26,9 +26,8 @@ public class Author {
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST}) @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "book_id") @ManyToMany(mappedBy = "authors")
private Set<Book> books = new HashSet<>(); private Set<Book> books = new HashSet<>();
public void addBook(Book book) { public void addBook(Book book) {

View File

@ -1,6 +1,7 @@
package com.baeldung.hibernate.exception.transientobject.entity; package com.baeldung.hibernate.exception.transientobject.entity;
import jakarta.persistence.JoinTable;
import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.CascadeType;
@ -29,7 +30,7 @@ public class Book {
@ManyToMany @ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST}) @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "author_id") @JoinTable(joinColumns = { @JoinColumn(name = "author_id") })
private Set<Author> authors = new HashSet<>(); private Set<Author> authors = new HashSet<>();
public void addAuthor(Author author) { public void addAuthor(Author author) {

View File

@ -44,7 +44,7 @@ class NamedParameterNotBoundExceptionUnitTest {
query.list(); query.list();
}); });
String expectedMessage = "Named parameter not bound"; String expectedMessage = "No argument for named parameter";
String actualMessage = exception.getMessage(); String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage)); assertTrue(actualMessage.contains(expectedMessage));

View File

@ -15,7 +15,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version> <version>${hibernate.version}</version>
</dependency> </dependency>
@ -84,6 +84,7 @@
<properties> <properties>
<mysql.version>8.2.0</mysql.version> <mysql.version>8.2.0</mysql.version>
<hibernate.version>6.4.2.Final</hibernate.version>
<mariaDB4j.version>2.6.0</mariaDB4j.version> <mariaDB4j.version>2.6.0</mariaDB4j.version>
<spring-boot.version>3.0.4</spring-boot.version> <spring-boot.version>3.0.4</spring-boot.version>
<h2.version>2.1.214</h2.version> <h2.version>2.1.214</h2.version>

View File

@ -8,9 +8,9 @@
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId> <artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath> <relativePath>../../parent-boot-3</relativePath>
</parent> </parent>
<dependencies> <dependencies>
@ -19,8 +19,9 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.persistence</groupId> <groupId>jakarta.persistence</groupId>
<artifactId>javax.persistence-api</artifactId> <artifactId>jakarta.persistence-api</artifactId>
<version>${jakarta.persistence.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
@ -29,6 +30,16 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</exclusion>
<exclusion>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
@ -36,33 +47,21 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.querydsl</groupId> <groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId> <artifactId>querydsl-jpa</artifactId>
<classifier>jakarta</classifier>
<version>${querydsl.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.querydsl</groupId> <groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId> <artifactId>querydsl-apt</artifactId>
<classifier>jakarta</classifier>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.bsc.maven</groupId> <groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId> <artifactId>maven-processor-plugin</artifactId>
@ -86,11 +85,21 @@
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId> <artifactId>hibernate-jpamodelgen</artifactId>
<version>5.6.11.Final</version> <version>${hibernate-jpamodelgen.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<querydsl.version>5.0.0</querydsl.version>
<jakarta.persistence.version>3.1.0</jakarta.persistence.version>
<apt-maven-plugin.version>1.1.3</apt-maven-plugin.version>
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
<hibernate-jpamodelgen.version>6.4.2.Final</hibernate-jpamodelgen.version>
</properties>
</project> </project>

View File

@ -1,8 +1,8 @@
package com.baeldung.spring.data.persistence.customrepository.model; package com.baeldung.spring.data.persistence.customrepository.model;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.Id; import jakarta.persistence.Id;
import java.util.Objects; import java.util.Objects;
@Entity @Entity

View File

@ -2,9 +2,9 @@ package com.baeldung.spring.data.persistence.customrepository.repository;
import com.baeldung.spring.data.persistence.customrepository.model.User; import com.baeldung.spring.data.persistence.customrepository.model.User;
import javax.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import java.util.Objects; import java.util.Objects;
public class CustomUserRepositoryImpl implements CustomUserRepository { public class CustomUserRepositoryImpl implements CustomUserRepository {

View File

@ -1,9 +1,9 @@
package com.baeldung.spring.data.persistence.findbyvsfindallby.model; package com.baeldung.spring.data.persistence.findbyvsfindallby.model;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
import java.util.Objects; import java.util.Objects;
@Entity @Entity

View File

@ -1,9 +1,9 @@
package com.baeldung.spring.data.persistence.saveperformance; package com.baeldung.spring.data.persistence.saveperformance;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
@Entity @Entity
public class Book { public class Book {

View File

@ -2,10 +2,10 @@ package com.baeldung.spring.data.persistence.search;
import java.util.Objects; import java.util.Objects;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
@Entity @Entity
public class Student { public class Student {

View File

@ -3,13 +3,13 @@ package com.baeldung.spring.data.persistence.springdatajpadifference.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Table(name = "employee") @Table(name = "employee")

View File

@ -2,7 +2,7 @@ package com.baeldung.spring.data.persistence.springdatajpadifference.springdata.
import java.util.Properties; import java.util.Properties;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;

View File

@ -1,11 +1,11 @@
package com.baeldung.spring.data.persistence.springdatajpadifference.springdata.repository; package com.baeldung.spring.data.persistence.springdatajpadifference.springdata.repository;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import com.baeldung.spring.data.persistence.springdatajpadifference.model.Employee; import com.baeldung.spring.data.persistence.springdatajpadifference.model.Employee;
@Repository @Repository
public interface EmployeeRepositoryPagingAndSort extends PagingAndSortingRepository<Employee, Long> { public interface EmployeeRepositoryPagingAndSort extends JpaRepository<Employee, Long> {
} }

View File

@ -13,8 +13,6 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;

View File

@ -7,15 +7,15 @@ import static org.junit.Assert.assertNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.EntityManagerFactory; import jakarta.persistence.EntityManagerFactory;
import javax.persistence.Persistence; import jakarta.persistence.Persistence;
import javax.persistence.Query; import jakarta.persistence.Query;
import javax.persistence.TypedQuery; import jakarta.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate; import jakarta.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Root; import jakarta.persistence.criteria.Root;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -1194,8 +1194,8 @@
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version> <exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<log4j.version>1.2.17</log4j.version> <log4j.version>1.2.17</log4j.version>
<jmh-core.version>1.36</jmh-core.version> <jmh-core.version>1.37</jmh-core.version>
<jmh-generator.version>1.36</jmh-generator.version> <jmh-generator.version>1.37</jmh-generator.version>
<maven-failsafe-plugin.version>3.1.2</maven-failsafe-plugin.version> <maven-failsafe-plugin.version>3.1.2</maven-failsafe-plugin.version>
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-io.version>2.13.0</commons-io.version> <commons-io.version>2.13.0</commons-io.version>

View File

@ -11,7 +11,8 @@
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>spring-security-modules</artifactId> <artifactId>parent-boot-3</artifactId>
<relativePath>../../parent-boot-3</relativePath>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
@ -46,16 +47,6 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
</dependency> </dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache-core.version}</version>
<type>jar</type>
</dependency>
</dependencies> </dependencies>
<properties>
<ehcache-core.version>2.6.11</ehcache-core.version>
</properties>
</project> </project>

View File

@ -4,8 +4,7 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.ehcache.EhCacheFactoryBean; import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
@ -16,7 +15,7 @@ import org.springframework.security.acls.domain.AclAuthorizationStrategy;
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl; import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
import org.springframework.security.acls.domain.ConsoleAuditLogger; import org.springframework.security.acls.domain.ConsoleAuditLogger;
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy; import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
import org.springframework.security.acls.domain.EhCacheBasedAclCache; import org.springframework.security.acls.domain.SpringCacheBasedAclCache;
import org.springframework.security.acls.jdbc.BasicLookupStrategy; import org.springframework.security.acls.jdbc.BasicLookupStrategy;
import org.springframework.security.acls.jdbc.JdbcMutableAclService; import org.springframework.security.acls.jdbc.JdbcMutableAclService;
import org.springframework.security.acls.jdbc.LookupStrategy; import org.springframework.security.acls.jdbc.LookupStrategy;
@ -31,21 +30,9 @@ public class ACLContext {
DataSource dataSource; DataSource dataSource;
@Bean @Bean
public EhCacheBasedAclCache aclCache() { public SpringCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy()); final ConcurrentMapCache aclCache = new ConcurrentMapCache("acl_cache");
} return new SpringCacheBasedAclCache(aclCache, permissionGrantingStrategy(), aclAuthorizationStrategy());
@Bean
public EhCacheFactoryBean aclEhCacheFactoryBean() {
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
@Bean
public EhCacheManagerFactoryBean aclCacheManager() {
return new EhCacheManagerFactoryBean();
} }
@Bean @Bean

View File

@ -1,9 +1,9 @@
package com.baeldung.acl.persistence.entity; package com.baeldung.acl.persistence.entity;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Table(name="system_message") @Table(name="system_message")

View File

@ -1,7 +1,7 @@
INSERT INTO acl_sid (id, principal, sid) VALUES INSERT INTO acl_sid (principal, sid) VALUES
(1, 1, 'manager'), (1, 'manager'),
(2, 1, 'hr'), (1, 'hr'),
(3, 0, 'ROLE_EDITOR'); (0, 'ROLE_EDITOR');
INSERT INTO acl_class (id, class) VALUES INSERT INTO acl_class (id, class) VALUES
(1, 'com.baeldung.acl.persistence.entity.NoticeMessage'); (1, 'com.baeldung.acl.persistence.entity.NoticeMessage');
@ -11,16 +11,16 @@ INSERT INTO system_message(id,content) VALUES
(2,'Second Level Message'), (2,'Second Level Message'),
(3,'Third Level Message'); (3,'Third Level Message');
INSERT INTO acl_object_identity (id, object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES INSERT INTO acl_object_identity (object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES
(1, 1, 1, NULL, 3, 0), (1, 1, NULL, 3, 0),
(2, 1, 2, NULL, 3, 0), (1, 2, NULL, 3, 0),
(3, 1, 3, NULL, 3, 0); (1, 3, NULL, 3, 0);
INSERT INTO acl_entry (id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure) VALUES INSERT INTO acl_entry (acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure) VALUES
(1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1),
(2, 1, 2, 1, 2, 1, 1, 1), (1, 2, 1, 2, 1, 1, 1),
(3, 1, 3, 3, 1, 1, 1, 1), (1, 3, 3, 1, 1, 1, 1),
(4, 2, 1, 2, 1, 1, 1, 1), (2, 1, 2, 1, 1, 1, 1),
(5, 2, 2, 3, 1, 1, 1, 1), (2, 2, 3, 1, 1, 1, 1),
(6, 3, 1, 3, 1, 1, 1, 1), (3, 1, 3, 1, 1, 1, 1),
(7, 3, 2, 3, 2, 1, 1, 1); (3, 2, 3, 2, 1, 1, 1);

View File

@ -4,10 +4,12 @@ import com.baeldung.acl.Application;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class) @SpringBootTest(classes = Application.class)
@DirtiesContext
public class SpringContextTest { public class SpringContextTest {
@Test @Test

View File

@ -11,7 +11,8 @@
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>spring-security-modules</artifactId> <artifactId>parent-boot-3</artifactId>
<relativePath>../../parent-boot-3</relativePath>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
@ -30,7 +31,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId> <groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId> <artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency> </dependency>
<!-- oauth2 --> <!-- oauth2 -->
<dependency> <dependency>

View File

@ -2,6 +2,7 @@ package com.baeldung.cognito;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
@ -10,16 +11,13 @@ public class SecurityConfiguration {
@Bean @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf() http.csrf(Customizer.withDefaults())
.and() .authorizeHttpRequests(authz -> authz.requestMatchers("/")
.authorizeRequests(authz -> authz.mvcMatchers("/")
.permitAll() .permitAll()
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
.oauth2Login() .oauth2Login(Customizer.withDefaults())
.and() .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessUrl("/"));
.logout()
.logoutSuccessUrl("/");
return http.build(); return http.build();
} }
} }

View File

@ -19,13 +19,13 @@ public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAutho
@Override @Override
public void onApplicationEvent(AuthorizationEvent event) { public void onApplicationEvent(AuthorizationEvent event) {
if (event instanceof AuthorizationDeniedEvent) { if (event instanceof AuthorizationDeniedEvent) {
onAuthorizationFailureEvent((AuthorizationDeniedEvent) event); onAuthorizationFailureEvent(event);
} }
} }
private void onAuthorizationFailureEvent(AuthorizationDeniedEvent event) { private void onAuthorizationFailureEvent(AuthorizationEvent event) {
String name = this.getName(event.getAuthentication()); String name = this.getName(event.getAuthentication());
Map<String, Object> data = new LinkedHashMap(); Map<String, Object> data = new LinkedHashMap<>();
Object details = this.getDetails(event.getAuthentication()); Object details = this.getDetails(event.getAuthentication());
if (details != null) { if (details != null) {
data.put("details", details); data.put("details", details);

View File

@ -3,9 +3,10 @@ package com.baeldung.app.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
@ -14,7 +15,7 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableMethodSecurity
public class WebSecurityConfig { public class WebSecurityConfig {
@Bean @Bean
@ -25,8 +26,8 @@ public class WebSecurityConfig {
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
.httpBasic(Customizer.withDefaults()) .httpBasic(Customizer.withDefaults())
.logout(logout -> logout.disable()) .logout(AbstractHttpConfigurer::disable)
.csrf(csrf -> csrf.disable()); .csrf(AbstractHttpConfigurer::disable);
return http.build(); return http.build();
} }

View File

@ -6,9 +6,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller @Controller
@RequestMapping("api/tasks") @RequestMapping("api/tasks")
@ -20,14 +21,14 @@ public class TaskController {
@Autowired(required = false) @Autowired(required = false)
private UserDetailsService userDetailsService; private UserDetailsService userDetailsService;
@RequestMapping(method = RequestMethod.GET) @GetMapping
public ResponseEntity<Iterable<Task>> findAllTasks() { public ResponseEntity<Iterable<Task>> findAllTasks() {
Iterable<Task> tasks = taskService.findAll(); Iterable<Task> tasks = taskService.findAll();
return ResponseEntity.ok().body(tasks); return ResponseEntity.ok().body(tasks);
} }
@RequestMapping(method = RequestMethod.POST, consumes = "application/json") @PostMapping(consumes = "application/json")
public ResponseEntity<Iterable<Task>> addTasks(@RequestBody Iterable<Task> newTasks) { public ResponseEntity<Iterable<Task>> addTasks(@RequestBody Iterable<Task> newTasks) {
Iterable<Task> tasks = taskService.save(newTasks); Iterable<Task> tasks = taskService.save(newTasks);

View File

@ -14,7 +14,7 @@ public class CustomFilter implements Filter {
private static Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class); private static Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);
@Override @Override
public void init(FilterConfig config) throws ServletException { public void init(FilterConfig config) {
} }
@Override @Override

View File

@ -2,34 +2,31 @@ package com.baeldung.denyonmissing;
import static org.springframework.security.access.annotation.Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE; import static org.springframework.security.access.annotation.Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.springframework.core.annotation.AnnotationUtils; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations; import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
public class CustomPermissionAllowedMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource { @Component
@Override public class CustomPermissionAllowedMethodSecurityMetadataSource implements AuthorizationManager<MethodInvocation> {
protected Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
return null;
}
@Override @Override
protected Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) { public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
MergedAnnotations annotations = MergedAnnotations.from(method, MergedAnnotations annotations = MergedAnnotations.from(mi.getMethod(), MergedAnnotations.SearchStrategy.DIRECT);
MergedAnnotations.SearchStrategy.DIRECT);
List<ConfigAttribute> attributes = new ArrayList<>(); List<ConfigAttribute> attributes = new ArrayList<>();
MergedAnnotations classAnnotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.DIRECT); MergedAnnotations classAnnotations = MergedAnnotations.from(DenyOnMissingController.class, MergedAnnotations.SearchStrategy.DIRECT);
// if the class is annotated as @Controller we should by default deny access to every method // if the class is annotated as @Controller we should by default deny access to every method
if (classAnnotations.get(Controller.class).isPresent()) { if (classAnnotations.get(Controller.class).isPresent()) {
attributes.add(DENY_ALL_ATTRIBUTE); attributes.add(DENY_ALL_ATTRIBUTE);
@ -38,12 +35,6 @@ public class CustomPermissionAllowedMethodSecurityMetadataSource extends Abstrac
if (annotations.get(PreAuthorize.class).isPresent() || annotations.get(PostAuthorize.class).isPresent()) { if (annotations.get(PreAuthorize.class).isPresent() || annotations.get(PostAuthorize.class).isPresent()) {
return null; return null;
} }
return new AuthorizationDecision(!Collections.disjoint(attributes, authentication.get().getAuthorities()));
return attributes;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
} }
} }

View File

@ -1,10 +1,12 @@
package com.baeldung.denyonmissing; package com.baeldung.denyonmissing;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.method.MethodSecurityMetadataSource; import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
@ -12,11 +14,16 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableMethodSecurity
public class DenyMethodSecurityConfig extends GlobalMethodSecurityConfiguration { public class DenyMethodSecurityConfig {
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { @Bean
return new CustomPermissionAllowedMethodSecurityMetadataSource(); public Advisor preAuthorize(CustomPermissionAllowedMethodSecurityMetadataSource manager) {
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
pattern.setPattern("com.baeldung.denyonmissing.*");
AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(pattern, manager);
interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder() - 1);
return interceptor;
} }
@Bean @Bean

View File

@ -6,6 +6,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@ -42,7 +43,7 @@ public class AppConfig implements WebMvcConfigurer {
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
.httpBasic(Customizer.withDefaults()) .httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable()); .csrf(AbstractHttpConfigurer::disable);
return http.build(); return http.build();
} }

View File

@ -6,11 +6,11 @@ import com.fasterxml.jackson.annotation.JsonView;
public class Item { public class Item {
@JsonView(View.User.class) @JsonView(View.User.class)
private int id; private final int id;
@JsonView(View.User.class) @JsonView(View.User.class)
private String name; private final String name;
@JsonView(View.Admin.class) @JsonView(View.Admin.class)
private String ownerName; private final String ownerName;
public Item(int id, String name, String ownerName) { public Item(int id, String name, String ownerName) {
this.id = id; this.id = id;

View File

@ -41,10 +41,8 @@ public class DenyOnMissingControllerIntegrationTest {
@Test @Test
@WithMockUser(username = "user") @WithMockUser(username = "user")
public void givenANormalUser_whenCallingBye_thenAccessDenied() throws Exception { public void givenANormalUser_whenCallingBye_thenAccessDenied() {
ServletException exception = Assertions.assertThrows(ServletException.class, () -> { ServletException exception = Assertions.assertThrows(ServletException.class, () -> mockMvc.perform(get("/bye")));
mockMvc.perform(get("/bye"));
});
Assertions.assertNotNull(exception); Assertions.assertNotNull(exception);
Assertions.assertEquals(exception.getCause().getClass(), AccessDeniedException.class); Assertions.assertEquals(exception.getCause().getClass(), AccessDeniedException.class);

View File

@ -15,7 +15,7 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -66,6 +66,6 @@ public class SpringSecurityJsonViewIntegrationTest {
}); });
Assertions.assertEquals(exception.getCause().getClass(), IllegalArgumentException.class); Assertions.assertEquals(exception.getCause().getClass(), IllegalArgumentException.class);
assertTrue(exception.getCause().getMessage().equals("Ambiguous @JsonView declaration for roles ROLE_ADMIN,ROLE_USER")); assertEquals("Ambiguous @JsonView declaration for roles ROLE_ADMIN,ROLE_USER", exception.getCause().getMessage());
} }
} }

View File

@ -1,6 +1,7 @@
package com.baeldung.methodsecurity; package com.baeldung.methodsecurity;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,7 +51,7 @@ public class MethodSecurityIntegrationTest {
@WithMockUser(username = "john", roles = { "EDITOR" }) @WithMockUser(username = "john", roles = { "EDITOR" })
public void givenUsernameJohn_whenCallIsValidUsername_thenReturnTrue() { public void givenUsernameJohn_whenCallIsValidUsername_thenReturnTrue() {
boolean isValid = userRoleService.isValidUsername("john"); boolean isValid = userRoleService.isValidUsername("john");
assertEquals(true, isValid); assertTrue(isValid);
} }
@Test(expected = AccessDeniedException.class) @Test(expected = AccessDeniedException.class)
@ -60,7 +61,7 @@ public class MethodSecurityIntegrationTest {
} }
@Test(expected = AccessDeniedException.class) @Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "USER" }) @WithMockUser(username = "john")
public void givenRoleUser_whenCallGetUsername2_thenReturnAccessDenied() { public void givenRoleUser_whenCallGetUsername2_thenReturnAccessDenied() {
userRoleService.getUsername2(); userRoleService.getUsername2();
} }
@ -76,7 +77,7 @@ public class MethodSecurityIntegrationTest {
@WithMockUser(username = "john", roles = { "VIEWER" }) @WithMockUser(username = "john", roles = { "VIEWER" })
public void givenUsernameJerry_whenCallIsValidUsername2_thenReturnFalse() { public void givenUsernameJerry_whenCallIsValidUsername2_thenReturnFalse() {
boolean isValid = userRoleService.isValidUsername2("jerry"); boolean isValid = userRoleService.isValidUsername2("jerry");
assertEquals(false, isValid); assertFalse(isValid);
} }
@Test @Test