Merge branch 'eugenp:master' into master

This commit is contained in:
Wynn Teo
2024-02-12 19:09:23 +08:00
committed by GitHub
49 changed files with 224 additions and 229 deletions
+10 -4
View File
@@ -18,6 +18,12 @@
<artifactId>transactions-jdbc</artifactId>
<version>${atomikos-version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>${atomikos-version}</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jms</artifactId>
@@ -90,10 +96,10 @@
</dependencies>
<properties>
<atomikos-version>5.0.6</atomikos-version>
<spring-version>5.1.6.RELEASE</spring-version>
<hibernate.version>5.4.3.Final</hibernate.version>
<spring-data-jpa.version>1.11.23.RELEASE</spring-data-jpa.version>
<atomikos-version>6.0.0</atomikos-version>
<spring-version>6.1.2</spring-version>
<hibernate.version>6.4.2.Final</hibernate.version>
<spring-data-jpa.version>3.2.2</spring-data-jpa.version>
<activemq-core.version>5.7.0</activemq-core.version>
<derby.version>10.8.1.2</derby.version>
<jta.version>1.1</jta.version>
@@ -1,17 +1,14 @@
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.jdbc.AtomikosDataSourceBean;
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
@EnableTransactionManagement
@@ -46,7 +43,7 @@ public class Config {
}
@Bean(initMethod = "init", destroyMethod = "close")
public UserTransactionManager userTransactionManager() throws SystemException {
public UserTransactionManager userTransactionManager() throws jakarta.transaction.SystemException {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setTransactionTimeout(300);
userTransactionManager.setForceShutdown(true);
@@ -29,13 +29,13 @@ public class Application {
String orderId = UUID.randomUUID()
.toString();
Inventory inventory = inventoryRepository.findOne(productId);
Inventory inventory = inventoryRepository.getReferenceById(productId);
inventory.setBalance(inventory.getBalance() - amount);
inventoryRepository.save(inventory);
Order order = new Order();
order.setOrderId(orderId);
order.setProductId(productId);
order.setAmount(new Long(amount));
order.setAmount( Long.valueOf(amount));
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Order>> violations = validator.validate(order);
@@ -1,6 +1,6 @@
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.Configuration;
@@ -1,8 +1,8 @@
package com.baeldung.atomikos.spring.jpa.inventory;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "INVENTORY")
@@ -2,7 +2,7 @@ package com.baeldung.atomikos.spring.jpa.inventory;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -1,8 +1,8 @@
package com.baeldung.atomikos.spring.jpa.order;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Max;
@Entity
@@ -2,7 +2,7 @@ package com.baeldung.atomikos.spring.jpa.order;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -72,7 +72,7 @@ public class ApplicationUnitTest {
private static long getBalance(InventoryRepository inventoryRepository, String productId) throws Exception {
return inventoryRepository.findOne(productId)
return inventoryRepository.getReferenceById(productId)
.getBalance();
}
@@ -15,7 +15,7 @@
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
@@ -25,7 +25,7 @@
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version>
</dependency>
@@ -45,7 +45,7 @@
<version>${mariaDB4j.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-testing</artifactId>
<version>${hibernate.version}</version>
</dependency>
@@ -82,6 +82,7 @@
<mysql.version>8.2.0</mysql.version>
<mariaDB4j.version>2.6.0</mariaDB4j.version>
<geodb.version>0.9</geodb.version>
<hibernate.version>6.4.2.Final</hibernate.version>
</properties>
</project>
@@ -9,12 +9,16 @@ import java.util.List;
import jakarta.persistence.OptimisticLockException;
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.MappingException;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.PropertyValueException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings;
@@ -132,8 +136,8 @@ public class HibernateExceptionUnitTest {
@Test
public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() {
thrown.expectCause(isA(SQLGrammarException.class));
thrown.expectMessage("could not prepare statement");
thrown.expectCause(isA(JdbcSQLSyntaxErrorException.class));
thrown.expectMessage("Table \"PRODUCT\" not found (this database is empty); SQL statement");
Configuration cfg = getConfiguration();
cfg.addAnnotatedClass(Product.class);
@@ -161,8 +165,8 @@ public class HibernateExceptionUnitTest {
@Test
public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() {
thrown.expectCause(isA(SQLGrammarException.class));
thrown.expectMessage("could not prepare statement");
thrown.expectCause(isA(JdbcSQLSyntaxErrorException.class));
thrown.expectMessage("Table \"NON_EXISTING_TABLE\" not found");
Session session = sessionFactory.openSession();
NativeQuery<Product> query = session.createNativeQuery("select * from NON_EXISTING_TABLE", Product.class);
@@ -171,7 +175,7 @@ public class HibernateExceptionUnitTest {
@Test
public void whenDuplicateIdSaved_thenConstraintViolationException() {
thrown.expectCause(isA(ConstraintViolationException.class));
thrown.expectCause(isA(JdbcSQLIntegrityConstraintViolationException.class));
thrown.expectMessage("could not execute statement");
Session session = null;
@@ -224,7 +228,7 @@ public class HibernateExceptionUnitTest {
public void givenEntityWithoutId_whenCallingSave_thenThrowIdentifierGenerationException() {
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;
Transaction transaction = null;
@@ -249,8 +253,8 @@ public class HibernateExceptionUnitTest {
@Test
public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() {
thrown.expectCause(isA(DataException.class));
thrown.expectMessage("could not prepare statement");
thrown.expectCause(isA(JdbcSQLDataException.class));
thrown.expectMessage("Data conversion error converting \"wrongTypeId\"");
Session session = sessionFactory.openSession();
NativeQuery<Product> query = session.createNativeQuery("select * from PRODUCT where id='wrongTypeId'", Product.class);
@@ -291,7 +295,7 @@ public class HibernateExceptionUnitTest {
@Test
public void whenDeletingADeletedObject_thenOptimisticLockException() {
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));
Session session = null;
@@ -327,8 +331,8 @@ public class HibernateExceptionUnitTest {
@Test
public void whenUpdatingNonExistingObject_thenStaleStateException() {
thrown.expectCause(isA(StaleStateException.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.expectCause(isA(StaleObjectStateException.class));
thrown.expectMessage("Row was updated or deleted by another transaction");
Session session = null;
Transaction transaction = null;
@@ -409,9 +413,7 @@ public class HibernateExceptionUnitTest {
@Test
public void givenExistingEntity_whenIdUpdated_thenHibernateException() {
thrown.expect(isA(PersistenceException.class));
thrown.expectCause(isA(HibernateException.class));
thrown.expectMessage("identifier of an instance of com.baeldung.hibernate.exception.Product was altered");
thrown.expect(isA(HibernateException.class));
Session session = null;
Transaction transaction = null;
@@ -10,7 +10,7 @@ import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionPr
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
@SuppressWarnings("serial")
public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider<String> {
private final Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
@@ -26,6 +26,7 @@ public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnect
.next();
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
return connectionProviderMap.get(tenantIdentifier);
@@ -12,7 +12,7 @@ import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionPr
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
@SuppressWarnings("serial")
public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider<String> {
private final ConnectionProvider connectionProvider;
@@ -179,7 +179,7 @@ public class SaveMethodsIntegrationTest {
.commit();
session.beginTransaction();
assertNull(person.getId());
assertNotNull(person.getId());
assertNotNull(mergedPerson.getId());
}
@@ -20,7 +20,7 @@
<version>${hsqldb.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
@@ -34,6 +34,7 @@
<properties>
<hsqldb.version>2.7.1</hsqldb.version>
<h2.version>2.1.214</h2.version>
<hibernate.version>6.4.2.Final</hibernate.version>
</properties>
</project>
@@ -26,9 +26,8 @@ public class Author {
@Column(name = "name")
private String name;
@ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "book_id")
@ManyToMany(mappedBy = "authors")
private Set<Book> books = new HashSet<>();
public void addBook(Book book) {
@@ -1,6 +1,7 @@
package com.baeldung.hibernate.exception.transientobject.entity;
import jakarta.persistence.JoinTable;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@@ -29,7 +30,7 @@ public class Book {
@ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "author_id")
@JoinTable(joinColumns = { @JoinColumn(name = "author_id") })
private Set<Author> authors = new HashSet<>();
public void addAuthor(Author author) {
@@ -44,7 +44,7 @@ class NamedParameterNotBoundExceptionUnitTest {
query.list();
});
String expectedMessage = "Named parameter not bound";
String expectedMessage = "No argument for named parameter";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
+2 -1
View File
@@ -15,7 +15,7 @@
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
@@ -84,6 +84,7 @@
<properties>
<mysql.version>8.2.0</mysql.version>
<hibernate.version>6.4.2.Final</hibernate.version>
<mariaDB4j.version>2.6.0</mariaDB4j.version>
<spring-boot.version>3.0.4</spring-boot.version>
<h2.version>2.1.214</h2.version>
@@ -8,9 +8,9 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
<relativePath>../../parent-boot-3</relativePath>
</parent>
<dependencies>
@@ -19,8 +19,9 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>${jakarta.persistence.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
@@ -29,6 +30,16 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<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>
<groupId>com.h2database</groupId>
@@ -36,33 +47,21 @@
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<artifactId>querydsl-jpa</artifactId>
<classifier>jakarta</classifier>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<artifactId>querydsl-apt</artifactId>
<classifier>jakarta</classifier>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<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>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
@@ -86,11 +85,21 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.6.11.Final</version>
<version>${hibernate-jpamodelgen.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</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>
@@ -1,8 +1,8 @@
package com.baeldung.spring.data.persistence.customrepository.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import java.util.Objects;
@Entity
@@ -2,9 +2,9 @@ package com.baeldung.spring.data.persistence.customrepository.repository;
import com.baeldung.spring.data.persistence.customrepository.model.User;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import jakarta.annotation.PostConstruct;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.Objects;
public class CustomUserRepositoryImpl implements CustomUserRepository {
@@ -1,9 +1,9 @@
package com.baeldung.spring.data.persistence.findbyvsfindallby.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.Objects;
@Entity
@@ -1,9 +1,9 @@
package com.baeldung.spring.data.persistence.saveperformance;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Book {
@@ -2,10 +2,10 @@ package com.baeldung.spring.data.persistence.search;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Student {
@@ -3,13 +3,13 @@ package com.baeldung.spring.data.persistence.springdatajpadifference.model;
import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
@Entity
@Table(name = "employee")
@@ -2,7 +2,7 @@ package com.baeldung.spring.data.persistence.springdatajpadifference.springdata.
import java.util.Properties;
import javax.persistence.EntityManager;
import jakarta.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
@@ -1,11 +1,11 @@
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 com.baeldung.spring.data.persistence.springdatajpadifference.model.Employee;
@Repository
public interface EmployeeRepositoryPagingAndSort extends PagingAndSortingRepository<Employee, Long> {
public interface EmployeeRepositoryPagingAndSort extends JpaRepository<Employee, Long> {
}
@@ -13,8 +13,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
@@ -7,15 +7,15 @@ import static org.junit.Assert.assertNull;
import java.util.Arrays;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Root;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
import jakarta.persistence.criteria.Root;
import org.junit.Before;
import org.junit.Test;
+2 -2
View File
@@ -1194,8 +1194,8 @@
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
<java.version>1.8</java.version>
<log4j.version>1.2.17</log4j.version>
<jmh-core.version>1.36</jmh-core.version>
<jmh-generator.version>1.36</jmh-generator.version>
<jmh-core.version>1.37</jmh-core.version>
<jmh-generator.version>1.37</jmh-generator.version>
<maven-failsafe-plugin.version>3.1.2</maven-failsafe-plugin.version>
<commons-collections4.version>4.4</commons-collections4.version>
<commons-io.version>2.13.0</commons-io.version>
@@ -11,7 +11,8 @@
<parent>
<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>
</parent>
@@ -46,16 +47,6 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache-core.version}</version>
<type>jar</type>
</dependency>
</dependencies>
<properties>
<ehcache-core.version>2.6.11</ehcache-core.version>
</properties>
</project>
@@ -4,8 +4,7 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.ehcache.EhCacheFactoryBean;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.ConsoleAuditLogger;
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.JdbcMutableAclService;
import org.springframework.security.acls.jdbc.LookupStrategy;
@@ -31,21 +30,9 @@ public class ACLContext {
DataSource dataSource;
@Bean
public EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), 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();
public SpringCacheBasedAclCache aclCache() {
final ConcurrentMapCache aclCache = new ConcurrentMapCache("acl_cache");
return new SpringCacheBasedAclCache(aclCache, permissionGrantingStrategy(), aclAuthorizationStrategy());
}
@Bean
@@ -1,9 +1,9 @@
package com.baeldung.acl.persistence.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name="system_message")
@@ -1,7 +1,7 @@
INSERT INTO acl_sid (id, principal, sid) VALUES
(1, 1, 'manager'),
(2, 1, 'hr'),
(3, 0, 'ROLE_EDITOR');
INSERT INTO acl_sid (principal, sid) VALUES
(1, 'manager'),
(1, 'hr'),
(0, 'ROLE_EDITOR');
INSERT INTO acl_class (id, class) VALUES
(1, 'com.baeldung.acl.persistence.entity.NoticeMessage');
@@ -11,16 +11,16 @@ INSERT INTO system_message(id,content) VALUES
(2,'Second 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
(1, 1, 1, NULL, 3, 0),
(2, 1, 2, NULL, 3, 0),
(3, 1, 3, NULL, 3, 0);
INSERT INTO acl_object_identity (object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES
(1, 1, NULL, 3, 0),
(1, 2, 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
(1, 1, 1, 1, 1, 1, 1, 1),
(2, 1, 2, 1, 2, 1, 1, 1),
(3, 1, 3, 3, 1, 1, 1, 1),
(4, 2, 1, 2, 1, 1, 1, 1),
(5, 2, 2, 3, 1, 1, 1, 1),
(6, 3, 1, 3, 1, 1, 1, 1),
(7, 3, 2, 3, 2, 1, 1, 1);
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, 2, 1, 2, 1, 1, 1),
(1, 3, 3, 1, 1, 1, 1),
(2, 1, 2, 1, 1, 1, 1),
(2, 2, 3, 1, 1, 1, 1),
(3, 1, 3, 1, 1, 1, 1),
(3, 2, 3, 2, 1, 1, 1);
@@ -4,10 +4,12 @@ import com.baeldung.acl.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@DirtiesContext
public class SpringContextTest {
@Test
@@ -11,7 +11,8 @@
<parent>
<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>
</parent>
@@ -30,7 +31,7 @@
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
<!-- oauth2 -->
<dependency>
@@ -2,6 +2,7 @@ package com.baeldung.cognito;
import org.springframework.context.annotation.Bean;
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.web.SecurityFilterChain;
@@ -10,16 +11,13 @@ public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.and()
.authorizeRequests(authz -> authz.mvcMatchers("/")
http.csrf(Customizer.withDefaults())
.authorizeHttpRequests(authz -> authz.requestMatchers("/")
.permitAll()
.anyRequest()
.authenticated())
.oauth2Login()
.and()
.logout()
.logoutSuccessUrl("/");
.oauth2Login(Customizer.withDefaults())
.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessUrl("/"));
return http.build();
}
}
@@ -19,13 +19,13 @@ public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAutho
@Override
public void onApplicationEvent(AuthorizationEvent event) {
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());
Map<String, Object> data = new LinkedHashMap();
Map<String, Object> data = new LinkedHashMap<>();
Object details = this.getDetails(event.getAuthentication());
if (details != null) {
data.put("details", details);
@@ -3,9 +3,10 @@ package com.baeldung.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -14,7 +15,7 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableMethodSecurity
public class WebSecurityConfig {
@Bean
@@ -25,8 +26,8 @@ public class WebSecurityConfig {
.anyRequest()
.authenticated())
.httpBasic(Customizer.withDefaults())
.logout(logout -> logout.disable())
.csrf(csrf -> csrf.disable());
.logout(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@@ -6,9 +6,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetailsService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("api/tasks")
@@ -20,14 +21,14 @@ public class TaskController {
@Autowired(required = false)
private UserDetailsService userDetailsService;
@RequestMapping(method = RequestMethod.GET)
@GetMapping
public ResponseEntity<Iterable<Task>> findAllTasks() {
Iterable<Task> tasks = taskService.findAll();
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) {
Iterable<Task> tasks = taskService.save(newTasks);
@@ -14,7 +14,7 @@ public class CustomFilter implements Filter {
private static Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);
@Override
public void init(FilterConfig config) throws ServletException {
public void init(FilterConfig config) {
}
@Override
@@ -2,34 +2,31 @@ package com.baeldung.denyonmissing;
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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.MergedAnnotation;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.MergedAnnotations;
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.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;
public class CustomPermissionAllowedMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
@Override
protected Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
return null;
}
@Component
public class CustomPermissionAllowedMethodSecurityMetadataSource implements AuthorizationManager<MethodInvocation> {
@Override
protected Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) {
MergedAnnotations annotations = MergedAnnotations.from(method,
MergedAnnotations.SearchStrategy.DIRECT);
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
MergedAnnotations annotations = MergedAnnotations.from(mi.getMethod(), MergedAnnotations.SearchStrategy.DIRECT);
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 (classAnnotations.get(Controller.class).isPresent()) {
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()) {
return null;
}
return attributes;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
return new AuthorizationDecision(!Collections.disjoint(attributes, authentication.get().getAuthorities()));
}
}
@@ -1,10 +1,12 @@
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.Configuration;
import org.springframework.security.access.method.MethodSecurityMetadataSource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -12,11 +14,16 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class DenyMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return new CustomPermissionAllowedMethodSecurityMetadataSource();
@EnableMethodSecurity
public class DenyMethodSecurityConfig {
@Bean
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
@@ -6,6 +6,7 @@ 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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -42,7 +43,7 @@ public class AppConfig implements WebMvcConfigurer {
.anyRequest()
.authenticated())
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable());
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@@ -6,11 +6,11 @@ import com.fasterxml.jackson.annotation.JsonView;
public class Item {
@JsonView(View.User.class)
private int id;
private final int id;
@JsonView(View.User.class)
private String name;
private final String name;
@JsonView(View.Admin.class)
private String ownerName;
private final String ownerName;
public Item(int id, String name, String ownerName) {
this.id = id;
@@ -41,10 +41,8 @@ public class DenyOnMissingControllerIntegrationTest {
@Test
@WithMockUser(username = "user")
public void givenANormalUser_whenCallingBye_thenAccessDenied() throws Exception {
ServletException exception = Assertions.assertThrows(ServletException.class, () -> {
mockMvc.perform(get("/bye"));
});
public void givenANormalUser_whenCallingBye_thenAccessDenied() {
ServletException exception = Assertions.assertThrows(ServletException.class, () -> mockMvc.perform(get("/bye")));
Assertions.assertNotNull(exception);
Assertions.assertEquals(exception.getCause().getClass(), AccessDeniedException.class);
@@ -15,7 +15,7 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
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.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -66,6 +66,6 @@ public class SpringSecurityJsonViewIntegrationTest {
});
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());
}
}
@@ -1,6 +1,7 @@
package com.baeldung.methodsecurity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
@@ -50,7 +51,7 @@ public class MethodSecurityIntegrationTest {
@WithMockUser(username = "john", roles = { "EDITOR" })
public void givenUsernameJohn_whenCallIsValidUsername_thenReturnTrue() {
boolean isValid = userRoleService.isValidUsername("john");
assertEquals(true, isValid);
assertTrue(isValid);
}
@Test(expected = AccessDeniedException.class)
@@ -60,7 +61,7 @@ public class MethodSecurityIntegrationTest {
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "USER" })
@WithMockUser(username = "john")
public void givenRoleUser_whenCallGetUsername2_thenReturnAccessDenied() {
userRoleService.getUsername2();
}
@@ -76,7 +77,7 @@ public class MethodSecurityIntegrationTest {
@WithMockUser(username = "john", roles = { "VIEWER" })
public void givenUsernameJerry_whenCallIsValidUsername2_thenReturnFalse() {
boolean isValid = userRoleService.isValidUsername2("jerry");
assertEquals(false, isValid);
assertFalse(isValid);
}
@Test