collado-mike commented on code in PR #493:
URL: https://github.com/apache/polaris/pull/493#discussion_r1866669012


##########
polaris-service/src/main/java/org/apache/polaris/service/PolarisApplication.java:
##########
@@ -151,87 +173,195 @@ public void 
initialize(Bootstrap<PolarisApplicationConfig> bootstrap) {
 
     bootstrap.addCommand(new BootstrapRealmsCommand());
     bootstrap.addCommand(new PurgeRealmsCommand());
-  }
+    serviceLocator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
+    SimpleValueInstantiators instantiators = new SimpleValueInstantiators();
+    ObjectMapper objectMapper = bootstrap.getObjectMapper();
 
-  @Override
-  public void run(PolarisApplicationConfig configuration, Environment 
environment) {
-    MetaStoreManagerFactory metaStoreManagerFactory = 
configuration.getMetaStoreManagerFactory();
-
-    metaStoreManagerFactory.setStorageIntegrationProvider(
-        new PolarisStorageIntegrationProviderImpl(
-            () -> {
-              StsClientBuilder stsClientBuilder = StsClient.builder();
-              AwsCredentialsProvider awsCredentialsProvider = 
configuration.credentialsProvider();
-              if (awsCredentialsProvider != null) {
-                stsClientBuilder.credentialsProvider(awsCredentialsProvider);
+    // Register the PolarisApplicationConfig class with the ServiceLocator so 
that we can inject
+    // instances of the configuration or certain of the configuration fields 
into other classes.
+    // The configuration's postConstruct method registers all the configured 
fields as factories
+    // so that they are used for DI.
+    ServiceLocatorUtilities.addClasses(serviceLocator, 
PolarisApplicationConfig.class);
+    TypeFactory typeFactory = TypeFactory.defaultInstance();
+    instantiators.addValueInstantiator(
+        PolarisApplicationConfig.class,
+        new ServiceLocatorValueInstantiator(
+            objectMapper.getDeserializationConfig(),
+            typeFactory.constructType(PolarisApplicationConfig.class),
+            serviceLocator));
+
+    // Use the default ServiceLocator to discover the implementations of 
various contract providers
+    // and register them as subtypes with the ObjectMapper. This allows 
Jackson to discover the
+    // various implementations and use the type annotations to determine which 
instance to use when
+    // parsing the YAML configuration.
+    serviceLocator
+        .getDescriptors((c) -> true)
+        .forEach(
+            descriptor -> {
+              try {
+                Class<?> klazz =
+                    PolarisApplication.class
+                        .getClassLoader()
+                        .loadClass(descriptor.getImplementation());
+                String name = descriptor.getName();
+                if (name == null) {
+                  objectMapper.registerSubtypes(klazz);
+                } else {
+                  objectMapper.registerSubtypes(new NamedType(klazz, name));
+                }
+              } catch (ClassNotFoundException e) {
+                LOGGER.error("Error loading class {}", 
descriptor.getImplementation(), e);
+                throw new RuntimeException("Unable to start Polaris 
application");
               }
-              return stsClientBuilder.build();
-            },
-            configuration.getGcpCredentialsProvider()));
+            });
 
-    PolarisMetricRegistry polarisMetricRegistry =
-        new PolarisMetricRegistry(new 
PrometheusMeterRegistry(PrometheusConfig.DEFAULT));
-    metaStoreManagerFactory.setMetricRegistry(polarisMetricRegistry);
+    ServiceLocatorUtilities.addClasses(serviceLocator, 
PolarisMetricRegistry.class);
+    ServiceLocatorUtilities.bind(
+        serviceLocator,
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bind(new 
PrometheusMeterRegistry(PrometheusConfig.DEFAULT)).to(MeterRegistry.class);
+          }
+        });
+    SimpleModule module = new SimpleModule();
+    module.setValueInstantiators(instantiators);
+    module.setMixInAnnotation(Authenticator.class, NamedAuthenticator.class);
+    objectMapper.registerModule(module);
+  }
 
-    OpenTelemetry openTelemetry = setupTracing();
-    if (metaStoreManagerFactory instanceof OpenTelemetryAware otAware) {
-      otAware.setOpenTelemetry(openTelemetry);
+  /**
+   * Value instantiator that uses the ServiceLocator to create instances of 
the various service
+   * types
+   */
+  private static class ServiceLocatorValueInstantiator extends 
StdValueInstantiator {
+    private final ServiceLocator serviceLocator;
+
+    public ServiceLocatorValueInstantiator(
+        DeserializationConfig config, JavaType valueType, ServiceLocator 
serviceLocator) {
+      super(config, valueType);
+      this.serviceLocator = serviceLocator;
     }
-    PolarisConfigurationStore configurationStore = 
configuration.getConfigurationStore();
-    if (metaStoreManagerFactory instanceof ConfigurationStoreAware) {
-      ((ConfigurationStoreAware) 
metaStoreManagerFactory).setConfigurationStore(configurationStore);
+
+    @Override
+    public boolean canCreateUsingDefault() {
+      return true;
     }
-    RealmEntityManagerFactory entityManagerFactory =
-        new RealmEntityManagerFactory(metaStoreManagerFactory);
-    CallContextResolver callContextResolver = 
configuration.getCallContextResolver();
-    callContextResolver.setMetaStoreManagerFactory(metaStoreManagerFactory);
-    if (callContextResolver instanceof ConfigurationStoreAware csa) {
-      csa.setConfigurationStore(configurationStore);
+
+    @Override
+    public boolean canInstantiate() {
+      return true;
     }
 
-    RealmContextResolver realmContextResolver = 
configuration.getRealmContextResolver();
-    realmContextResolver.setMetaStoreManagerFactory(metaStoreManagerFactory);
+    @Override
+    public Object createUsingDefault(DeserializationContext ctxt) throws 
IOException {
+      return ServiceLocatorUtilities.findOrCreateService(serviceLocator, 
getValueClass());
+    }
+  }
+
+  /**
+   * Authenticator uses the java Class name in the YAML configuration. Since 
the Authenticator
+   * interface is owned by Dropwizard, we need to use a MixIn to tell Jackson 
what field to use to
+   * discover the implementation from the configuration.
+   */
+  @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "class")
+  static final class NamedAuthenticator {}
+
+  @Override
+  public void run(PolarisApplicationConfig configuration, Environment 
environment) {
+    OpenTelemetry openTelemetry = setupTracing();
+    PolarisMetricRegistry polarisMetricRegistry =
+        configuration.findService(PolarisMetricRegistry.class);
+
+    MetaStoreManagerFactory metaStoreManagerFactory =
+        configuration.findService(MetaStoreManagerFactory.class);
+
+    // Use the PolarisApplicationConfig to register dependencies in the Jersey 
resource
+    // configuration. This uses a different ServiceLocator from the one in the 
bootstrap step
+    environment.jersey().register(configuration.binder());
+    environment
+        .jersey()
+        .register(
+            new AbstractBinder() {
+              @Override
+              protected void configure() {
+                bind(RealmScopeContext.class)

Review Comment:
   I think this should be considered the smallest change necessary to get CDI 
working. There are improvements that can be made, e.g., classpath scanning for 
detecting Resource and Service impls, but the primary goal right now is to have 
runtime framework dependent on `@Inject` for wiring. Once that's done, lots of 
other changes can happen in parallel - e.g., improvements to the authorizer, 
authentication changes, as well as improvements to the CDI framework. I think 
this accomplishes the smallest change necessary to allow those other changes to 
progress.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to