Merge pull request #3561 from glavoie/KEYCLOAK-3990
KEYCLOAK-3990: Very slow use of NamedQueries.
This commit is contained in:
commit
684689d40d
15 changed files with 302 additions and 330 deletions
|
@ -29,18 +29,20 @@ import org.keycloak.models.jpa.entities.ClientEntity;
|
|||
import org.keycloak.models.jpa.entities.ClientTemplateEntity;
|
||||
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -222,7 +224,7 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
Set<RoleModel> roleMappings = getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<>();
|
||||
|
@ -240,47 +242,22 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
|||
|
||||
@Override
|
||||
public Set<RoleModel> getScopeMappings() {
|
||||
TypedQuery<String> query = em.createNamedQuery("clientScopeMappingIds", String.class);
|
||||
query.setParameter("client", getEntity());
|
||||
List<String> ids = query.getResultList();
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (String roleId : ids) {
|
||||
RoleModel role = realm.getRoleById(roleId);
|
||||
if (role == null) continue;
|
||||
roles.add(role);
|
||||
}
|
||||
return roles;
|
||||
return getEntity().getScopeMapping().stream()
|
||||
.map(RoleEntity::getId)
|
||||
.map(realm::getRoleById)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addScopeMapping(RoleModel role) {
|
||||
Set<RoleModel> roles = getScopeMappings();
|
||||
if (roles.contains(role)) return;
|
||||
ScopeMappingEntity entity = new ScopeMappingEntity();
|
||||
entity.setClient(getEntity());
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
entity.setRole(roleEntity);
|
||||
em.persist(entity);
|
||||
em.flush();
|
||||
em.detach(entity);
|
||||
getEntity().getScopeMapping().add(roleEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteScopeMapping(RoleModel role) {
|
||||
TypedQuery<ScopeMappingEntity> query = getRealmScopeMappingQuery(role);
|
||||
List<ScopeMappingEntity> results = query.getResultList();
|
||||
if (results.size() == 0) return;
|
||||
for (ScopeMappingEntity entity : results) {
|
||||
em.remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
protected TypedQuery<ScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
|
||||
TypedQuery<ScopeMappingEntity> query = em.createNamedQuery("hasScope", ScopeMappingEntity.class);
|
||||
query.setParameter("client", getEntity());
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
query.setParameter("role", roleEntity);
|
||||
return query;
|
||||
getEntity().getScopeMapping().remove(RoleAdapter.toRoleEntity(role, em));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -689,7 +666,6 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
|||
}
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
entities.add(roleEntity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.util.HashSet;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -133,14 +134,6 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
|
||||
int num = em.createNamedQuery("deleteGroupRoleMappingsByRealm")
|
||||
.setParameter("realm", realm).executeUpdate();
|
||||
num = em.createNamedQuery("deleteGroupAttributesByRealm")
|
||||
.setParameter("realm", realm).executeUpdate();
|
||||
num = em.createNamedQuery("deleteGroupsByRealm")
|
||||
.setParameter("realm", realm).executeUpdate();
|
||||
num = em.createNamedQuery("deleteComponentConfigByRealm")
|
||||
.setParameter("realm", realm).executeUpdate();
|
||||
num = em.createNamedQuery("deleteComponentByRealm")
|
||||
.setParameter("realm", realm).executeUpdate();
|
||||
|
||||
TypedQuery<String> query = em.createNamedQuery("getClientIdsByRealm", String.class);
|
||||
query.setParameter("realm", realm.getId());
|
||||
|
@ -228,7 +221,6 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
roleEntity.setClientRole(true);
|
||||
roleEntity.setRealmId(realm.getId());
|
||||
em.persist(roleEntity);
|
||||
em.flush();
|
||||
RoleAdapter adapter = new RoleAdapter(session, realm, em, roleEntity);
|
||||
return adapter;
|
||||
}
|
||||
|
@ -281,10 +273,11 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
RoleEntity roleEntity = em.getReference(RoleEntity.class, role.getId());
|
||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
|
||||
em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
||||
realm.getClients().forEach(c -> c.deleteScopeMapping(role));
|
||||
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
||||
int val = em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
|
||||
|
||||
em.flush();
|
||||
em.remove(roleEntity);
|
||||
|
||||
session.getKeycloakSessionFactory().publish(new RoleContainerModel.RoleRemovedEvent() {
|
||||
|
@ -337,27 +330,23 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
|
||||
@Override
|
||||
public List<GroupModel> getGroups(RealmModel realm) {
|
||||
List<String> groups = em.createNamedQuery("getAllGroupIdsByRealm", String.class)
|
||||
.setParameter("realm", realm.getId()).getResultList();
|
||||
if (groups == null) return Collections.EMPTY_LIST;
|
||||
List<GroupModel> list = new LinkedList<>();
|
||||
for (String id : groups) {
|
||||
list.add(session.realms().getGroupById(id, realm));
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
RealmEntity ref = em.getReference(RealmEntity.class, realm.getId());
|
||||
|
||||
return ref.getGroups().stream()
|
||||
.map(g -> session.realms().getGroupById(g.getId(), realm))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> getTopLevelGroups(RealmModel realm) {
|
||||
List<String> groups = em.createNamedQuery("getTopLevelGroupIds", String.class)
|
||||
.setParameter("realm", realm.getId())
|
||||
.getResultList();
|
||||
if (groups == null) return Collections.EMPTY_LIST;
|
||||
List<GroupModel> list = new LinkedList<>();
|
||||
for (String id : groups) {
|
||||
list.add(session.realms().getGroupById(id, realm));
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
RealmEntity ref = em.getReference(RealmEntity.class, realm.getId());
|
||||
|
||||
return ref.getGroups().stream()
|
||||
.filter(g -> g.getParent() == null)
|
||||
.map(g -> session.realms().getGroupById(g.getId(), realm))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -377,9 +366,11 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
if (!groupEntity.getRealm().getId().equals(realm.getId())) {
|
||||
return false;
|
||||
}
|
||||
// I don't think we need this as GroupEntity has cascade removal. It causes batch errors if you turn this on.
|
||||
// em.createNamedQuery("deleteGroupAttributesByGroup").setParameter("group", groupEntity).executeUpdate();
|
||||
em.createNamedQuery("deleteGroupRoleMappingsByGroup").setParameter("group", groupEntity).executeUpdate();
|
||||
|
||||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||
realmEntity.getGroups().remove(groupEntity);
|
||||
|
||||
em.remove(groupEntity);
|
||||
return true;
|
||||
|
||||
|
@ -401,6 +392,7 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||
groupEntity.setRealm(realmEntity);
|
||||
em.persist(groupEntity);
|
||||
realmEntity.getGroups().add(groupEntity);
|
||||
|
||||
GroupAdapter adapter = new GroupAdapter(realm, em, groupEntity);
|
||||
return adapter;
|
||||
|
@ -494,9 +486,6 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
|
||||
ClientEntity clientEntity = ((ClientAdapter)client).getEntity();
|
||||
|
||||
em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
|
||||
em.flush();
|
||||
|
||||
session.getKeycloakSessionFactory().publish(new RealmModel.ClientRemovedEvent() {
|
||||
@Override
|
||||
public ClientModel getClient() {
|
||||
|
|
|
@ -58,7 +58,6 @@ import org.keycloak.models.utils.ComponentUtil;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -68,7 +67,10 @@ import java.util.Iterator;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -1375,16 +1377,10 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public List<AuthenticationFlowModel> getAuthenticationFlows() {
|
||||
TypedQuery<AuthenticationFlowEntity> query = em.createNamedQuery("getAuthenticationFlowsByRealm", AuthenticationFlowEntity.class);
|
||||
query.setParameter("realm", realm);
|
||||
List<AuthenticationFlowEntity> flows = query.getResultList();
|
||||
if (flows.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<AuthenticationFlowModel> models = new LinkedList<>();
|
||||
for (AuthenticationFlowEntity entity : flows) {
|
||||
AuthenticationFlowModel model = entityToModel(entity);
|
||||
models.add(model);
|
||||
}
|
||||
return Collections.unmodifiableList(models);
|
||||
return realm.getAuthenticationFlows().stream()
|
||||
.map(this::entityToModel)
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1461,26 +1457,20 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
entity.setRealm(realm);
|
||||
realm.getAuthenticationFlows().add(entity);
|
||||
em.persist(entity);
|
||||
em.flush();
|
||||
model.setId(entity.getId());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||
TypedQuery<AuthenticationExecutionEntity> query = em.createNamedQuery("getAuthenticationExecutionsByFlow", AuthenticationExecutionEntity.class);
|
||||
AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
|
||||
query.setParameter("realm", realm);
|
||||
query.setParameter("parentFlow", flow);
|
||||
List<AuthenticationExecutionEntity> queryResult = query.getResultList();
|
||||
if (queryResult.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<AuthenticationExecutionModel> executions = new LinkedList<>();
|
||||
for (AuthenticationExecutionEntity entity : queryResult) {
|
||||
AuthenticationExecutionModel model = entityToModel(entity);
|
||||
executions.add(model);
|
||||
}
|
||||
Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
|
||||
return Collections.unmodifiableList(executions);
|
||||
|
||||
return flow.getExecutions().stream()
|
||||
.filter(e -> getId().equals(e.getRealm().getId()))
|
||||
.map(this::entityToModel)
|
||||
.sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON)
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
|
||||
|
@ -1519,7 +1509,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
entity.setRealm(realm);
|
||||
entity.setAutheticatorFlow(model.isAuthenticatorFlow());
|
||||
em.persist(entity);
|
||||
em.flush();
|
||||
model.setId(entity.getId());
|
||||
return model;
|
||||
|
||||
|
@ -1557,7 +1546,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
auth.setConfig(model.getConfig());
|
||||
realm.getAuthenticatorConfigs().add(auth);
|
||||
em.persist(auth);
|
||||
em.flush();
|
||||
model.setId(auth.getId());
|
||||
return model;
|
||||
}
|
||||
|
@ -1850,12 +1838,14 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
c.setSubType(model.getSubType());
|
||||
c.setRealm(realm);
|
||||
em.persist(c);
|
||||
realm.getComponents().add(c);
|
||||
setConfig(model, c);
|
||||
model.setId(c.getId());
|
||||
return model;
|
||||
}
|
||||
|
||||
protected void setConfig(ComponentModel model, ComponentEntity c) {
|
||||
c.getComponentConfigs().clear();
|
||||
for (String key : model.getConfig().keySet()) {
|
||||
List<String> vals = model.getConfig().get(key);
|
||||
if (vals == null) {
|
||||
|
@ -1867,7 +1857,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
config.setName(key);
|
||||
config.setValue(val);
|
||||
config.setComponent(c);
|
||||
em.persist(config);
|
||||
c.getComponentConfigs().add(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1884,8 +1874,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
c.setProviderType(component.getProviderType());
|
||||
c.setParentId(component.getParentId());
|
||||
c.setSubType(component.getSubType());
|
||||
em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate();
|
||||
em.flush();
|
||||
setConfig(component, c);
|
||||
ComponentUtil.notifyUpdated(session, this, old, component);
|
||||
|
||||
|
@ -1898,55 +1886,39 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
if (c == null) return;
|
||||
session.users().preRemove(this, component);
|
||||
removeComponents(component.getId());
|
||||
em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate();
|
||||
em.remove(c);
|
||||
getEntity().getComponents().remove(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeComponents(String parentId) {
|
||||
TypedQuery<String> query = em.createNamedQuery("getComponentIdsByParent", String.class)
|
||||
.setParameter("realm", realm)
|
||||
.setParameter("parentId", parentId);
|
||||
List<String> results = query.getResultList();
|
||||
if (results.isEmpty()) return;
|
||||
for (String id : results) {
|
||||
session.users().preRemove(this, getComponent(id));
|
||||
}
|
||||
em.createNamedQuery("deleteComponentConfigByParent").setParameter("parentId", parentId).executeUpdate();
|
||||
em.createNamedQuery("deleteComponentByParent").setParameter("parentId", parentId).executeUpdate();
|
||||
Predicate<ComponentEntity> sameParent = c -> Objects.equals(parentId, c.getParentId());
|
||||
|
||||
getEntity().getComponents().stream()
|
||||
.filter(sameParent)
|
||||
.map(this::entityToModel)
|
||||
.forEach(c -> session.users().preRemove(this, c));
|
||||
|
||||
getEntity().getComponents().removeIf(sameParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ComponentModel> getComponents(String parentId, String providerType) {
|
||||
public List<ComponentModel> getComponents(String parentId, final String providerType) {
|
||||
if (parentId == null) parentId = getId();
|
||||
TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponentsByParentAndType", ComponentEntity.class)
|
||||
.setParameter("realm", realm)
|
||||
.setParameter("parentId", parentId)
|
||||
.setParameter("providerType", providerType);
|
||||
List<ComponentEntity> results = query.getResultList();
|
||||
List<ComponentModel> rtn = new LinkedList<>();
|
||||
for (ComponentEntity c : results) {
|
||||
ComponentModel model = entityToModel(c);
|
||||
rtn.add(model);
|
||||
final String parent = parentId;
|
||||
|
||||
}
|
||||
return rtn;
|
||||
return realm.getComponents().stream()
|
||||
.filter(c -> parent.equals(c.getParentId())
|
||||
&& providerType.equals(c.getProviderType()))
|
||||
.map(this::entityToModel)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ComponentModel> getComponents(String parentId) {
|
||||
TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponentsByParent", ComponentEntity.class)
|
||||
.setParameter("realm", realm)
|
||||
.setParameter("parentId", parentId);
|
||||
List<ComponentEntity> results = query.getResultList();
|
||||
List<ComponentModel> rtn = new LinkedList<>();
|
||||
for (ComponentEntity c : results) {
|
||||
ComponentModel model = entityToModel(c);
|
||||
rtn.add(model);
|
||||
|
||||
}
|
||||
return rtn;
|
||||
public List<ComponentModel> getComponents(final String parentId) {
|
||||
return realm.getComponents().stream()
|
||||
.filter(c -> parentId.equals(c.getParentId()))
|
||||
.map(this::entityToModel)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected ComponentModel entityToModel(ComponentEntity c) {
|
||||
|
@ -1958,10 +1930,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
model.setSubType(c.getSubType());
|
||||
model.setParentId(c.getParentId());
|
||||
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
|
||||
TypedQuery<ComponentConfigEntity> configQuery = em.createNamedQuery("getComponentConfig", ComponentConfigEntity.class)
|
||||
.setParameter("component", c);
|
||||
List<ComponentConfigEntity> configResults = configQuery.getResultList();
|
||||
for (ComponentConfigEntity configEntity : configResults) {
|
||||
for (ComponentConfigEntity configEntity : c.getComponentConfigs()) {
|
||||
config.add(configEntity.getName(), configEntity.getValue());
|
||||
}
|
||||
model.setConfig(config);
|
||||
|
@ -1970,16 +1939,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public List<ComponentModel> getComponents() {
|
||||
TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponents", ComponentEntity.class)
|
||||
.setParameter("realm", realm);
|
||||
List<ComponentEntity> results = query.getResultList();
|
||||
List<ComponentModel> rtn = new LinkedList<>();
|
||||
for (ComponentEntity c : results) {
|
||||
ComponentModel model = entityToModel(c);
|
||||
rtn.add(model);
|
||||
|
||||
}
|
||||
return rtn;
|
||||
return realm.getComponents().stream().map(this::entityToModel).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,6 @@ public class RoleAdapter implements RoleModel, JpaModel<RoleEntity> {
|
|||
if (composite.equals(entity)) return;
|
||||
}
|
||||
getEntity().getCompositeRoles().add(entity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,11 +37,6 @@ import javax.persistence.Table;
|
|||
*/
|
||||
@Table(name="AUTHENTICATION_EXECUTION")
|
||||
@Entity
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getAuthenticationExecutionsByFlow", query="select authenticator from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
|
||||
@NamedQuery(name="deleteAuthenticationExecutionsByRealm", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm"),
|
||||
@NamedQuery(name="deleteAuthenticationExecutionsByRealmAndFlow", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
|
||||
})
|
||||
public class AuthenticationExecutionEntity {
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
|
|
|
@ -39,10 +39,6 @@ import java.util.Collection;
|
|||
*/
|
||||
@Table(name="AUTHENTICATION_FLOW")
|
||||
@Entity
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getAuthenticationFlowsByRealm", query="select flow from AuthenticationFlowEntity flow where flow.realm = :realm"),
|
||||
@NamedQuery(name="deleteAuthenticationFlowByRealm", query="delete from AuthenticationFlowEntity flow where flow.realm = :realm")
|
||||
})
|
||||
public class AuthenticationFlowEntity {
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
|
|
|
@ -162,6 +162,10 @@ public class ClientEntity {
|
|||
@JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
|
||||
Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(name="SCOPE_MAPPING", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
|
||||
protected Set<RoleEntity> scopeMapping = new HashSet<>();
|
||||
|
||||
@ElementCollection
|
||||
@MapKeyColumn(name="NAME")
|
||||
@Column(name="VALUE")
|
||||
|
@ -456,6 +460,14 @@ public class ClientEntity {
|
|||
this.useTemplateMappers = useTemplateMappers;
|
||||
}
|
||||
|
||||
public Set<RoleEntity> getScopeMapping() {
|
||||
return scopeMapping;
|
||||
}
|
||||
|
||||
public void setScopeMapping(Set<RoleEntity> scopeMapping) {
|
||||
this.scopeMapping = scopeMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -33,12 +33,6 @@ import javax.persistence.Table;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getComponentConfig", query="select attr from ComponentConfigEntity attr where attr.component = :component"),
|
||||
@NamedQuery(name="deleteComponentConfigByComponent", query="delete from ComponentConfigEntity attr where attr.component = :component"),
|
||||
@NamedQuery(name="deleteComponentConfigByRealm", query="delete from ComponentConfigEntity attr where attr.component IN (select u from ComponentEntity u where u.realm=:realm)"),
|
||||
@NamedQuery(name="deleteComponentConfigByParent", query="delete from ComponentConfigEntity attr where attr.component IN (select u from ComponentEntity u where u.parentId=:parentId)"),
|
||||
})
|
||||
@Table(name="COMPONENT_CONFIG")
|
||||
@Entity
|
||||
public class ComponentConfigEntity {
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
|
||||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
|
@ -27,19 +31,12 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getComponents", query="select attr from ComponentEntity attr where attr.realm = :realm"),
|
||||
@NamedQuery(name="getComponentsByParentAndType", query="select attr from ComponentEntity attr where attr.realm = :realm and attr.providerType = :providerType and attr.parentId = :parentId"),
|
||||
@NamedQuery(name="getComponentByParent", query="select attr from ComponentEntity attr where attr.realm = :realm and attr.parentId = :parentId"),
|
||||
@NamedQuery(name="getComponentIdsByParent", query="select attr.id from ComponentEntity attr where attr.realm = :realm and attr.parentId = :parentId"),
|
||||
@NamedQuery(name="deleteComponentByRealm", query="delete from ComponentEntity c where c.realm = :realm"),
|
||||
@NamedQuery(name="deleteComponentByParent", query="delete from ComponentEntity c where c.parentId = :parentId")
|
||||
})
|
||||
@Entity
|
||||
@Table(name="COMPONENT")
|
||||
public class ComponentEntity {
|
||||
|
@ -68,6 +65,9 @@ public class ComponentEntity {
|
|||
@Column(name="SUB_TYPE")
|
||||
protected String subType;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade ={ CascadeType.ALL}, orphanRemoval = true, mappedBy = "component")
|
||||
Set<ComponentConfigEntity> componentConfigs = new HashSet<>();
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -124,6 +124,14 @@ public class ComponentEntity {
|
|||
this.realm = realm;
|
||||
}
|
||||
|
||||
public Set<ComponentConfigEntity> getComponentConfigs() {
|
||||
return componentConfigs;
|
||||
}
|
||||
|
||||
public void setComponentConfigs(Set<ComponentConfigEntity> componentConfigs) {
|
||||
this.componentConfigs = componentConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -35,8 +35,6 @@ import javax.persistence.Table;
|
|||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getGroupAttributesByNameAndValue", query="select attr from GroupAttributeEntity attr where attr.name = :name and attr.value = :value"),
|
||||
@NamedQuery(name="deleteGroupAttributesByGroup", query="delete from GroupAttributeEntity attr where attr.group = :group"),
|
||||
@NamedQuery(name="deleteGroupAttributesByRealm", query="delete from GroupAttributeEntity attr where attr.group IN (select u from GroupEntity u where u.realm=:realm)")
|
||||
})
|
||||
@Table(name="GROUP_ATTRIBUTE")
|
||||
@Entity
|
||||
|
|
|
@ -38,13 +38,7 @@ import java.util.Collection;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getAllGroupsByRealm", query="select u from GroupEntity u where u.realm = :realm order by u.name"),
|
||||
@NamedQuery(name="getAllGroupIdsByRealm", query="select u.id from GroupEntity u where u.realm.id = :realm order by u.name"),
|
||||
@NamedQuery(name="getGroupById", query="select u from GroupEntity u where u.id = :id and u.realm = :realm"),
|
||||
@NamedQuery(name="getGroupIdsByParent", query="select u.id from GroupEntity u where u.parent = :parent"),
|
||||
@NamedQuery(name="getTopLevelGroupIds", query="select u.id from GroupEntity u where u.parent is null and u.realm.id = :realm"),
|
||||
@NamedQuery(name="getGroupCount", query="select count(u) from GroupEntity u where u.realm = :realm"),
|
||||
@NamedQuery(name="deleteGroupsByRealm", query="delete from GroupEntity u where u.realm = :realm")
|
||||
})
|
||||
@Entity
|
||||
@Table(name="KEYCLOAK_GROUP")
|
||||
|
|
|
@ -159,6 +159,9 @@ public class RealmEntity {
|
|||
@JoinTable(name="REALM_DEFAULT_GROUPS", joinColumns = { @JoinColumn(name="REALM_ID")}, inverseJoinColumns = { @JoinColumn(name="GROUP_ID")})
|
||||
protected Collection<GroupEntity> defaultGroups = new ArrayList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
protected Collection<GroupEntity> groups = new ArrayList<>();
|
||||
|
||||
@Column(name="EVENTS_ENABLED")
|
||||
protected boolean eventsEnabled;
|
||||
@Column(name="EVENTS_EXPIRATION")
|
||||
|
@ -199,6 +202,9 @@ public class RealmEntity {
|
|||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
Collection<AuthenticationFlowEntity> authenticationFlows = new ArrayList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.ALL}, orphanRemoval = true, mappedBy = "realm")
|
||||
Set<ComponentEntity> components = new HashSet<>();
|
||||
|
||||
@Column(name="BROWSER_FLOW")
|
||||
protected String browserFlow;
|
||||
|
||||
|
@ -426,6 +432,14 @@ public class RealmEntity {
|
|||
this.defaultGroups = defaultGroups;
|
||||
}
|
||||
|
||||
public Collection<GroupEntity> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public void setGroups(Collection<GroupEntity> groups) {
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
public String getPasswordPolicy() {
|
||||
return passwordPolicy;
|
||||
}
|
||||
|
@ -623,6 +637,14 @@ public class RealmEntity {
|
|||
this.authenticationFlows = authenticationFlows;
|
||||
}
|
||||
|
||||
public Set<ComponentEntity> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public void setComponents(Set<ComponentEntity> components) {
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public String getOtpPolicyType() {
|
||||
return otpPolicyType;
|
||||
}
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.jpa.entities;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="hasScope", query="select m from ScopeMappingEntity m where m.client = :client and m.role = :role"),
|
||||
@NamedQuery(name="clientScopeMappings", query="select m from ScopeMappingEntity m where m.client = :client"),
|
||||
@NamedQuery(name="clientScopeMappingIds", query="select m.role.id from ScopeMappingEntity m where m.client = :client"),
|
||||
@NamedQuery(name="deleteScopeMappingByRole", query="delete from ScopeMappingEntity where role = :role"),
|
||||
@NamedQuery(name="deleteScopeMappingByClient", query="delete from ScopeMappingEntity where client = :client")
|
||||
})
|
||||
@Table(name="SCOPE_MAPPING")
|
||||
@Entity
|
||||
@IdClass(ScopeMappingEntity.Key.class)
|
||||
public class ScopeMappingEntity {
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name = "CLIENT_ID")
|
||||
protected ClientEntity client;
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name="ROLE_ID")
|
||||
protected RoleEntity role;
|
||||
|
||||
public ClientEntity getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(ClientEntity client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(RoleEntity role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected ClientEntity client;
|
||||
|
||||
protected RoleEntity role;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(ClientEntity client, RoleEntity role) {
|
||||
this.client = client;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public ClientEntity getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
|
||||
if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = client != null ? client.getId().hashCode() : 0;
|
||||
result = 31 * result + (role != null ? role.getId().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof ScopeMappingEntity)) return false;
|
||||
|
||||
ScopeMappingEntity key = (ScopeMappingEntity) o;
|
||||
|
||||
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
|
||||
if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = client != null ? client.getId().hashCode() : 0;
|
||||
result = 31 * result + (role != null ? role.getId().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -37,7 +37,6 @@
|
|||
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.UserAttributeEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
|
||||
package org.keycloak.testsuite.admin;
|
||||
|
||||
import org.keycloak.admin.client.resource.ComponentResource;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ComponentsResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.representations.idm.AdminEventRepresentation;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||
import org.keycloak.representations.idm.*;
|
||||
import org.keycloak.testsuite.components.TestProvider;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
@ -33,6 +33,10 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.hamcrest.Matchers;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
|
@ -47,6 +51,44 @@ public class ComponentsTest extends AbstractAdminTest {
|
|||
components = adminClient.realm(REALM_NAME).components();
|
||||
}
|
||||
|
||||
private volatile CountDownLatch remainingDeleteSubmissions;
|
||||
|
||||
private static final int NUMBER_OF_THREADS = 4;
|
||||
private static final int NUMBER_OF_TASKS = NUMBER_OF_THREADS * 5;
|
||||
private static final int NUMBER_OF_CHILDREN = 3;
|
||||
|
||||
private void testConcurrency(BiConsumer<ExecutorService, Integer> taskCreator) throws InterruptedException {
|
||||
ExecutorService s = Executors.newFixedThreadPool(NUMBER_OF_THREADS,
|
||||
new BasicThreadFactory.Builder().daemon(true).uncaughtExceptionHandler((t, e) -> log.error(e.getMessage(), e)).build());
|
||||
this.remainingDeleteSubmissions = new CountDownLatch(NUMBER_OF_TASKS);
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_TASKS; i++) {
|
||||
taskCreator.accept(s, i);
|
||||
}
|
||||
|
||||
try {
|
||||
assertTrue("Did not create all components in time", this.remainingDeleteSubmissions.await(30, TimeUnit.SECONDS));
|
||||
s.shutdown();
|
||||
assertTrue("Did not finish before timeout", s.awaitTermination(30, TimeUnit.SECONDS));
|
||||
} finally {
|
||||
s.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrencyWithoutChildren() throws InterruptedException {
|
||||
testConcurrency((s, i) -> s.submit(new CreateAndDeleteComponent(s, i)));
|
||||
|
||||
assertThat(realm.components().query(realm.toRepresentation().getId(), TestProvider.class.getName()), Matchers.hasSize(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrencyWithChildren() throws InterruptedException {
|
||||
testConcurrency((s, i) -> s.submit(new CreateAndDeleteComponentWithFlatChildren(s, i)));
|
||||
|
||||
assertThat(realm.components().query(realm.toRepresentation().getId(), TestProvider.class.getName()), Matchers.hasSize(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotDeadlocked() {
|
||||
for (int i = 0; i < 50; i++) {
|
||||
|
@ -67,7 +109,7 @@ public class ComponentsTest extends AbstractAdminTest {
|
|||
try {
|
||||
createComponent(rep);
|
||||
} catch (WebApplicationException e) {
|
||||
assertErrror(e.getResponse(), "'Required' is required");
|
||||
assertError(e.getResponse(), "'Required' is required");
|
||||
}
|
||||
|
||||
rep.getConfig().putSingle("required", "Required");
|
||||
|
@ -77,7 +119,7 @@ public class ComponentsTest extends AbstractAdminTest {
|
|||
try {
|
||||
createComponent(rep);
|
||||
} catch (WebApplicationException e) {
|
||||
assertErrror(e.getResponse(), "'Number' should be a number");
|
||||
assertError(e.getResponse(), "'Number' should be a number");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,16 +301,27 @@ public class ComponentsTest extends AbstractAdminTest {
|
|||
assertEquals(value, returned.getConfig().getFirst("val1"));
|
||||
}
|
||||
|
||||
private String createComponent(ComponentRepresentation rep) {
|
||||
ComponentsResource components = realm.components();
|
||||
Response response = components.add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
getCleanup().addComponentId(id);
|
||||
response.close();
|
||||
return id;
|
||||
private java.lang.String createComponent(ComponentRepresentation rep) {
|
||||
return createComponent(realm, rep);
|
||||
}
|
||||
|
||||
private void assertErrror(Response response, String error) {
|
||||
private String createComponent(RealmResource realm, ComponentRepresentation rep) {
|
||||
Response response = null;
|
||||
try {
|
||||
ComponentsResource components = realm.components();
|
||||
response = components.add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
getCleanup(realm.toRepresentation().getRealm()).addComponentId(id);
|
||||
return id;
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.bufferEntity();
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertError(Response response, String error) {
|
||||
if (!response.hasEntity()) {
|
||||
fail("No error message set");
|
||||
}
|
||||
|
@ -290,4 +343,119 @@ public class ComponentsTest extends AbstractAdminTest {
|
|||
return rep;
|
||||
}
|
||||
|
||||
private class CreateComponent implements Runnable {
|
||||
|
||||
protected final ExecutorService s;
|
||||
protected final int i;
|
||||
protected final RealmResource realm;
|
||||
|
||||
public CreateComponent(ExecutorService s, int i, RealmResource realm) {
|
||||
this.s = s;
|
||||
this.i = i;
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public CreateComponent(ExecutorService s, int i) {
|
||||
this(s, i, ComponentsTest.this.realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.debugf("Started for i=%d ", i);
|
||||
ComponentRepresentation rep = createComponentRepresentation("test-" + i);
|
||||
rep.getConfig().putSingle("required", "required-value");
|
||||
rep.setParentId(this.realm.toRepresentation().getId());
|
||||
|
||||
String id = createComponent(this.realm, rep);
|
||||
assertThat(id, Matchers.notNullValue());
|
||||
|
||||
createChildren(id);
|
||||
|
||||
log.debugf("Finished: i=%d, id=%s", i, id);
|
||||
|
||||
scheduleDeleteComponent(id);
|
||||
remainingDeleteSubmissions.countDown();
|
||||
}
|
||||
|
||||
protected void scheduleDeleteComponent(String id) {
|
||||
}
|
||||
|
||||
protected void createChildren(String id) {
|
||||
}
|
||||
}
|
||||
|
||||
private class CreateAndDeleteComponent extends CreateComponent {
|
||||
|
||||
public CreateAndDeleteComponent(ExecutorService s, int i) {
|
||||
super(s, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduleDeleteComponent(String id) {
|
||||
s.submit(new DeleteComponent(id));
|
||||
}
|
||||
}
|
||||
|
||||
private class CreateComponentWithFlatChildren extends CreateComponent {
|
||||
|
||||
public CreateComponentWithFlatChildren(ExecutorService s, int i, RealmResource realm) {
|
||||
super(s, i, realm);
|
||||
}
|
||||
|
||||
public CreateComponentWithFlatChildren(ExecutorService s, int i) {
|
||||
super(s, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createChildren(String id) {
|
||||
for (int j = 0; j < NUMBER_OF_CHILDREN; j ++) {
|
||||
ComponentRepresentation rep = createComponentRepresentation("test-" + i + ":" + j);
|
||||
rep.setParentId(id);
|
||||
rep.getConfig().putSingle("required", "required-value");
|
||||
|
||||
assertThat(createComponent(this.realm, rep), Matchers.notNullValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class CreateAndDeleteComponentWithFlatChildren extends CreateAndDeleteComponent {
|
||||
|
||||
public CreateAndDeleteComponentWithFlatChildren(ExecutorService s, int i) {
|
||||
super(s, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createChildren(String id) {
|
||||
for (int j = 0; j < NUMBER_OF_CHILDREN; j ++) {
|
||||
ComponentRepresentation rep = createComponentRepresentation("test-" + i + ":" + j);
|
||||
rep.setParentId(id);
|
||||
rep.getConfig().putSingle("required", "required-value");
|
||||
|
||||
assertThat(createComponent(this.realm, rep), Matchers.notNullValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DeleteComponent implements Runnable {
|
||||
|
||||
private final String id;
|
||||
|
||||
public DeleteComponent(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.debugf("Started, id=%s", id);
|
||||
|
||||
ComponentResource c = realm.components().component(id);
|
||||
assertThat(c.toRepresentation(), Matchers.notNullValue());
|
||||
c.remove();
|
||||
|
||||
log.debugf("Finished, id=%s", id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue