Skip to content

Commit

Permalink
Don't let certain errors fail SPI loading
Browse files Browse the repository at this point in the history
  • Loading branch information
alzimmermsft committed Sep 23, 2024
1 parent f5741c4 commit e1dc87a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ public static Stream<HttpClient> getHttpClients() {
httpClientProvider.getClass().getSimpleName().toLowerCase(Locale.ROOT))) {
httpClientsToTest.add(httpClientProvider.createInstance());
}
} catch (ServiceConfigurationError | UnsupportedClassVersionError error) {
LOGGER.atWarning().log(() -> "Skipping HttpClientProvider due to UnsupportedClassVersionError.", error);
} catch (ServiceConfigurationError | LinkageError error) {
LOGGER.atWarning().log(() -> "Skipping HttpClientProvider due to LinkageError.", error);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

import com.azure.core.util.CoreUtils;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LogLevel;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.function.Function;

/**
* Helper class that unifies SPI instances creation.
*
*
* @param <TProvider> Service Provider interface.
* @param <TInstance> Service interface type.
*/
Expand Down Expand Up @@ -44,30 +44,39 @@ public Providers(Class<TProvider> providerClass, String defaultImplementationNam
// System classloader to load TProvider classes.
ServiceLoader<TProvider> serviceLoader = ServiceLoader.load(providerClass, Providers.class.getClassLoader());

availableProviders = new HashMap<>();
// Use the first provider found in the service loader iterator.
Iterator<TProvider> it = serviceLoader.iterator();
if (it.hasNext()) {
defaultProvider = it.next();
defaultProviderName = defaultProvider.getClass().getName();
availableProviders.put(defaultProviderName, defaultProvider);
LOGGER.log(LogLevel.VERBOSE,
() -> "Using " + defaultProviderName + " as the default " + providerClass.getName() + ".");
} else {
defaultProvider = null;
defaultProviderName = null;
}
TProvider defaultProvider = null;
String defaultProviderName = null;
this.availableProviders = new HashMap<>();

// Load all provider instances.
Iterator<TProvider> it = serviceLoader.iterator();
while (it.hasNext()) {
TProvider additionalProvider = it.next();
String additionalProviderName = additionalProvider.getClass().getName();
availableProviders.put(additionalProviderName, additionalProvider);
LOGGER.log(LogLevel.VERBOSE, () -> "Additional provider found on the classpath: " + additionalProviderName);
try {
TProvider provider = it.next();
String providerName = provider.getClass().getName();
availableProviders.put(providerName, provider);
if (defaultProvider == null) {
defaultProvider = provider;
defaultProviderName = providerName;
LOGGER.atVerbose()
.addKeyValue("providerName", providerName)
.addKeyValue("providerClass", providerClass.getName())
.log("Loaded default provider.");
} else {
LOGGER.atVerbose()
.addKeyValue("providerName", providerName)
.log("Additional provider found on the classpath");
}
} catch (LinkageError | ServiceConfigurationError error) {
LOGGER.atWarning().log(() -> "Failed to load a provider instance.", error);
}
}

defaultImplementation = defaultImplementationName;
noDefaultImplementation = CoreUtils.isNullOrEmpty(defaultImplementation);
noProviderMessage = noProviderErrorMessage;
this.defaultProvider = defaultProvider;
this.defaultProviderName = defaultProviderName;
this.defaultImplementation = defaultImplementationName;
this.noDefaultImplementation = CoreUtils.isNullOrEmpty(defaultImplementation);
this.noProviderMessage = noProviderErrorMessage;
}

private String formatNoSpecificProviderErrorMessage(String selectedImplementation) {
Expand Down

0 comments on commit e1dc87a

Please sign in to comment.