Map Storage JPA fixes

---
Quarkus3 branch sync no. 6 (17.2.2023)
Resolved conflicts:
keycloak/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java - Modified
---
Quarkus3 branch sync no. 3 (27.1.2023)
Resolved conflicts:
keycloak/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java - Modified
This commit is contained in:
Stefan Guilhen 2023-01-06 11:18:29 -03:00 committed by Václav Muzikář
parent ab6ca6e63d
commit 3111ef0085
26 changed files with 104 additions and 7 deletions

View file

@ -412,6 +412,8 @@ public class JpaMapStorageProviderFactory implements
properties.put("hibernate.show_sql", config.getBoolean("showSql", false)); properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
properties.put("hibernate.format_sql", config.getBoolean("formatSql", true)); properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
properties.put("hibernate.dialect", config.get("driverDialect")); properties.put("hibernate.dialect", config.get("driverDialect"));
// metadata contributor to register the json type
properties.put("hibernate.metadata_builder_contributor", "org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbMetadataBuilderContributor");
Long lockTimeout = config.getLong("lockTimeout", DEFAULT_LOCK_TIMEOUT); Long lockTimeout = config.getLong("lockTimeout", DEFAULT_LOCK_TIMEOUT);
if (lockTimeout >= 0) { if (lockTimeout >= 0) {
// This property does not work for PostgreSQL/CockroachDB - https://hibernate.atlassian.net/browse/HHH-16181 // This property does not work for PostgreSQL/CockroachDB - https://hibernate.atlassian.net/browse/HHH-16181
@ -423,12 +425,6 @@ public class JpaMapStorageProviderFactory implements
// Pass on the property to 'EventListenerIntegrator' to activate the necessary event listeners for JPA map storage // Pass on the property to 'EventListenerIntegrator' to activate the necessary event listeners for JPA map storage
properties.put(EventListenerIntegrator.JPA_MAP_STORAGE_ENABLED, Boolean.TRUE.toString()); properties.put(EventListenerIntegrator.JPA_MAP_STORAGE_ENABLED, Boolean.TRUE.toString());
// register custom jsonb type
ServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().build();
MetadataSources sources = new MetadataSources(standardRegistry);
MetadataBuilder metadataBuilder = sources.getMetadataBuilder();
metadataBuilder.applyBasicType(JsonbType.INSTANCE);
logger.trace("Creating EntityManagerFactory"); logger.trace("Creating EntityManagerFactory");
ParsedPersistenceXmlDescriptor descriptor = PersistenceXmlParser.locateIndividualPersistenceUnit( ParsedPersistenceXmlDescriptor descriptor = PersistenceXmlParser.locateIndividualPersistenceUnit(
JpaMapStorageProviderFactory.class.getClassLoader() JpaMapStorageProviderFactory.class.getClassLoader()

View file

@ -39,4 +39,7 @@ public class JpaAuthenticationSessionMetadata extends MapAuthenticationSessionEn
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -39,4 +39,7 @@ public class JpaRootAuthenticationSessionMetadata extends MapRootAuthenticationS
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaPermissionMetadata extends MapPermissionTicketEntityImpl impleme
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaPolicyMetadata extends MapPolicyEntityImpl implements Serializab
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaResourceMetadata extends MapResourceEntityImpl implements Serial
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaResourceServerMetadata extends MapResourceServerEntityImpl imple
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaScopeMetadata extends MapScopeEntityImpl implements Serializable
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaClientMetadata extends MapClientEntityImpl implements Serializab
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaClientScopeMetadata extends MapClientScopeEntityImpl implements
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaAdminEventMetadata extends MapAdminEventEntityImpl implements Se
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaAuthEventMetadata extends MapAuthEventEntityImpl implements Seri
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaGroupMetadata extends MapGroupEntityImpl implements Serializable
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -0,0 +1,39 @@
/*
* Copyright 2023 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.
*/
package org.keycloak.models.map.storage.jpa.hibernate.jsonb;
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.spi.MetadataBuilderContributor;
import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.function.PatternBasedSqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
/**
* A {@link MetadataBuilderContributor} to register JSONB types/functions.
*/
public class JsonbMetadataBuilderContributor implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applyBasicType(JsonbType.INSTANCE);
metadataBuilder.applySqlFunction("->>", new PatternBasedSqmFunctionDescriptor(
new PatternRenderer("?1->>?2"), StandardArgumentsValidators.exactly(2), null, null, "->>",
FunctionKind.NORMAL, null
));
}
}

View file

@ -227,15 +227,20 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> imp
try { try {
ObjectNode tree = MAPPER.readValue(json.toString(), ObjectNode.class); ObjectNode tree = MAPPER.readValue(json.toString(), ObjectNode.class);
JsonNode ev = tree.get("entityVersion"); JsonNode ev = tree.get("entityVersion");
JsonNode mc = tree.get("metadataClass");
if (ev == null || ! ev.isInt()) throw new IllegalArgumentException("unable to read entity version from " + json); if (ev == null || ! ev.isInt()) throw new IllegalArgumentException("unable to read entity version from " + json);
Integer entityVersion = ev.asInt(); Integer entityVersion = ev.asInt();
tree = migrate(tree, entityVersion); tree = migrate(tree, entityVersion);
String metadataClass = mc.asText();
valueType = Class.forName(metadataClass);
return MAPPER.treeToValue(tree, valueType); return MAPPER.treeToValue(tree, valueType);
} catch (IOException e) { } catch (IOException e) {
throw new HibernateException("unable to read", e); throw new HibernateException("unable to read", e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} }
} }

View file

@ -45,4 +45,7 @@ public class JpaUserLoginFailureMetadata extends MapUserLoginFailureEntityImpl i
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaComponentMetadata extends MapComponentEntityImpl implements Seri
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,6 @@ public class JpaRealmMetadata extends MapRealmEntityImpl implements Serializable
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaRoleMetadata extends MapRoleEntityImpl implements Serializable {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaSingleUseObjectMetadata extends MapSingleUseObjectEntityImpl imp
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaUserConsentMetadata extends MapUserConsentEntityImpl implements
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -45,4 +45,7 @@ public class JpaUserFederatedIdentityMetadata extends MapUserFederatedIdentityEn
public void setEntityVersion(Integer entityVersion) { public void setEntityVersion(Integer entityVersion) {
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -54,4 +54,7 @@ public class JpaUserMetadata extends MapUserEntityImpl implements Serializable {
public String getUsernameWithCase() { public String getUsernameWithCase() {
return this.usernameWithCase; return this.usernameWithCase;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaClientSessionMetadata extends MapAuthenticatedClientSessionEntit
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -40,4 +40,6 @@ public class JpaUserSessionMetadata extends MapUserSessionEntityImpl implements
this.entityVersion = entityVersion; this.entityVersion = entityVersion;
} }
private String metadataClass = this.getClass().getCanonicalName();
} }

View file

@ -16,7 +16,10 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="keycloak-default"> <persistence-unit name="keycloak-default">
<!--auth-sessions--> <!--auth-sessions-->
<class>org.keycloak.models.map.storage.jpa.authSession.entity.JpaRootAuthenticationSessionEntity</class> <class>org.keycloak.models.map.storage.jpa.authSession.entity.JpaRootAuthenticationSessionEntity</class>