Skip to content

http-client not picking the Configuration dynamically. #189

Open

Description

@sunilkumar207106

Hello Team,

Let us assume a case we are trying to connect to openstack with SSL Configuration in a loop i.e if not able to authenticate retry again until authentication is not successful, as for SSL Configuration we need to load up the certificate. So I will say two threads are running parallelly

  1. Trying to update keystore dynamically. Thread 1
  2. Trying to authenticate user to openstack over SSL/TSL Thread 2.

Thread 2 loads the certificate from the keystore before the thread 1 update the certificate in keystore. So Thread 2 Continuously picking the updated certificate even though before each authentication request we are creating the OSClientV3 and Config object in loop you can see the below snippet which is running in a loop.

`Config cfg = Config.newConfig().withConnectionTimeout(100000).withReadTimeout(100000);
System.out.println("sslContext= "+sslContext);
cfg.withSSLContext(sslContext);
OSFactory.enableHttpLoggingFilter(true);

		V3 cb = OSFactory.builderV3().withConfig(cfg).endpoint(url).credentials(user, password,
				Identifier.byName(userDomain));
		if (projectDomain != null && !projectDomain.trim().isEmpty()) {
			if (tenant != null && !tenant.trim().isEmpty()) {
				/* project scoped auth */
				cb.scopeToProject(Identifier.byName(tenant), Identifier.byName(projectDomain));
			} else {
				/* domain scoped auth */
				cb.scopeToDomain(Identifier.byName(projectDomain));
			}
		}
		OSClientV3 os = cb.authenticate();` 

Root cause of this issue which I assume that we are creating singleton object Of Client in Factory class regardless the Config object changed or not

CloseableHttpClient getClient(Config config) { if (client == null) { synchronized (this) { if (client == null) { client = buildClient(config); } } } return client; }

But if we see the implementation of jersey connector it takes care of it i.e is config object changed or not. Please see the code in jersey code base

` private static LoadingCache<Config, Client> CACHE = CacheBuilder.newBuilder()
.expireAfterAccess(20, TimeUnit.MINUTES)
.build(new CacheLoader<Config, Client>() {
@OverRide
public Client load(Config config) throws Exception {
return buildClientFromConfig(config);
}
});

/**
 * Creates or Returns a Client
 *
 * @param config the configuration to use for the given client
 * @return the client
 */
static Client create(Config config) {
    try {
        return CACHE.get(config);
    } catch (ExecutionException e) {
        throw new ConnectionException("Issue creating Jersey 2 Client: " + e.getMessage(), 0, e);
    }
}`

At last what are real world scenario...

  1. If someone wants to update the certificate and do not want to restart the service.
  2. If someone wants to connect with two different version of certificate in same app or service then always first Certificate will gets it precedence

Please share your thoughts and if possible if there is any workaround please comment.

Thank You,

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions