Skip to content

Commit b209afa

Browse files
committed
fix: resolve ProxyBuilderImpl ClassNotFoundException in parallel import
Signed-off-by: Anil Dhurjaty <[email protected]>
1 parent f9e3655 commit b209afa

File tree

7 files changed

+55
-5
lines changed

7 files changed

+55
-5
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
## [6.4.1] - 2025-03-11
10+
### Added
11+
- Explicitly set the class loader in parallel forEach consumers
12+
13+
### Fixed
14+
- Fix `ClassNotFoundException: org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl` exception when using parallel imports [#1107](https://github.com/adorsys/keycloak-config-cli/issues/1107)
15+
916
## [6.4.0] - 2025-02-21
1017
### Added
1118
- Allow a user's username to be updated through the config [#810](https://github.com/adorsys/keycloak-config-cli/issues/810)

src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import de.adorsys.keycloak.config.util.ClientScopeUtil;
3131
import de.adorsys.keycloak.config.util.CloneUtil;
3232
import de.adorsys.keycloak.config.util.KeycloakUtil;
33+
import de.adorsys.keycloak.config.util.ParallelUtil;
3334
import de.adorsys.keycloak.config.util.ProtocolMapperUtil;
3435
import de.adorsys.keycloak.config.util.ResponseUtil;
3536
import org.apache.commons.lang3.ArrayUtils;
@@ -111,7 +112,7 @@ private void createOrUpdateClients(
111112
) {
112113
Consumer<ClientRepresentation> loop = client -> createOrUpdateClient(realmImport, client);
113114
if (importConfigProperties.isParallel()) {
114-
clients.parallelStream().forEach(loop);
115+
ParallelUtil.forEach(clients, loop);
115116
} else {
116117
clients.forEach(loop);
117118
}

src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import de.adorsys.keycloak.config.repository.ClientScopeRepository;
2727
import de.adorsys.keycloak.config.repository.RealmRepository;
2828
import de.adorsys.keycloak.config.util.CloneUtil;
29+
import de.adorsys.keycloak.config.util.ParallelUtil;
2930
import de.adorsys.keycloak.config.util.ProtocolMapperUtil;
3031
import org.keycloak.representations.idm.ClientScopeRepresentation;
3132
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
@@ -172,7 +173,7 @@ private void createOrUpdateClientScopes(
172173
) {
173174
Consumer<ClientScopeRepresentation> loop = clientScope -> createOrUpdateClientScope(realmName, clientScope);
174175
if (importConfigProperties.isParallel()) {
175-
clientScopes.parallelStream().forEach(loop);
176+
ParallelUtil.forEach(clientScopes, loop);
176177
} else {
177178
clientScopes.forEach(loop);
178179
}

src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues;
2828
import de.adorsys.keycloak.config.repository.GroupRepository;
2929
import de.adorsys.keycloak.config.util.CloneUtil;
30+
import de.adorsys.keycloak.config.util.ParallelUtil;
3031
import org.keycloak.representations.idm.GroupRepresentation;
3132
import org.slf4j.Logger;
3233
import org.slf4j.LoggerFactory;
@@ -78,7 +79,7 @@ public void importGroups(RealmImport realmImport) {
7879
public void createOrUpdateGroups(List<GroupRepresentation> groups, String realmName) {
7980
Consumer<GroupRepresentation> loop = group -> createOrUpdateRealmGroup(realmName, group);
8081
if (importConfigProperties.isParallel()) {
81-
groups.parallelStream().forEach(loop);
82+
ParallelUtil.forEach(groups, loop);
8283
} else {
8384
groups.forEach(loop);
8485
}

src/main/java/de/adorsys/keycloak/config/service/RoleImportService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import de.adorsys.keycloak.config.service.state.StateService;
3030
import de.adorsys.keycloak.config.util.CloneUtil;
3131
import de.adorsys.keycloak.config.util.KeycloakUtil;
32+
import de.adorsys.keycloak.config.util.ParallelUtil;
3233
import org.keycloak.representations.idm.RoleRepresentation;
3334
import org.keycloak.representations.idm.RolesRepresentation;
3435
import org.slf4j.Logger;
@@ -124,7 +125,7 @@ private void createOrUpdateRealmRoles(
124125
) {
125126
Consumer<RoleRepresentation> loop = role -> createOrUpdateRealmRole(realmName, role, existingRealmRoles);
126127
if (importConfigProperties.isParallel()) {
127-
rolesToImport.parallelStream().forEach(loop);
128+
ParallelUtil.forEach(rolesToImport, loop);
128129
} else {
129130
rolesToImport.forEach(loop);
130131
}

src/main/java/de/adorsys/keycloak/config/service/UserImportService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import de.adorsys.keycloak.config.repository.UserRepository;
3131
import de.adorsys.keycloak.config.util.CloneUtil;
3232
import de.adorsys.keycloak.config.util.KeycloakUtil;
33+
import de.adorsys.keycloak.config.util.ParallelUtil;
3334
import org.keycloak.representations.idm.*;
3435
import org.slf4j.Logger;
3536
import org.slf4j.LoggerFactory;
@@ -87,7 +88,7 @@ public void doImport(RealmImport realmImport) {
8788

8889
Consumer<UserRepresentation> loop = user -> importUser(realmImport.getRealm(), user);
8990
if (importConfigProperties.isParallel()) {
90-
users.parallelStream().forEach(loop);
91+
ParallelUtil.forEach(users, loop);
9192
} else {
9293
users.forEach(loop);
9394
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*-
2+
* ---license-start
3+
* keycloak-config-cli
4+
* ---
5+
* Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com
6+
* ---
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* ---license-end
19+
*/
20+
21+
package de.adorsys.keycloak.config.util;
22+
23+
import java.util.List;
24+
import java.util.function.Consumer;
25+
26+
// Override the default implementation of the forEach method in the ParallelUtil class
27+
// Found that the class loader in threads is different from the application class loader,
28+
// leading to [this issue](https://github.com/adorsys/keycloak-config-cli/issues/1107)
29+
public class ParallelUtil {
30+
public static <T> void forEach(List<T> list, Consumer<T> consumer) {
31+
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
32+
list.parallelStream()
33+
.forEach(x -> {
34+
Thread.currentThread().setContextClassLoader(originalClassLoader);
35+
consumer.accept(x);
36+
});
37+
}
38+
}

0 commit comments

Comments
 (0)