This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new ad896bfb85 Complete JCache support for Core (#1545)
ad896bfb85 is described below
commit ad896bfb85d91ec5f158a149832507e09e39ba76
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Sep 23 09:02:45 2026 +0200
Complete JCache support for Core (#1545)
---
.github/workflows/crosschecks.yml | 2 +-
.../resources/archetype-resources/core/pom.xml | 4 +
.../src/main/resources/archetype-resources/pom.xml | 5 ++
core/cache/caffeine/pom.xml | 55 +++++++++++++
core/cache/ehcache/pom.xml | 55 +++++++++++++
core/cache/hazelcast/pom.xml | 55 +++++++++++++
core/cache/infinispan/pom.xml | 55 +++++++++++++
core/cache/pom.xml | 94 ++++++++++++++++++++++
.../core/persistence/jpa/JPADomainRegistry.java | 14 ++--
.../core/persistence/jpa/PersistenceContext.java | 35 ++++----
.../persistence/jpa/PersistenceProperties.java | 30 +++----
.../core/persistence/jpa/entity/JPARole.java | 3 +-
.../jpa/entity/anyobject/JPAAnyObject.java | 6 +-
.../persistence/jpa/entity/group/JPAGroup.java | 3 +-
.../persistence/jpa/entity/task/JPAMacroTask.java | 3 +-
.../core/persistence/jpa/entity/user/JPAUser.java | 21 +++--
.../jpa/spring/CommonEntityManagerFactoryConf.java | 2 +-
.../jpa/spring/DomainEntityManagerFactoryBean.java | 63 ++++++---------
.../spring/DomainRoutingEntityManagerFactory.java | 32 +++++---
.../persistence/jpa/PersistenceTestContext.java | 12 ++-
.../neo4j/entity/task/Neo4jMacroTask.java | 3 +-
.../persistence/neo4j/entity/user/Neo4jUser.java | 15 ++--
core/pom.xml | 1 +
.../spring/security/DefaultCredentialChecker.java | 8 +-
.../security/throttle/AbstractThrottler.java | 7 +-
.../security/throttle/AuthenticationThrottler.java | 59 +++++++-------
.../throttle/PasswordResetRequestThrottler.java | 64 +++++++--------
.../throttle/AuthenticationThrottlerTest.java | 10 ++-
core/starter/pom.xml | 4 -
core/starter/src/main/resources/core.properties | 2 -
.../core/workflow/java/WorkflowTestContext.java | 7 ++
docker/core/pom.xml | 39 +++++++++
docker/core/src/main/resources/Dockerfile | 3 +-
.../core/src/main/resources/core-docker.properties | 2 -
docker/core/src/main/resources/startup.sh | 22 +++++
.../docker-compose/docker-compose-all.yml | 2 +-
.../resources/docker-compose/docker-compose-ha.yml | 4 +-
.../docker-compose/docker-compose-mariadb.yml | 2 +-
.../docker-compose/docker-compose-mysql.yml | 2 +-
.../docker-compose/docker-compose-oracle.yml | 2 +-
.../docker-compose/docker-compose-postgresql.yml | 2 +-
.../syncope/templates/syncope-deployment.yaml | 2 +-
fit/core-reference/pom.xml | 21 +++--
.../src/main/resources/core-payara.properties | 18 -----
src/main/asciidoc/getting-started/obtain.adoc | 11 ++-
.../concepts/attributerepositories.adoc | 14 ++--
.../concepts/authenticationmodules.adoc | 36 ++++-----
.../reference-guide/concepts/authprofile.adoc | 10 +--
.../concepts/clientapplications.adoc | 6 +-
.../asciidoc/reference-guide/concepts/domains.adoc | 2 +-
.../concepts/passwordmanagement.adoc | 10 +--
.../reference-guide/concepts/policies.adoc | 8 +-
.../configuration/highavailability.adoc | 87 ++++++++++++++++----
.../asciidoc/reference-guide/usage/actuator.adoc | 12 +--
.../reference-guide/usage/customization.adoc | 2 +-
.../asciidoc/reference-guide/usage/metrics.adoc | 2 +-
56 files changed, 740 insertions(+), 310 deletions(-)
diff --git a/.github/workflows/crosschecks.yml
b/.github/workflows/crosschecks.yml
index d0deecd39b..2038b8a375 100644
--- a/.github/workflows/crosschecks.yml
+++ b/.github/workflows/crosschecks.yml
@@ -31,7 +31,7 @@ jobs:
fail-fast: false
matrix:
language: ['java']
- java: [ '25', '27-ea' ]
+ java: [ '25', '28-ea' ]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
diff --git a/archetype/src/main/resources/archetype-resources/core/pom.xml
b/archetype/src/main/resources/archetype-resources/core/pom.xml
index 39282e92af..6d0b2de0e3 100644
--- a/archetype/src/main/resources/archetype-resources/core/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/core/pom.xml
@@ -47,6 +47,10 @@ under the License.
<groupId>org.apache.syncope.core</groupId>
<artifactId>syncope-core-starter</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.syncope.core.idm</groupId>
<artifactId>syncope-core-idm-rest-cxf</artifactId>
diff --git a/archetype/src/main/resources/archetype-resources/pom.xml
b/archetype/src/main/resources/archetype-resources/pom.xml
index 25a71bc0e9..ae9d094b4e 100644
--- a/archetype/src/main/resources/archetype-resources/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/pom.xml
@@ -67,6 +67,11 @@ under the License.
<artifactId>syncope-core-starter</artifactId>
<version>${syncope.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${syncope.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.syncope.core.idm</groupId>
<artifactId>syncope-core-idm-rest-cxf</artifactId>
diff --git a/core/cache/caffeine/pom.xml b/core/cache/caffeine/pom.xml
new file mode 100644
index 0000000000..ceeb6d677a
--- /dev/null
+++ b/core/cache/caffeine/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-cache</artifactId>
+ <version>5.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Core Cache Caffeine</name>
+ <description>Apache Syncope Core Cache Caffeine</description>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.github.ben-manes.caffeine</groupId>
+ <artifactId>jcache</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/cache/ehcache/pom.xml b/core/cache/ehcache/pom.xml
new file mode 100644
index 0000000000..d2d9e3a2c0
--- /dev/null
+++ b/core/cache/ehcache/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-cache</artifactId>
+ <version>5.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Core Cache Ehcache</name>
+ <description>Apache Syncope Core Cache Ehcache</description>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-ehcache</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/cache/hazelcast/pom.xml b/core/cache/hazelcast/pom.xml
new file mode 100644
index 0000000000..d6873a57b0
--- /dev/null
+++ b/core/cache/hazelcast/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-cache</artifactId>
+ <version>5.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Core Cache Hazelcast</name>
+ <description>Apache Syncope Core Cache Hazelcast</description>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-hazelcast</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.hazelcast</groupId>
+ <artifactId>hazelcast</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/cache/infinispan/pom.xml b/core/cache/infinispan/pom.xml
new file mode 100644
index 0000000000..c6906fea85
--- /dev/null
+++ b/core/cache/infinispan/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-cache</artifactId>
+ <version>5.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Core Cache Infinispan</name>
+ <description>Apache Syncope Core Cache Infinispan</description>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-infinispan</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-jcache</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/cache/pom.xml b/core/cache/pom.xml
new file mode 100644
index 0000000000..10c81c8228
--- /dev/null
+++ b/core/cache/pom.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope</groupId>
+ <artifactId>syncope-core</artifactId>
+ <version>5.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Core Cache</name>
+ <description>Apache Syncope Core Cache</description>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-cache</artifactId>
+ <packaging>pom</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <inlineDescriptors>
+ <inlineDescriptor>
+ <id>wrap</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/</outputDirectory>
+ <useProjectArtifact>false</useProjectArtifact>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+ <files>
+ <file>
+ <source>${rootpom.basedir}/LICENSE</source>
+ <outputDirectory>META-INF</outputDirectory>
+ </file>
+ <file>
+ <source>${rootpom.basedir}/NOTICE</source>
+ <outputDirectory>META-INF</outputDirectory>
+ </file>
+ </files>
+ </inlineDescriptor>
+ </inlineDescriptors>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <modules>
+ <module>caffeine</module>
+ <module>hazelcast</module>
+ <module>ehcache</module>
+ <module>infinispan</module>
+ </modules>
+</project>
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/JPADomainRegistry.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/JPADomainRegistry.java
index e9dbe5dac1..df1fa5e3d5 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/JPADomainRegistry.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/JPADomainRegistry.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.jpa;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.ByteArrayInputStream;
+import javax.cache.CacheManager;
import javax.sql.DataSource;
import org.apache.syncope.common.keymaster.client.api.model.JPADomain;
import org.apache.syncope.core.persistence.api.DomainHolder;
@@ -33,9 +34,12 @@ import org.springframework.jndi.JndiObjectFactoryBean;
public class JPADomainRegistry implements DomainRegistry<JPADomain> {
+ protected final CacheManager cacheManager;
+
protected final ConfigurableApplicationContext ctx;
- public JPADomainRegistry(final ConfigurableApplicationContext ctx) {
+ public JPADomainRegistry(final CacheManager cacheManager, final
ConfigurableApplicationContext ctx) {
+ this.cacheManager = cacheManager;
this.ctx = ctx;
}
@@ -78,12 +82,12 @@ public class JPADomainRegistry implements
DomainRegistry<JPADomain> {
addPropertyValue("jndiName",
"java:comp/env/jdbc/syncope" + domain.getKey() + "DataSource").
addPropertyValue("defaultObject", new
HikariDataSource(hikariConfig)).
getBeanDefinition());
- DataSource initedDataSource = beanFactory().getBean(domain.getKey() +
"DataSource", DataSource.class);
+ DataSource initedDataSource = ctx.getBean(domain.getKey() +
"DataSource", DataSource.class);
domainHolder().getDomains().put(domain.getKey(), initedDataSource);
// DomainRoutingEntityManagerFactory#domain
-
beanFactory().getBean(DomainRoutingEntityManagerFactory.class).domain(domain,
initedDataSource);
+ ctx.getBean(DomainRoutingEntityManagerFactory.class).domain(domain,
initedDataSource, cacheManager);
// domainContentXML
beanFactory().registerBeanDefinition(domain.getKey() + "ContentXML",
@@ -109,7 +113,7 @@ public class JPADomainRegistry implements
DomainRegistry<JPADomain> {
beanFactory().removeBeanDefinition(domain + "ContentXML");
// DomainRoutingEntityManagerFactory#remove
-
beanFactory().getBean(DomainRoutingEntityManagerFactory.class).remove(domain);
+ ctx.getBean(DomainRoutingEntityManagerFactory.class).remove(domain);
// domainDataSourceInitializer
unregisterSingleton(domain.toLowerCase() + "DataSourceInitializer");
@@ -121,6 +125,6 @@ public class JPADomainRegistry implements
DomainRegistry<JPADomain> {
unregisterSingleton(domain + "DataSource");
beanFactory().removeBeanDefinition(domain + "DataSource");
- beanFactory().getBean(DomainHolder.class).getDomains().remove(domain);
+ ctx.getBean(DomainHolder.class).getDomains().remove(domain);
}
}
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
index 8a8f871f70..374ad73776 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
@@ -20,10 +20,11 @@ package org.apache.syncope.core.persistence.jpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.ValidationMode;
import java.util.HashMap;
import java.util.Map;
-import java.util.Optional;
+import javax.cache.CacheManager;
import javax.sql.DataSource;
import org.apache.syncope.common.keymaster.client.api.DomainOps;
import org.apache.syncope.common.keymaster.client.api.model.JPADomain;
@@ -188,6 +189,8 @@ import
org.apache.syncope.core.persistence.jpa.spring.MultiJarAwarePersistenceUn
import org.apache.syncope.core.persistence.jpa.spring.SyncopeJPARepository;
import org.apache.syncope.core.provisioning.api.ConnectorManager;
import org.apache.syncope.core.spring.security.SecurityProperties;
+import org.hibernate.cache.jcache.ConfigSettings;
+import org.hibernate.cfg.AvailableSettings;
import org.springframework.beans.factory.annotation.Qualifier;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import
org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -217,7 +220,8 @@ public class PersistenceContext {
public CommonEntityManagerFactoryConf commonEMFConf(
final PersistenceProperties props,
@Qualifier("MasterDataSource")
- final JndiObjectFactoryBean masterDataSource) {
+ final JndiObjectFactoryBean masterDataSource,
+ final CacheManager cacheManager) {
CommonEntityManagerFactoryConf commonEMFConf = new
CommonEntityManagerFactoryConf();
commonEMFConf.setPackagesToScan("org.apache.syncope.core.persistence.jpa.entity");
@@ -225,15 +229,14 @@ public class PersistenceContext {
commonEMFConf.setPersistenceUnitPostProcessors(new
MultiJarAwarePersistenceUnitPostProcessor());
Map<String, Object> jpaPropertyMap = new HashMap<>();
-
jpaPropertyMap.put("jakarta.persistence.schema-generation.database.action",
"create");
+ jpaPropertyMap.put(PersistenceConfiguration.SCHEMAGEN_DATABASE_ACTION,
"update");
+
+ jpaPropertyMap.put(AvailableSettings.USE_SECOND_LEVEL_CACHE, "true");
+ jpaPropertyMap.put(AvailableSettings.USE_QUERY_CACHE, "true");
+ jpaPropertyMap.put(AvailableSettings.CACHE_REGION_FACTORY,
DomainJCacheRegionFactory.class.getName());
+ jpaPropertyMap.put(ConfigSettings.CACHE_MANAGER, cacheManager);
- jpaPropertyMap.put("hibernate.cache.use_second_level_cache", "true");
- jpaPropertyMap.put("hibernate.cache.use_query_cache", "true");
- jpaPropertyMap.put("hibernate.cache.region.factory_class", "jcache");
- jpaPropertyMap.put("hibernate.javax.cache.provider",
props.getCacheProvider());
- Optional.ofNullable(props.getCacheURI()).
- ifPresent(cacheURI ->
jpaPropertyMap.put("hibernate.javax.cache.uri", cacheURI));
- jpaPropertyMap.put("hibernate.cache.region.factory_class",
DomainJCacheRegionFactory.class.getName());
+ jpaPropertyMap.putAll(props.getAdditionalJPAProperties());
commonEMFConf.setJpaPropertyMap(jpaPropertyMap);
@@ -250,11 +253,12 @@ public class PersistenceContext {
final JndiObjectFactoryBean masterDataSource,
final CommonEntityManagerFactoryConf commonEMFConf,
final @Lazy ConnectorManager connectorManager,
- final @Lazy ExternalResourceDAO resourceDAO) {
+ final @Lazy ExternalResourceDAO resourceDAO,
+ final CacheManager cacheManager) {
DomainRoutingEntityManagerFactory emf = new
DomainRoutingEntityManagerFactory(
commonEMFConf, connectorManager, resourceDAO);
- emf.master(props, masterDataSource);
+ emf.master(props, masterDataSource, cacheManager);
return emf;
}
@@ -299,8 +303,11 @@ public class PersistenceContext {
@ConditionalOnMissingBean
@Bean
- public DomainRegistry<JPADomain> domainRegistry(final
ConfigurableApplicationContext ctx) {
- return new JPADomainRegistry(ctx);
+ public DomainRegistry<JPADomain> domainRegistry(
+ final CacheManager cacheManager,
+ final ConfigurableApplicationContext ctx) {
+
+ return new JPADomainRegistry(cacheManager, ctx);
}
@ConditionalOnMissingBean
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceProperties.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceProperties.java
index adc5c4e3c3..5c20252192 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceProperties.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceProperties.java
@@ -18,6 +18,8 @@
*/
package org.apache.syncope.core.persistence.jpa;
+import java.util.HashMap;
+import java.util.Map;
import
org.apache.syncope.core.persistence.common.AbstractPersistenceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -28,27 +30,9 @@ public class PersistenceProperties extends
AbstractPersistenceProperties<DomainP
public static final String DB_TYPE = "db-type";
- private String cacheProvider =
"com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider";
-
- private String cacheURI;
-
private String viewsXML = "classpath:META-INF/views.xml";
- public String getCacheProvider() {
- return cacheProvider;
- }
-
- public void setCacheProvider(final String cacheProvider) {
- this.cacheProvider = cacheProvider;
- }
-
- public String getCacheURI() {
- return cacheURI;
- }
-
- public void setCacheURI(final String cacheURI) {
- this.cacheURI = cacheURI;
- }
+ private Map<String, String> additionalJPAProperties = new HashMap<>();
public String getViewsXML() {
return viewsXML;
@@ -57,4 +41,12 @@ public class PersistenceProperties extends
AbstractPersistenceProperties<DomainP
public void setViewsXML(final String viewsXML) {
this.viewsXML = viewsXML;
}
+
+ public Map<String, String> getAdditionalJPAProperties() {
+ return additionalJPAProperties;
+ }
+
+ public void setAdditionalJPAProperties(final Map<String, String>
additionalJPAProperties) {
+ this.additionalJPAProperties = additionalJPAProperties;
+ }
}
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
index 5d89e319a3..9c9a02c372 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
@@ -60,8 +60,7 @@ public class JPARole extends AbstractProvidedKeyEntity
implements Role {
@JoinColumn(name = "realm_id"),
uniqueConstraints =
@UniqueConstraint(columnNames = { "role_id", "realm_id" }))
- @Valid
- private List<JPARealm> realms = new ArrayList<>();
+ private List<@Valid JPARealm> realms = new ArrayList<>();
@Override
public Set<String> getEntitlements() {
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index bc931c30aa..7814485e4a 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -91,12 +91,10 @@ public class JPAAnyObject
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"leftEnd")
- @Valid
- private List<JPAARelationship> relationships = new ArrayList<>();
+ private List<@Valid JPAARelationship> relationships = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"leftEnd")
- @Valid
- private List<JPAAMembership> memberships = new ArrayList<>();
+ private List<@Valid JPAAMembership> memberships = new ArrayList<>();
@Override
public String getName() {
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
index d934f05216..99effe74f5 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
@@ -93,8 +93,7 @@ public class JPAGroup
private List<JPAGroupTypeExtension> typeExtensions = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"leftEnd")
- @Valid
- private List<JPAGRelationship> relationships = new ArrayList<>();
+ private List<@Valid JPAGRelationship> relationships = new ArrayList<>();
@Override
public String getName() {
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAMacroTask.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAMacroTask.java
index 31ad23b78b..e46a7d2ee6 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAMacroTask.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAMacroTask.java
@@ -65,8 +65,7 @@ public class JPAMacroTask extends AbstractSchedTask
implements MacroTask {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
orphanRemoval = true, mappedBy = "macroTask")
@OrderBy("idx")
- @Valid
- private List<JPAFormPropertyDef> formPropertyDefs = new ArrayList<>();
+ private List<@Valid JPAFormPropertyDef> formPropertyDefs = new
ArrayList<>();
@ManyToOne(fetch = FetchType.EAGER)
private JPAImplementation macroActions;
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index aa4fb93a9f..a0a40775d7 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -158,12 +158,10 @@ public class JPAUser
protected List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"leftEnd")
- @Valid
- protected List<JPAURelationship> relationships = new ArrayList<>();
+ protected List<@Valid JPAURelationship> relationships = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"leftEnd")
- @Valid
- protected List<JPAUMembership> memberships = new ArrayList<>();
+ protected List<@Valid JPAUMembership> memberships = new ArrayList<>();
@ManyToOne(fetch = FetchType.EAGER)
protected JPASecurityQuestion securityQuestion;
@@ -175,8 +173,7 @@ public class JPAUser
protected String mfa;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy =
"owner")
- @Valid
- protected List<JPALinkedAccount> linkedAccounts = new ArrayList<>();
+ protected List<@Valid JPALinkedAccount> linkedAccounts = new ArrayList<>();
protected Encryptor encryptor() {
return
ApplicationContextProvider.getApplicationContext().getBean(EncryptorManager.class).getInstance();
@@ -231,11 +228,11 @@ public class JPAUser
value,
Optional.ofNullable(cipherAlgorithm).
orElseGet(() -> CipherAlgorithm.valueOf(
-
ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).get(
- AuthContextUtils.getDomain(),
- StandardConfParams.PASSWORD_CIPHER_ALGORITHM,
- CipherAlgorithm.AES.name(),
- String.class))));
+
ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).get(
+ AuthContextUtils.getDomain(),
+
StandardConfParams.PASSWORD_CIPHER_ALGORITHM,
+ CipherAlgorithm.AES.name(),
+ String.class))));
}
@Override
@@ -519,7 +516,7 @@ public class JPAUser
public Optional<? extends LinkedAccount> getLinkedAccount(final String
resource, final String connObjectKeyValue) {
return linkedAccounts.stream().
filter(account ->
account.getResource().getKey().equals(resource)
- && account.getConnObjectKeyValue().equals(connObjectKeyValue)).
+ &&
account.getConnObjectKeyValue().equals(connObjectKeyValue)).
findFirst();
}
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java
index 1cd004a735..d5fe7b8c45 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java
@@ -33,7 +33,7 @@ import
org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
/**
* Container for common configuration options among all EntityManagerFactory
entities (one for each domain).
- * Acts as a commodity place for fetching each domain's {@link DataSource}..
+ * Acts as a commodity place for fetching each domain's {@link DataSource}.
*/
public class CommonEntityManagerFactoryConf implements
DomainHolder<DataSource> {
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java
index e1789bf58a..2f6549796c 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java
@@ -18,15 +18,10 @@
*/
package org.apache.syncope.core.persistence.jpa.spring;
-import jakarta.persistence.EntityManagerFactory;
-import jakarta.persistence.spi.PersistenceUnitInfo;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Optional;
-import javax.cache.Caching;
+import javax.cache.CacheManager;
import javax.cache.configuration.FactoryBuilder;
import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
-import javax.cache.event.CacheEntryListener;
import
org.apache.syncope.core.persistence.jpa.ConnectorManagerCacheEntryListener;
import org.apache.syncope.core.persistence.jpa.entity.JPAConnInstance;
import org.apache.syncope.core.persistence.jpa.entity.JPAExternalResource;
@@ -43,11 +38,11 @@ public class DomainEntityManagerFactoryBean extends
LocalContainerEntityManagerF
private static final long serialVersionUID = 49152547930966545L;
- protected final List<CacheEntryListener<Object, Object>>
cacheEntryListeners = new ArrayList<>();
+ protected final CacheManager cacheManager;
- protected ConnectorManagerCacheEntryListener
connectorManagerCacheEntryListener;
-
- protected ImplementationManagerCacheEntryListener
implementationManagerCacheEntryListener;
+ public DomainEntityManagerFactoryBean(final CacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
public void setCommonEntityManagerFactoryConf(final
CommonEntityManagerFactoryConf commonEMFConf) {
super.setJpaPropertyMap(commonEMFConf.getJpaPropertyMap());
@@ -62,42 +57,32 @@ public class DomainEntityManagerFactoryBean extends
LocalContainerEntityManagerF
}
public void setConnectorManagerCacheEntryListener(
+ final String domain,
final ConnectorManagerCacheEntryListener
connectorManagerCacheEntryListener) {
- this.connectorManagerCacheEntryListener =
connectorManagerCacheEntryListener;
+ Optional.ofNullable(cacheManager.getCache(
+ RegionNameQualifier.INSTANCE.qualify(domain,
JPAConnInstance.class.getName()))).
+ ifPresent(cache -> cache.registerCacheEntryListener(
+ new MutableCacheEntryListenerConfiguration<Object,
Object>(
+
FactoryBuilder.factoryOf(connectorManagerCacheEntryListener),
+ null, false, false)));
+ Optional.ofNullable(cacheManager.getCache(
+ RegionNameQualifier.INSTANCE.qualify(domain,
JPAExternalResource.class.getName()))).
+ ifPresent(cache -> cache.registerCacheEntryListener(
+ new MutableCacheEntryListenerConfiguration<Object,
Object>(
+
FactoryBuilder.factoryOf(connectorManagerCacheEntryListener),
+ null, false, false)));
}
public void setImplementationManagerCacheEntryListener(
+ final String domain,
final ImplementationManagerCacheEntryListener
implementationManagerCacheEntryListener) {
- this.implementationManagerCacheEntryListener =
implementationManagerCacheEntryListener;
- }
-
- @Override
- protected void postProcessEntityManagerFactory(final EntityManagerFactory
emf, final PersistenceUnitInfo pui) {
- super.postProcessEntityManagerFactory(emf, pui);
-
- Optional.ofNullable(Caching.getCachingProvider().getCacheManager().
- getCache(RegionNameQualifier.INSTANCE.qualify(
- pui.getPersistenceUnitName(),
JPAConnInstance.class.getName()))).
- ifPresent(cache -> cache.registerCacheEntryListener(
- new MutableCacheEntryListenerConfiguration<Object, Object>(
-
FactoryBuilder.factoryOf(connectorManagerCacheEntryListener),
- null, false, false)));
- Optional.ofNullable(Caching.getCachingProvider().getCacheManager().
- getCache(RegionNameQualifier.INSTANCE.qualify(
- pui.getPersistenceUnitName(),
JPAExternalResource.class.getName()))).
- ifPresent(cache -> cache.registerCacheEntryListener(
- new MutableCacheEntryListenerConfiguration<Object, Object>(
-
FactoryBuilder.factoryOf(connectorManagerCacheEntryListener),
- null, false, false)));
-
- Optional.ofNullable(Caching.getCachingProvider().getCacheManager().
- getCache(RegionNameQualifier.INSTANCE.qualify(
- pui.getPersistenceUnitName(),
JPAImplementation.class.getName()))).
+ Optional.ofNullable(cacheManager.getCache(
+ RegionNameQualifier.INSTANCE.qualify(domain,
JPAImplementation.class.getName()))).
ifPresent(cache -> cache.registerCacheEntryListener(
- new MutableCacheEntryListenerConfiguration<Object, Object>(
-
FactoryBuilder.factoryOf(implementationManagerCacheEntryListener),
- null, false, false)));
+ new MutableCacheEntryListenerConfiguration<Object,
Object>(
+
FactoryBuilder.factoryOf(implementationManagerCacheEntryListener),
+ null, false, false)));
}
}
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainRoutingEntityManagerFactory.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainRoutingEntityManagerFactory.java
index c7481ae408..f9c83a2a6c 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainRoutingEntityManagerFactory.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainRoutingEntityManagerFactory.java
@@ -37,6 +37,7 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
+import javax.cache.CacheManager;
import javax.sql.DataSource;
import org.apache.syncope.common.keymaster.client.api.model.JPADomain;
import org.apache.syncope.common.lib.SyncopeConstants;
@@ -90,23 +91,27 @@ public class DomainRoutingEntityManagerFactory implements
EntityManagerFactory,
public void master(
final PersistenceProperties props,
- final JndiObjectFactoryBean dataSource) {
+ final JndiObjectFactoryBean dataSource,
+ final CacheManager cacheManager) {
HibernateJpaVendorAdapter vendorAdapter = new
HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform(props.getDomain().getFirst().getDatabasePlatform());
- DomainEntityManagerFactoryBean emf = new
DomainEntityManagerFactoryBean();
+ DomainEntityManagerFactoryBean emf = new
DomainEntityManagerFactoryBean(cacheManager);
emf.setPersistenceUnitName(SyncopeConstants.MASTER_DOMAIN);
emf.setMappingResources(props.getDomain().getFirst().getOrm());
emf.setDataSource(Objects.requireNonNull((DataSource)
dataSource.getObject()));
emf.setJpaVendorAdapter(vendorAdapter);
emf.setCommonEntityManagerFactoryConf(commonEMFConf);
- emf.setConnectorManagerCacheEntryListener(new
ConnectorManagerCacheEntryListener(
- this, connectorManager, resourceDAO,
SyncopeConstants.MASTER_DOMAIN));
- emf.setImplementationManagerCacheEntryListener(new
ImplementationManagerCacheEntryListener(
- this, SyncopeConstants.MASTER_DOMAIN));
+ emf.setConnectorManagerCacheEntryListener(
+ SyncopeConstants.MASTER_DOMAIN,
+ new ConnectorManagerCacheEntryListener(
+ this, connectorManager, resourceDAO,
SyncopeConstants.MASTER_DOMAIN));
+ emf.setImplementationManagerCacheEntryListener(
+ SyncopeConstants.MASTER_DOMAIN,
+ new ImplementationManagerCacheEntryListener(this,
SyncopeConstants.MASTER_DOMAIN));
addToJpaPropertyMap(
emf,
@@ -121,23 +126,26 @@ public class DomainRoutingEntityManagerFactory implements
EntityManagerFactory,
public void domain(
final JPADomain domain,
- final DataSource dataSource) {
+ final DataSource dataSource,
+ final CacheManager cacheManager) {
HibernateJpaVendorAdapter vendorAdapter = new
HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform(domain.getDatabasePlatform());
- DomainEntityManagerFactoryBean emf = new
DomainEntityManagerFactoryBean();
+ DomainEntityManagerFactoryBean emf = new
DomainEntityManagerFactoryBean(cacheManager);
emf.setPersistenceUnitName(domain.getKey());
emf.setMappingResources(domain.getOrm());
emf.setDataSource(dataSource);
emf.setJpaVendorAdapter(vendorAdapter);
emf.setCommonEntityManagerFactoryConf(commonEMFConf);
- emf.setConnectorManagerCacheEntryListener(new
ConnectorManagerCacheEntryListener(
- this, connectorManager, resourceDAO, domain.getKey()));
- emf.setImplementationManagerCacheEntryListener(new
ImplementationManagerCacheEntryListener(
- this, domain.getKey()));
+ emf.setConnectorManagerCacheEntryListener(
+ domain.getKey(),
+ new ConnectorManagerCacheEntryListener(this, connectorManager,
resourceDAO, domain.getKey()));
+ emf.setImplementationManagerCacheEntryListener(
+ domain.getKey(),
+ new ImplementationManagerCacheEntryListener(this,
domain.getKey()));
addToJpaPropertyMap(emf, vendorAdapter, domain.getDbSchema(),
domain.getKey());
diff --git
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
index 89753aef2f..0fa5bc7e13 100644
---
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
+++
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
@@ -20,6 +20,8 @@ package org.apache.syncope.core.persistence.jpa;
import jakarta.persistence.EntityManagerFactory;
import java.io.IOException;
+import javax.cache.CacheManager;
+import javax.cache.Caching;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
@@ -126,6 +128,11 @@ public class PersistenceTestContext {
return new DefaultEncryptorManager(new DefaultCredentialChecker("",
"", "", "", false), securityProperties);
}
+ @Bean
+ public CacheManager cacheManager() {
+ return Caching.getCachingProvider().getCacheManager();
+ }
+
@Bean
public DomainRoutingEntityManagerFactory entityManagerFactory(
final PersistenceProperties props,
@@ -133,7 +140,8 @@ public class PersistenceTestContext {
final JndiObjectFactoryBean masterDataSource,
final CommonEntityManagerFactoryConf commonEMFConf,
final @Lazy ConnectorManager connectorManager,
- final @Lazy ExternalResourceDAO resourceDAO) {
+ final @Lazy ExternalResourceDAO resourceDAO,
+ final CacheManager cacheManager) {
DomainRoutingEntityManagerFactory emf = new
DomainRoutingEntityManagerFactory(
commonEMFConf, connectorManager, resourceDAO) {
@@ -145,7 +153,7 @@ public class PersistenceTestContext {
delegates.get(SyncopeConstants.MASTER_DOMAIN));
}
};
- emf.master(props, masterDataSource);
+ emf.master(props, masterDataSource, cacheManager);
return emf;
}
}
diff --git
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java
index 7c1174705d..4c8318e81a 100644
---
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java
+++
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java
@@ -74,8 +74,7 @@ public class Neo4jMacroTask extends Neo4jSchedTask implements
MacroTask {
commands, Neo4jMacroTaskCommandRelationship.builder());
@Relationship(type = MACRO_TASK_FORM_PROPERTY_DEF_REL, direction =
Relationship.Direction.INCOMING)
- @Valid
- private SortedSet<Neo4jFormPropertyDefRelationship> formPropertyDefs = new
TreeSet<>();
+ private SortedSet<@Valid Neo4jFormPropertyDefRelationship>
formPropertyDefs = new TreeSet<>();
@Transient
private List<Neo4jFormPropertyDef> sortedFormPropertyDefs = new
SortedSetList<>(
diff --git
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java
index e8a006974b..b57855ec00 100644
---
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java
+++
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java
@@ -145,8 +145,7 @@ public class Neo4jUser
protected String mfa;
@Relationship(direction = Relationship.Direction.INCOMING)
- @Valid
- protected List<Neo4jLinkedAccount> linkedAccounts = new ArrayList<>();
+ protected List<@Valid Neo4jLinkedAccount> linkedAccounts = new
ArrayList<>();
protected Encryptor encryptor() {
return
ApplicationContextProvider.getApplicationContext().getBean(EncryptorManager.class).getInstance();
@@ -206,11 +205,11 @@ public class Neo4jUser
value,
Optional.ofNullable(cipherAlgorithm).
orElseGet(() -> CipherAlgorithm.valueOf(
-
ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).get(
- AuthContextUtils.getDomain(),
- StandardConfParams.PASSWORD_CIPHER_ALGORITHM,
- CipherAlgorithm.AES.name(),
- String.class))));
+
ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).get(
+ AuthContextUtils.getDomain(),
+
StandardConfParams.PASSWORD_CIPHER_ALGORITHM,
+ CipherAlgorithm.AES.name(),
+ String.class))));
}
@Override
@@ -469,7 +468,7 @@ public class Neo4jUser
public Optional<? extends LinkedAccount> getLinkedAccount(final String
resource, final String connObjectKeyValue) {
return linkedAccounts.stream().
filter(account ->
account.getResource().getKey().equals(resource)
- && account.getConnObjectKeyValue().equals(connObjectKeyValue)).
+ &&
account.getConnObjectKeyValue().equals(connObjectKeyValue)).
findFirst();
}
diff --git a/core/pom.xml b/core/pom.xml
index af9ddb0d4c..73bca90cab 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -85,6 +85,7 @@ under the License.
<module>persistence-jpa</module>
<module>persistence-neo4j</module>
<module>spring</module>
+ <module>cache</module>
<module>provisioning-api</module>
<module>provisioning-java</module>
<module>workflow-api</module>
diff --git
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
index df72ccd74d..ae317dd8ea 100644
---
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
+++
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
@@ -32,19 +32,19 @@ public class DefaultCredentialChecker {
private static final Logger LOG =
LoggerFactory.getLogger(DefaultCredentialChecker.class);
private static final String DEFAULT_AES_KEY_ERROR_MESSAGE =
- "⚠ The default AES key property is being used. "
+ "⚠️ WARNING: The default AES key property is being used. "
+ "This must be changed to avoid a security breach!";
private static final String DEFAULT_JWS_KEY_ERROR_MESSAGE =
- "⚠ The default JWKS key property is being used. "
+ "⚠️ WARNING: The default JWKS key property is being used. "
+ "This must be changed to avoid a security breach!";
private static final String DEFAULT_ADMIN_PASSWORD_ERROR_MESSAGE =
- "⚠ The default adminPassword property is being used. "
+ "⚠️ WARNING: The default adminPassword property is being used. "
+ "This must be changed to avoid a security breach!";
private static final String DEFAULT_ANON_KEY_ERROR_MESSAGE =
- "⚠ The default anonymousKey property is being used. "
+ "⚠️ WARNING: The default anonymousKey property is being used. "
+ "This must be changed to avoid a security breach!";
private final boolean defaultAesKeyInUse;
diff --git
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AbstractThrottler.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AbstractThrottler.java
index 711df6540b..80593895e6 100644
---
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AbstractThrottler.java
+++
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AbstractThrottler.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.spring.security.throttle;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
-import java.util.function.LongSupplier;
import javax.cache.Cache;
import org.apache.syncope.core.spring.security.SecurityProperties;
@@ -29,8 +28,6 @@ abstract class AbstractThrottler {
protected final SecurityProperties.ThrottleProperties throttle;
- protected final LongSupplier clock = System::currentTimeMillis;
-
protected final Cache<String, ThrottlerAttempts> attempts;
protected AbstractThrottler(
@@ -48,6 +45,10 @@ abstract class AbstractThrottler {
&& throttle.getLockSeconds() > 0;
}
+ protected long now() {
+ return System.currentTimeMillis();
+ }
+
protected Deque<Long> prune(final Deque<Long> attempts, final long now) {
Deque<Long> failures = new ArrayDeque<>(attempts);
long threshold = now -
TimeUnit.SECONDS.toMillis(throttle.getWindowSeconds());
diff --git
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottler.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottler.java
index f725e0afba..0155bb66d7 100644
---
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottler.java
+++
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottler.java
@@ -49,25 +49,26 @@ public class AuthenticationThrottler extends
AbstractThrottler {
}
String key = key(domain, username);
- long now = clock.getAsLong();
- Long retryAfter = attempts.invoke(key, (entry, args) -> {
- if (!entry.exists()) {
- return null;
- }
-
- ThrottlerAttempts state = entry.getValue();
- if (state.blockedUntil() > now) {
- return retryAfterSeconds(state.blockedUntil(), now);
- }
+ long now = now();
- Deque<Long> failures = prune(state.failures(), now);
- if (failures.isEmpty()) {
- entry.remove();
+ Long retryAfter = null;
+ synchronized (attempts) {
+ ThrottlerAttempts state = attempts.get(key);
+ if (state == null) {
+ retryAfter = null;
} else {
- entry.setValue(new ThrottlerAttempts(failures,
state.blockedUntil()));
+ if (state.blockedUntil() > now) {
+ retryAfter = retryAfterSeconds(state.blockedUntil(), now);
+ } else {
+ Deque<Long> failures = prune(state.failures(), now);
+ if (failures.isEmpty()) {
+ attempts.remove(key);
+ } else {
+ attempts.put(key, new ThrottlerAttempts(failures,
state.blockedUntil()));
+ }
+ }
}
- return null;
- });
+ }
if (retryAfter != null) {
throw new AuthenticationThrottleException(retryAfter);
}
@@ -82,23 +83,27 @@ public class AuthenticationThrottler extends
AbstractThrottler {
return;
}
- long now = clock.getAsLong();
- Long retryAfter = attempts.invoke(key(domain, username), (entry, args)
-> {
- ThrottlerAttempts state = entry.exists()
- ? entry.getValue()
- : new ThrottlerAttempts();
+ String key = key(domain, username);
+ long now = now();
+
+ Long retryAfter = null;
+ synchronized (attempts) {
+ ThrottlerAttempts state = attempts.get(key);
+ if (state == null) {
+ state = new ThrottlerAttempts();
+ }
+
Deque<Long> failures = prune(state.failures(), now);
failures.addLast(now);
if (failures.size() >= throttle.getMaxAttempts()) {
long blockedUntil = now +
TimeUnit.SECONDS.toMillis(throttle.getLockSeconds());
- entry.setValue(new ThrottlerAttempts(failures, blockedUntil));
- return retryAfterSeconds(blockedUntil, now);
+ attempts.put(key, new ThrottlerAttempts(failures,
blockedUntil));
+ retryAfter = retryAfterSeconds(blockedUntil, now);
+ } else {
+ attempts.put(key, new ThrottlerAttempts(failures,
state.blockedUntil()));
}
-
- entry.setValue(new ThrottlerAttempts(failures,
state.blockedUntil()));
- return null;
- });
+ }
if (retryAfter != null) {
throw new AuthenticationThrottleException(retryAfter);
}
diff --git
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/PasswordResetRequestThrottler.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/PasswordResetRequestThrottler.java
index 9795cfae42..d811b78c78 100644
---
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/PasswordResetRequestThrottler.java
+++
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/throttle/PasswordResetRequestThrottler.java
@@ -60,48 +60,48 @@ public class PasswordResetRequestThrottler extends
AbstractThrottler {
return;
}
- long now = clock.getAsLong();
String attemptKey = key(domain, username, clientAddress);
String attemptKeyId = attemptKeyId(attemptKey);
- PasswordResetThrottleException blocked = attempts.invoke(
- attemptKey,
- (entry, args) -> {
- ThrottlerAttempts state = entry.exists()
- ? entry.getValue()
- : new ThrottlerAttempts();
+ long now = now();
- if (state.blockedUntil() > now) {
- PasswordResetThrottleException exception =
blocked(state.blockedUntil(), now);
- LOG.debug(
- "Password reset request throttled for attempt
key [{}]; retry after [{}] seconds",
- attemptKeyId,
- exception.getRetryAfterSeconds());
- return exception;
- }
+ PasswordResetThrottleException blocked = null;
+ synchronized (attempts) {
+ ThrottlerAttempts state = attempts.get(attemptKey);
+ if (state == null) {
+ state = new ThrottlerAttempts();
+ }
- Deque<Long> failures = prune(state.failures(), now);
- failures.addLast(now);
- if (failures.size() > throttle.getMaxAttempts()) {
- long blockedUntil = now +
TimeUnit.SECONDS.toMillis(throttle.getLockSeconds());
- entry.setValue(new ThrottlerAttempts(failures,
blockedUntil));
- LOG.warn(
- "Password reset request throttling activated
for attempt key [{}]; "
- + "attempts [{}], max attempts [{}], lock
seconds [{}]",
- attemptKeyId,
- failures.size(),
- throttle.getMaxAttempts(),
- throttle.getLockSeconds());
- return blocked(blockedUntil, now);
- }
+ if (state.blockedUntil() > now) {
+ blocked = blocked(state.blockedUntil(), now);
+ LOG.debug(
+ "Password reset request throttled for attempt key
[{}]; retry after [{}] seconds",
+ attemptKeyId,
+ blocked.getRetryAfterSeconds());
+ } else {
+ Deque<Long> failures = prune(state.failures(), now);
+ failures.addLast(now);
- entry.setValue(new ThrottlerAttempts(failures,
state.blockedUntil()));
+ if (failures.size() > throttle.getMaxAttempts()) {
+ long blockedUntil = now +
TimeUnit.SECONDS.toMillis(throttle.getLockSeconds());
+ attempts.put(attemptKey, new ThrottlerAttempts(failures,
blockedUntil));
+ LOG.warn(
+ "Password reset request throttling activated for
attempt key [{}]; "
+ + "attempts [{}], max attempts [{}], lock seconds
[{}]",
+ attemptKeyId,
+ failures.size(),
+ throttle.getMaxAttempts(),
+ throttle.getLockSeconds());
+ blocked = blocked(blockedUntil, now);
+ } else {
+ attempts.put(attemptKey, new ThrottlerAttempts(failures,
state.blockedUntil()));
LOG.trace(
"Password reset request failure recorded for
attempt key [{}]; attempts [{}/{}]",
attemptKeyId,
failures.size(),
throttle.getMaxAttempts());
- return null;
- });
+ }
+ }
+ }
if (blocked != null) {
throw blocked;
}
diff --git
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottlerTest.java
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottlerTest.java
index 8f2a0c1795..77bb80215a 100644
---
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottlerTest.java
+++
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/throttle/AuthenticationThrottlerTest.java
@@ -32,7 +32,6 @@ import javax.cache.expiry.TouchedExpiryPolicy;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.core.spring.security.SecurityProperties;
import org.junit.jupiter.api.Test;
-import org.springframework.test.util.ReflectionTestUtils;
class AuthenticationThrottlerTest {
@@ -61,8 +60,13 @@ class AuthenticationThrottlerTest {
cache.clear();
}
- AuthenticationThrottler throttler = new
AuthenticationThrottler(securityProperties, cache);
- ReflectionTestUtils.setField(throttler, "clock", clock);
+ AuthenticationThrottler throttler = new
AuthenticationThrottler(securityProperties, cache) {
+
+ @Override
+ protected long now() {
+ return clock.getAsLong();
+ }
+ };
return throttler;
}
diff --git a/core/starter/pom.xml b/core/starter/pom.xml
index c973d6c024..c22ba64a8d 100644
--- a/core/starter/pom.xml
+++ b/core/starter/pom.xml
@@ -58,10 +58,6 @@ under the License.
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
- <dependency>
- <groupId>com.github.ben-manes.caffeine</groupId>
- <artifactId>jcache</artifactId>
- </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
diff --git a/core/starter/src/main/resources/core.properties
b/core/starter/src/main/resources/core.properties
index 27c75d568e..55b64fe55a 100644
--- a/core/starter/src/main/resources/core.properties
+++ b/core/starter/src/main/resources/core.properties
@@ -45,8 +45,6 @@ service.discovery.address=http://localhost:8080/syncope/rest/
# acceptable values: POSTGRESQL | MYSQL | MARIADB | ORACLE
persistence.db-type=POSTGRESQL
-persistence.cacheProvider=com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
-
persistence.domain[0].key=Master
persistence.domain[0].jdbcDriver=org.postgresql.Driver
persistence.domain[0].jdbcURL=jdbc:postgresql://localhost:5432/syncope?stringtype=unspecified
diff --git
a/core/workflow-java/src/test/java/org/apache/syncope/core/workflow/java/WorkflowTestContext.java
b/core/workflow-java/src/test/java/org/apache/syncope/core/workflow/java/WorkflowTestContext.java
index 664db44d1d..678bf5c6c0 100644
---
a/core/workflow-java/src/test/java/org/apache/syncope/core/workflow/java/WorkflowTestContext.java
+++
b/core/workflow-java/src/test/java/org/apache/syncope/core/workflow/java/WorkflowTestContext.java
@@ -23,6 +23,8 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import java.time.OffsetDateTime;
+import javax.cache.CacheManager;
+import javax.cache.Caching;
import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
import org.apache.syncope.common.keymaster.client.api.DomainOps;
import org.apache.syncope.common.keymaster.client.api.model.JPADomain;
@@ -128,4 +130,9 @@ public class WorkflowTestContext {
public ConnectorManager connectorManager() {
return mock(ConnectorManager.class);
}
+
+ @Bean
+ public CacheManager cacheManager() {
+ return Caching.getCachingProvider().getCacheManager();
+ }
}
diff --git a/docker/core/pom.xml b/docker/core/pom.xml
index 8d61db9d16..77d4e3e905 100644
--- a/docker/core/pom.xml
+++ b/docker/core/pom.xml
@@ -111,6 +111,40 @@ under the License.
<version>${project.version}</version>
</dependency>
+ <!-- JCache providers -->
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${project.version}</version>
+ <classifier>wrap</classifier>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-hazelcast</artifactId>
+ <version>${project.version}</version>
+ <classifier>wrap</classifier>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-ehcache</artifactId>
+ <version>${project.version}</version>
+ <classifier>wrap</classifier>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-infinispan</artifactId>
+ <version>${project.version}</version>
+ <classifier>wrap</classifier>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
+
<!-- JDBC drivers -->
<dependency>
<groupId>org.postgresql</groupId>
@@ -172,6 +206,11 @@ under the License.
<copy
file="${settings.localRepository}/com/mysql/mysql-connector-j/${jdbc.mysql.version}/mysql-connector-j-${jdbc.mysql.version}.jar"
todir="${project.build.directory}/tmp/lib" overwrite="true"/>
<copy
file="${settings.localRepository}/org/mariadb/jdbc/mariadb-java-client/${jdbc.mariadb.version}/mariadb-java-client-${jdbc.mariadb.version}.jar"
todir="${project.build.directory}/tmp/lib" overwrite="true"/>
<copy
file="${settings.localRepository}/com/oracle/database/jdbc/ojdbc11/${jdbc.oracle.version}/ojdbc11-${jdbc.oracle.version}.jar"
todir="${project.build.directory}/tmp/lib" overwrite="true"/>
+
+ <copy
file="${settings.localRepository}/org/apache/syncope/core/cache/syncope-core-cache-caffeine/${project.version}/syncope-core-cache-caffeine-${project.version}-wrap.zip"
tofile="${project.build.directory}/tmp/lib/syncope-core-cache-caffeine-wrap.zip"
overwrite="true"/>
+ <copy
file="${settings.localRepository}/org/apache/syncope/core/cache/syncope-core-cache-ehcache/${project.version}/syncope-core-cache-ehcache-${project.version}-wrap.zip"
tofile="${project.build.directory}/tmp/lib/syncope-core-cache-ehcache-wrap.zip"
overwrite="true"/>
+ <copy
file="${settings.localRepository}/org/apache/syncope/core/cache/syncope-core-cache-hazelcast/${project.version}/syncope-core-cache-hazelcast-${project.version}-wrap.zip"
tofile="${project.build.directory}/tmp/lib/syncope-core-cache-hazelcast-wrap.zip"
overwrite="true"/>
+ <copy
file="${settings.localRepository}/org/apache/syncope/core/cache/syncope-core-cache-infinispan/${project.version}/syncope-core-cache-infinispan-${project.version}-wrap.zip"
tofile="${project.build.directory}/tmp/lib/syncope-core-cache-infinispan-wrap.zip"
overwrite="true"/>
</target>
</configuration>
<goals>
diff --git a/docker/core/src/main/resources/Dockerfile
b/docker/core/src/main/resources/Dockerfile
index 62c065d62f..e99b9a6e46 100644
--- a/docker/core/src/main/resources/Dockerfile
+++ b/docker/core/src/main/resources/Dockerfile
@@ -20,13 +20,14 @@ LABEL
org.opencontainers.image.authors="[email protected]"
RUN apk update && apk add bash
-RUN mkdir /opt/syncope /opt/syncope/bin /opt/syncope/bundles /opt/syncope/conf
/opt/syncope/lib /opt/syncope/log
+RUN mkdir /opt/syncope /opt/syncope/bin /opt/syncope/bundles /opt/syncope/conf
/opt/syncope/lib /opt/syncope/log /opt/syncope/cache
COPY *.properties *.xml saml.keystore.jks /opt/syncope/conf/
COPY bundles/*.jar /opt/syncope/bundles/
COPY lib/mariadb*.jar lib/mysql*jar lib/ojdbc*jar lib/postgresql*jar
/opt/syncope/lib/
+COPY lib/syncope-core-cache-*zip /opt/syncope/cache
COPY lib/syncope-docker-core-*jar /opt/syncope/lib/syncope.jar
ENV SPRING_PROFILES_ACTIVE=docker
diff --git a/docker/core/src/main/resources/core-docker.properties
b/docker/core/src/main/resources/core-docker.properties
index 2749e0994c..cbadd111ae 100644
--- a/docker/core/src/main/resources/core-docker.properties
+++ b/docker/core/src/main/resources/core-docker.properties
@@ -24,8 +24,6 @@ security.productionMode=${PRODUCTION_MODE:true}
security.anonymousUser=${ANONYMOUS_USER:anonymous}
security.anonymousKey=${ANONYMOUS_KEY:anonymousKey}
-persistence.cacheProvider=${HIBERNATE_JCACHE_PROVIDER}
-
spring.lifecycle.timeout-per-shutdown-phase=30s
spring.threads.virtual.enabled=true
diff --git a/docker/core/src/main/resources/startup.sh
b/docker/core/src/main/resources/startup.sh
index 3a552db7b0..09191582b6 100755
--- a/docker/core/src/main/resources/startup.sh
+++ b/docker/core/src/main/resources/startup.sh
@@ -17,4 +17,26 @@
# specific language governing permissions and limitations
# under the License.
+cd /opt/syncope/cache
+if [ $JCACHE = "ehcache" ]; then
+ mkdir ehcache && cd ehcache && unzip ../syncope-core-cache-ehcache-wrap.zip
+ LOADER_PATH="$LOADER_PATH,/opt/syncope/cache/ehcache"
+elif [[ $JCACHE == hazelcast* ]]; then
+ mkdir hazelcast && cd hazelcast && unzip
../syncope-core-cache-hazelcast-wrap.zip
+ LOADER_PATH="$LOADER_PATH,/opt/syncope/cache/hazelcast"
+
+ PROVIDER_TYPE="member"
+ if [ $JCACHE = "hazelcast_client" ]; then
+ PROVIDER_TYPE="client"
+ fi
+ JAVA_OPTS="$JAVA_OPTS -Dhazelcast.jcache.provider.type=$PROVIDER_TYPE
-Dhazelcast.logging.type=slf4j --add-modules java.se --add-exports
java.base/jdk.internal.ref=ALL-UNNAMED --add-opens
java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED --add-opens
jdk.management/com.sun.management.internal=ALL-UNNAMED"
+elif [ $JCACHE = "infinispan" ]; then
+ mkdir infinispan && cd infinispan && unzip
../syncope-core-cache-infinispan-wrap.zip
+ LOADER_PATH="$LOADER_PATH,/opt/syncope/cache/infinispan"
+else
+ mkdir caffeine && cd caffeine && unzip
../syncope-core-cache-caffeine-wrap.zip
+ LOADER_PATH="$LOADER_PATH,/opt/syncope/cache/caffeine"
+fi
+cd -
+
exec java $JAVA_OPTS -jar /opt/syncope/lib/syncope.jar
diff --git a/docker/src/main/resources/docker-compose/docker-compose-all.yml
b/docker/src/main/resources/docker-compose/docker-compose-all.yml
index 75f0feef1b..a69b11424f 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-all.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-all.yml
@@ -48,7 +48,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: keymaster:2181
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME:-}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD:-}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-ha.yml
b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
index 1897c0723d..840b412d72 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-ha.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
@@ -35,13 +35,13 @@ services:
- "18080:8080"
restart: always
environment:
+ JCACHE: hazelcast_member
SPRING_PROFILES_ACTIVE: docker,postgresql,saml2
DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
DB_USER: syncope
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER: tcp(Addresses=syncope1;syncope2)
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
@@ -57,13 +57,13 @@ services:
- "18081:8080"
restart: always
environment:
+ JCACHE: hazelcast_member
SPRING_PROFILES_ACTIVE: docker,postgresql
DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
DB_USER: syncope
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER: tcp(Addresses=syncope1;syncope2)
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git
a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
index cc2e5df6c2..866a91ea0e 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
@@ -43,7 +43,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
b/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
index eee9de85be..d464753b63 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
@@ -43,7 +43,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-oracle.yml
b/docker/src/main/resources/docker-compose/docker-compose-oracle.yml
index 00d72705bd..4255ae7746 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-oracle.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-oracle.yml
@@ -42,7 +42,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git
a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
index 4fbaf7e1ad..3329f76dc5 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
@@ -40,7 +40,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git
a/docker/src/main/resources/kubernetes/syncope/templates/syncope-deployment.yaml
b/docker/src/main/resources/kubernetes/syncope/templates/syncope-deployment.yaml
index 74efb05717..ebde7fd2fd 100644
---
a/docker/src/main/resources/kubernetes/syncope/templates/syncope-deployment.yaml
+++
b/docker/src/main/resources/kubernetes/syncope/templates/syncope-deployment.yaml
@@ -25,7 +25,7 @@ data:
DB_PASSWORD: {{.Values.syncopeEnvironment.userCreds}}
DB_POOL_MAX: "{{.Values.syncopeEnvironment.dbPoolMax}}"
DB_POOL_MIN: "{{.Values.syncopeEnvironment.dbPoolMin}}"
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
---
apiVersion: extensions/v1beta1
kind: Deployment
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 3650a0e83a..6525cf5be8 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -64,6 +64,12 @@ under the License.
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.syncope.core</groupId>
<artifactId>syncope-core-self-keymaster-starter</artifactId>
@@ -1223,10 +1229,6 @@ under the License.
<profile>
<id>payara-it</id>
- <properties>
- <spring.profiles.active>embedded,payara</spring.profiles.active>
- </properties>
-
<dependencies>
<dependency>
<groupId>org.apache.syncope.core</groupId>
@@ -1241,13 +1243,16 @@ under the License.
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</exclusion>
- <exclusion>
- <groupId>com.github.ben-manes.caffeine</groupId>
- <artifactId>jcache</artifactId>
- </exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.faces</artifactId>
diff --git a/fit/core-reference/src/main/resources/core-payara.properties
b/fit/core-reference/src/main/resources/core-payara.properties
deleted file mode 100644
index db449da933..0000000000
--- a/fit/core-reference/src/main/resources/core-payara.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-persistence.cacheProvider=com.hazelcast.cache.HazelcastCachingProvider
diff --git a/src/main/asciidoc/getting-started/obtain.adoc
b/src/main/asciidoc/getting-started/obtain.adoc
index 69e109a68d..8f28619353 100644
--- a/src/main/asciidoc/getting-started/obtain.adoc
+++ b/src/main/asciidoc/getting-started/obtain.adoc
@@ -102,10 +102,9 @@ Environment variables:
* `DB_PASSWORD`: password for internal storage authentication
* `DB_POOL_MAX`: internal storage connection pool: ceiling
* `DB_POOL_MIN`: internal storage connection pool: floor
-* `HIBERNATE_JCACHE_PROVIDER`: configure multiple instances, with high
availability; valid values are the ones accepted by
-Hibernate for
-https://docs.hibernate.org/orm/7.3/userguide/html_single/#caching-provider-jcache-cache-manager[JCache
CacheManager^]
-including the default value
`com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider` (single
instance)
+* `JCACHE`: configure
https://docs.hibernate.org/orm/7.4/userguide/html_single/#caching-provider-jcache-cache-manager[JCache
provider^]
+for Hibernate, defaults to https://github.com/ben-manes/caffeine[Caffeine^] if
no value is provided; allowed values:
+`caffeine|ehcache|hazelcast_client|hazelcast_member|infinispan`
===== Console
@@ -180,7 +179,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
KEYMASTER_USERNAME: ${ANONYMOUS_USER}
KEYMASTER_PASSWORD: ${ANONYMOUS_KEY}
@@ -265,7 +264,7 @@ services:
DB_PASSWORD: syncope
DB_POOL_MAX: 20
DB_POOL_MIN: 5
- HIBERNATE_JCACHE_PROVIDER:
com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
+ JCACHE: caffeine
KEYMASTER_ADDRESS: keymaster:2181
KEYMASTER_USERNAME: ${KEYMASTER_USERNAME:-}
KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD:-}
diff --git
a/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
b/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
index 328ce57ac7..65679d6c03 100644
--- a/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
@@ -23,12 +23,12 @@ certain <<policies-attribute-release,Attribute Release
Policy>>.
Some attribute repositories are provided:
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-JDBC.html[Database^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-LDAP.html[LDAP^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-Stub.html[Stub^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-Syncope.html[Syncope^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-AzureAD.html[Azure
Active Directory^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution-Okta.html[Okta^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-JDBC.html[Database^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-LDAP.html[LDAP^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-Stub.html[Stub^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-Syncope.html[Syncope^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-AzureAD.html[Azure
Active Directory^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution-Okta.html[Okta^]
[TIP]
====
@@ -51,4 +51,4 @@ class.
[NOTE]
Attribute Repositories are dynamically translated into
-https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution.html[CAS
Attribute Resolution^] configuration.
+https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution.html[CAS
Attribute Resolution^] configuration.
diff --git
a/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
b/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
index 4623370f6c..880826b3a3 100644
--- a/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
@@ -24,24 +24,24 @@ technology or repository, in the context of a certain
<<policies-authentication,
Several authentication modules are provided:
* Principal Authentication:
- **
https://apereo.github.io/cas/7.3.x/authentication/Database-Authentication.html[Database^]
- **
https://apereo.github.io/cas/7.3.x/authentication/JAAS-Authentication.html[JAAS^]
- **
https://apereo.github.io/cas/7.3.x/authentication/LDAP-Authentication.html[LDAP^]
- **
https://apereo.github.io/cas/7.3.x/authentication/SPNEGO-Authentication.html[SPNEGO^]
- **
https://apereo.github.io/cas/7.3.x/authentication/Syncope-Authentication.html[Syncope^]
- **
https://apereo.github.io/cas/7.3.x/authentication/Azure-ActiveDirectory-Authentication.html[Azure
Active Directory^]
- **
https://apereo.github.io/cas/7.3.x/authentication/Okta-Authentication.html[Okta^]
- **
https://apereo.github.io/cas/7.3.x/authentication/X509-Authentication.html[X509^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-Generic-OpenID-Connect.html[OpenID
Connect^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-OAuth20.html[OAuth2^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-SAML.htmll[SAML^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-Apple.html[Apple
Signin^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-Azure-AD.html[Azure
Active Directory (OIDC)^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-Google-OpenID-Connect.html[Google
OpenID^]
- **
https://apereo.github.io/cas/7.3.x/integration/Delegate-Authentication-Keycloak.html[Keycloak^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/Database-Authentication.html[Database^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/JAAS-Authentication.html[JAAS^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/LDAP-Authentication.html[LDAP^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/SPNEGO-Authentication.html[SPNEGO^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/Syncope-Authentication.html[Syncope^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/Azure-ActiveDirectory-Authentication.html[Azure
Active Directory^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/Okta-Authentication.html[Okta^]
+ **
https://apereo.github.io/cas/8.0.x/authentication/X509-Authentication.html[X509^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-Generic-OpenID-Connect.html[OpenID
Connect^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-OAuth20.html[OAuth2^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-SAML.htmll[SAML^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-Apple.html[Apple
Signin^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-Azure-AD.html[Azure
Active Directory (OIDC)^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-Google-OpenID-Connect.html[Google
OpenID^]
+ **
https://apereo.github.io/cas/8.0.x/integration/Delegate-Authentication-Keycloak.html[Keycloak^]
* MFA:
- **
https://apereo.github.io/cas/7.3.x/mfa/DuoSecurity-Authentication.html[Duo
Security^]
- **
https://apereo.github.io/cas/7.3.x/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator^]
+ **
https://apereo.github.io/cas/8.0.x/mfa/DuoSecurity-Authentication.html[Duo
Security^]
+ **
https://apereo.github.io/cas/8.0.x/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator^]
[TIP]
====
@@ -64,4 +64,4 @@ class.
[NOTE]
Authentication Modules are dynamically translated into
-https://apereo.github.io/cas/7.3.x/authentication/Configuring-Authentication-Components.html#authentication-handlers[CAS
Authentication Handlers^].
+https://apereo.github.io/cas/8.0.x/authentication/Configuring-Authentication-Components.html#authentication-handlers[CAS
Authentication Handlers^].
diff --git a/src/main/asciidoc/reference-guide/concepts/authprofile.adoc
b/src/main/asciidoc/reference-guide/concepts/authprofile.adoc
index d7e230e841..250bc1882a 100644
--- a/src/main/asciidoc/reference-guide/concepts/authprofile.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/authprofile.adoc
@@ -21,8 +21,8 @@
When users log into the <<client-applications,web applications>> integrated
with <<web-access,WA>>, the following
information is tracked for <<admin-console,administration>> and
<<enduser-application,self-management>>:
-*
https://apereo.github.io/cas/7.3.x/authentication/Surrogate-Authentication.html[Surrogate
Authentication^]
-*
https://apereo.github.io/cas/7.3.x/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator Authentication^]
-*
https://apereo.github.io/cas/7.3.x/mfa/Multifactor-TrustedDevice-Authentication.html[Multifactor
Authentication Trusted Devices^]
-*
https://apereo.github.io/cas/7.3.x/mfa/FIDO2-WebAuthn-Authentication.html[FIDO2
WebAuthn (Passkey) Multifactor Authentication^]
-*
https://apereo.github.io/cas/7.3.x/integration/Attribute-Release-Consent.html[Attribute
Consent^]
+*
https://apereo.github.io/cas/8.0.x/authentication/Surrogate-Authentication.html[Surrogate
Authentication^]
+*
https://apereo.github.io/cas/8.0.x/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator Authentication^]
+*
https://apereo.github.io/cas/8.0.x/mfa/Multifactor-TrustedDevice-Authentication.html[Multifactor
Authentication Trusted Devices^]
+*
https://apereo.github.io/cas/8.0.x/mfa/FIDO2-WebAuthn-Authentication.html[FIDO2
WebAuthn (Passkey) Multifactor Authentication^]
+*
https://apereo.github.io/cas/8.0.x/integration/Attribute-Release-Consent.html[Attribute
Consent^]
diff --git a/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
b/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
index 4a1156f077..f96f626504 100644
--- a/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
@@ -34,17 +34,17 @@ When defining a client application, the following
parameters shall be specified:
. name - regular expression to match requests
. description - optional textual description
. username attribute provider, mapping to
-https://apereo.github.io/cas/7.3.x/integration/Attribute-Release-PrincipalId-Attribute.html[CAS
Attribute-based Principal Id^]
+https://apereo.github.io/cas/8.0.x/integration/Attribute-Release-PrincipalId-Attribute.html[CAS
Attribute-based Principal Id^]
. <<policies-authentication,authentication policy>>
. <<policies-access,access policy>>
. <<policies-attribute-release,attribute release policy>>
. <<policies-ticket-expiration,ticket expiration policy>>
. additional properties
. logout type, mapping to
-https://apereo.github.io/cas/7.3.x/installation/Logout-Single-Signout.html#slo-requests[the
equivalent CAS setting^]
+https://apereo.github.io/cas/8.0.x/installation/Logout-Single-Signout.html#slo-requests[the
equivalent CAS setting^]
More parameters are required to be specified depending on the actual client
application type.
[NOTE]
Client Applications are dynamically translated into
-https://apereo.github.io/cas/7.3.x/services/Service-Management.html[CAS
Services^].
+https://apereo.github.io/cas/8.0.x/services/Service-Management.html[CAS
Services^].
diff --git a/src/main/asciidoc/reference-guide/concepts/domains.adoc
b/src/main/asciidoc/reference-guide/concepts/domains.adoc
index 3eea561038..379cbe2964 100644
--- a/src/main/asciidoc/reference-guide/concepts/domains.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/domains.adoc
@@ -27,7 +27,7 @@ External Resources, Policies, Tasks, etc. from different
domains (e.g. tenants)
By default, a single `Master` domain is defined, which also bears the
configuration for additional domains.
Every domain besides `Master` is mapped one-to-one with a
-https://apereo.github.io/cas/7.3.x/multitenancy/Multitenancy-Overview.html[CAS
tenant^] having the same identifier; this
+https://apereo.github.io/cas/8.0.x/multitenancy/Multitenancy-Overview.html[CAS
tenant^] having the same identifier; this
allows for <<web-access>> configuration to relate only to the given domain's
database instance.
[.text-center]
diff --git a/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc
b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc
index 5807ed49ca..e44ef78fc6 100644
--- a/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc
@@ -23,10 +23,10 @@ according to rules defined by a single configured password
management module (on
Some password management modules are provided:
-*
https://apereo.github.io/cas/7.3.x/password_management/Password-Management-LDAP.html[LDAP^]
-*
https://apereo.github.io/cas/7.3.x/password_management/Password-Management-JDBC.html[JDBC^]
-*
https://apereo.github.io/cas/7.3.x/password_management/Password-Management-REST.html[REST^]
-*
https://apereo.github.io/cas/7.3.x/password_management/Password-Management-ApacheSyncope.html[Syncope^]
+*
https://apereo.github.io/cas/8.0.x/password_management/Password-Management-LDAP.html[LDAP^]
+*
https://apereo.github.io/cas/8.0.x/password_management/Password-Management-JDBC.html[JDBC^]
+*
https://apereo.github.io/cas/8.0.x/password_management/Password-Management-REST.html[REST^]
+*
https://apereo.github.io/cas/8.0.x/password_management/Password-Management-ApacheSyncope.html[Syncope^]
[TIP]
====
@@ -49,4 +49,4 @@ class.
[NOTE]
Password Management is dynamically translated into
-https://apereo.github.io/cas/7.3.x/password_management/Password-Management.html[CAS
Password Management^] configuration.
+https://apereo.github.io/cas/8.0.x/password_management/Password-Management.html[CAS
Password Management^] configuration.
diff --git a/src/main/asciidoc/reference-guide/concepts/policies.adoc
b/src/main/asciidoc/reference-guide/concepts/policies.adoc
index dd84c70dfb..2d3ae151b2 100644
--- a/src/main/asciidoc/reference-guide/concepts/policies.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/policies.adoc
@@ -329,7 +329,7 @@ endif::[]
[NOTE]
Access Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.3.x/services/Configuring-Service-Access-Strategy.html#configure-service-access-strategy[CAS
Service Access Strategy^].
+https://apereo.github.io/cas/8.0.x/services/Configuring-Service-Access-Strategy.html#configure-service-access-strategy[CAS
Service Access Strategy^].
[[policies-attribute-release]]
==== Attribute Release
@@ -341,7 +341,7 @@ values.
[NOTE]
Attribute Release Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.3.x/integration/Attribute-Release-Policies.html#attribute-release-policies[CAS
Attribute Release Policy^].
+https://apereo.github.io/cas/8.0.x/integration/Attribute-Release-Policies.html#attribute-release-policies[CAS
Attribute Release Policy^].
[[policies-authentication]]
==== Authentication
@@ -368,7 +368,7 @@ be considered successful.
[NOTE]
Authentication Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.3.x/authentication/Configuring-Authentication-Policy.html#authentication-policy[CAS
Authentication Policy^].
+https://apereo.github.io/cas/8.0.x/authentication/Configuring-Authentication-Policy.html#authentication-policy[CAS
Authentication Policy^].
[[policies-propagation]]
==== Propagation
@@ -487,4 +487,4 @@ Ticket Expiration policies control the duration of various
types of WA sessions.
[NOTE]
Ticket Expiration Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.3.x/ticketing/Configuring-Ticket-Expiration-Policy.html[their
CAS equivalent^].
+https://apereo.github.io/cas/8.0.x/ticketing/Configuring-Ticket-Expiration-Policy.html[their
CAS equivalent^].
diff --git
a/src/main/asciidoc/reference-guide/configuration/highavailability.adoc
b/src/main/asciidoc/reference-guide/configuration/highavailability.adoc
index 101ff82ae8..5000cfc488 100644
--- a/src/main/asciidoc/reference-guide/configuration/highavailability.adoc
+++ b/src/main/asciidoc/reference-guide/configuration/highavailability.adoc
@@ -21,31 +21,86 @@
==== Core HA
When deploying multiple Syncope <<core>> instances with a single database or
database cluster, it is of
-fundamental importance that the
https://docs.hibernate.org/orm/7.3/userguide/html_single/#caching[second-level
cache^]
+fundamental importance that the
https://docs.hibernate.org/orm/7.4/userguide/html_single/#caching[second-level
cache^]
is correctly configured for Hibernate ORM.
Such configuration, in fact, allows the Hibernate ORM cache to remain
synchronized across multiple JVMs, thus
enforcing data consistency across all Syncope Core instances.
-The default configuration in `core.properties` is
+The supported https://github.com/jsr107/jsr107spec[JCache^] provider is
configured according to the implementation found
+in the classpath.
-[source]
-....
-persistence.cacheProvider=com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider
-....
+[WARNING]
+Ensure to define only one of the following providers to avoid conflicts.
-which is suited for single JVM installations; with multiple instances, more
options are available depending on the
-configured https://github.com/jsr107/jsr107spec[JCache^] implementation, such
as, for example,
-https://docs.hazelcast.com/hazelcast/5.6/jcache/overview[Hazelcast^],
-https://www.ehcache.org/documentation/3.0/107.html[Ehcache],
-https://infinispan.org/docs/stable/titles/hibernate/hibernate.html[Infinispan^]
or
-https://ignite.apache.org/[Apache Ignite^].
+[core-ha-caffeine]
+===== Caffeine
-Additional, implementation-specific configuration files can be set up via
`persistence.cacheURI`.
+By default, the following dependency is set in `core/pom.xml`.
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+[WARNING]
+https://github.com/ben-manes/caffeine[Caffeine^] does support only single JVM
installations.
+
+[core-ha-ehcache]
+===== Ehcache
+
+Set the following dependency is in `core/pom.xml` to enable
https://www.ehcache.org/documentation/3.11/107.html[Ehcache^]:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-caffeine</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+[TIP]
+Adding `ehcache.xml` in the classpath will allow to fine-tune Ehcache's
https://www.ehcache.org/documentation/3.11/xml.html[configuration^].
+
+[core-ha-hazelcast]
+===== Hazelcast
+
+Set the following dependency is in `core/pom.xml` to enable
https://docs.hazelcast.com/hazelcast/5.7/jcache/overview[Hazelcast^]:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-hazelcast</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+[TIP]
+Adding `hazelcast.xml` in the classpath will allow to fine-tune Hazelcast's
https://docs.hazelcast.com/hazelcast/5.7/configuration/understanding-configuration[configuration^].
+
+[core-ha-infinispan]
+===== Infinispan
+
+Set the following dependency is in `core/pom.xml` to enable
https://infinispan.org/docs/stable/titles/embedding/embedding.html[Infinispan^]:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.core.cache</groupId>
+ <artifactId>syncope-core-cache-infinispan</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
==== WA HA
When multiple Syncope <<web-access>> instances are needed to support
authentication and authorization requirements,
-a distributed
https://apereo.github.io/cas/7.3.x/ticketing/Configuring-Ticketing-Components.html#ticket-registry[Ticket
Registry^]
+a distributed
https://apereo.github.io/cas/8.0.x/ticketing/Configuring-Ticketing-Components.html#ticket-registry[Ticket
Registry^]
is required, such has the ones based on
-https://apereo.github.io/cas/7.3.x/ticketing/Hazelcast-Ticket-Registry.html[Hazelcast^]
-or
https://apereo.github.io/cas/7.3.x/ticketing/Ignite-Ticket-Registry.html[Apache
Ignite^].
+https://apereo.github.io/cas/8.0.x/ticketing/Hazelcast-Ticket-Registry.html[Hazelcast^]
+or
https://apereo.github.io/cas/8.0.x/ticketing/Ignite-Ticket-Registry.html[Apache
Ignite^].
diff --git a/src/main/asciidoc/reference-guide/usage/actuator.adoc
b/src/main/asciidoc/reference-guide/usage/actuator.adoc
index 478b348d1e..10b8eeda8d 100644
--- a/src/main/asciidoc/reference-guide/usage/actuator.adoc
+++ b/src/main/asciidoc/reference-guide/usage/actuator.adoc
@@ -40,7 +40,7 @@ The pre-defined `health` endpoint is typically used for
liveness and readiness p
|===
| `entityCache`
-a| Allows to work with
https://docs.hibernate.org/orm/7.3/userguide/html_single/#caching-statistics[JPA
cache statistics^]
+a| Allows to work with
https://docs.hibernate.org/orm/7.4/userguide/html_single/#caching-statistics[JPA
cache statistics^]
* `GET` - shows JPA cache statistics
* `POST {ENABLE,DISABLE,RESET}` - performs the requested operation onto JPA
cache
@@ -60,15 +60,15 @@ a| Allows to work with the various jobs defined after
<<tasks>> and <<reports>>.
|===
| `ssoSessions`
-|
https://apereo.github.io/cas/7.3.x/authentication/Configuring-SSO.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/8.0.x/authentication/Configuring-SSO.html#actuator-endpoints[More
details^]
| `registeredServices`
-|
https://apereo.github.io/cas/7.3.x/services/Service-Management.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/8.0.x/services/Service-Management.html#actuator-endpoints[More
details^]
| `authenticationHandlers`
-|
https://apereo.github.io/cas/7.3.x/authentication/Configuring-Authentication-Components.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/8.0.x/authentication/Configuring-Authentication-Components.html#actuator-endpoints[More
details^]
| `authenticationPolicies`
-|
https://apereo.github.io/cas/7.3.x/authentication/Configuring-Authentication-Policy.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/8.0.x/authentication/Configuring-Authentication-Policy.html#actuator-endpoints[More
details^]
| `resolveAttributes`
-|
https://apereo.github.io/cas/7.3.x/integration/Attribute-Resolution.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/8.0.x/integration/Attribute-Resolution.html#actuator-endpoints[More
details^]
|===
diff --git a/src/main/asciidoc/reference-guide/usage/customization.adoc
b/src/main/asciidoc/reference-guide/usage/customization.adoc
index f46742a142..1280b54186 100644
--- a/src/main/asciidoc/reference-guide/usage/customization.adoc
+++ b/src/main/asciidoc/reference-guide/usage/customization.adoc
@@ -275,7 +275,7 @@ components:
===== Customize Hibernate ORM settings
Hibernate ORM is at the core of the <<persistence,persistence>> layer; its
configuration can be tweaked under several
-aspects - including
https://docs.hibernate.org/orm/7.3/userguide/html_single/#caching[caching^] for
+aspects - including
https://docs.hibernate.org/orm/7.4/userguide/html_single/#caching[caching^] for
example, to best suit the various environments.
The main configuration classes are:
diff --git a/src/main/asciidoc/reference-guide/usage/metrics.adoc
b/src/main/asciidoc/reference-guide/usage/metrics.adoc
index 01baccff3d..c3137f6945 100644
--- a/src/main/asciidoc/reference-guide/usage/metrics.adoc
+++ b/src/main/asciidoc/reference-guide/usage/metrics.adoc
@@ -52,4 +52,4 @@ This can be enabled by adding the following dependency to
`wa/pom.xml`:
</dependency>
----
-For further options and configuration, refer to
https://apereo.github.io/cas/7.3.x/monitoring/Configuring-Metrics.html[CAS
documentation^].
+For further options and configuration, refer to
https://apereo.github.io/cas/8.0.x/monitoring/Configuring-Metrics.html[CAS
documentation^].