Skip to content

Feature Request: MicroProfile-config integration: Allow injecting annotations with jakarta.inject.Qualifier #1679

@scr-oath

Description

@scr-oath

I would like to integrate with MicroProfile Config. I got pretty far along, but… in order to allow Guice to allow @ConfigProperty, I had to do some very nasty reflection to muck with the innards of the strategyFor so that ensureIsBindingAnnotation(annotationType); would pass and allow me to Key.get(someType, someConfigPropertyAnnotation).

Ultimately, I would like to bind the @ConfigProperty and, of course, if this snippet can be made to work, any solution is awesome:

package org.example;

import com.google.common.reflect.ClassPath;
import com.google.inject.AbstractModule;
import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.name.Names;
import com.google.inject.spi.Message;
import io.smallrye.config.SmallRyeConfigBuilder;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class MPConfigModule extends AbstractModule {

    private static final Logger LOGGER = LoggerFactory.getLogger(MPConfigModule.class);

    @Override
    protected void configure() {

        SmallRyeConfigBuilder configBuilder = new SmallRyeConfigBuilder()
            .addDefaultSources()
            .addDefaultInterceptors()
            .addDiscoveredSources()
            .addDiscoveredConverters()
            .addDiscoveredInterceptors();

        Provider<Config> configProvider = getProvider(Config.class);

        try {
            for (ClassPath.ClassInfo clsInfo : ClassPath.from(ClassLoader.getSystemClassLoader()).getAllClasses()) {
                try {
                    if (clsInfo.getSimpleName().equals("module-info")) {
                        continue;
                    }
                    Class<?> cls;
                    cls = clsInfo.load();
                    Set<Key<?>> seen = new HashSet<>();

                    for (Constructor<?> constructor : cls.getDeclaredConstructors()) {
                        if (null != constructor.getDeclaredAnnotation(com.google.inject.Inject.class)
                            || null != constructor.getDeclaredAnnotation(javax.inject.Inject.class)) {
                            LOGGER.debug("constructor {}", constructor);
                        }
                        for (Parameter parameter : constructor.getParameters()) {
                            ConfigProperty configProperty = parameter.getDeclaredAnnotation(ConfigProperty.class);
                            if (null == configProperty) {
                                continue;
                            }
                            Class<?> tpe = parameter.getType();
                            LOGGER.debug("method {} {} ", tpe, configProperty);
                            Key<?> key = Key.get(tpe, configProperty);
                            if (seen.add(key)) {
                                String name = configProperty.name();
                                String defaultValue = configProperty.defaultValue();
                                if (defaultValue != null) {
                                    configBuilder.withDefaultValue(name, defaultValue);
                                }
                                //noinspection unchecked
                                bind((Key<Object>) key).toProvider(() -> configProvider.get().getValue(name, tpe));
                            }
                        }
                    }
                    for (Field field : cls.getDeclaredFields()) {
                        ConfigProperty configProperty = field.getDeclaredAnnotation(ConfigProperty.class);
                        if (null == configProperty) {
                            continue;
                        }
                        if (null != field.getDeclaredAnnotation(com.google.inject.Inject.class)
                            || null != field.getDeclaredAnnotation(javax.inject.Inject.class)) {
                            Class<?> tpe = field.getType();
                            LOGGER.debug("field {} {} ", tpe, configProperty);
                            Key<?> key = Key.get(tpe, configProperty);
                            if (seen.add(key)) {
                                String name = configProperty.name();
                                String defaultValue = configProperty.defaultValue();
                                if (defaultValue != null) {
                                    configBuilder.withDefaultValue(name, defaultValue);
                                }
                                //noinspection unchecked
                                bind((Key<Object>) key).toProvider(() -> configProvider.get().getValue(name, tpe));
                            }
                        }
                    }
                    for (Method method : cls.getDeclaredMethods()) {
                        if (null != method.getDeclaredAnnotation(com.google.inject.Inject.class)
                            || null != method.getDeclaredAnnotation(javax.inject.Inject.class)) {
                            for (Parameter parameter : method.getParameters()) {
                                ConfigProperty configProperty = parameter.getDeclaredAnnotation(ConfigProperty.class);
                                if (null == configProperty) {
                                    continue;
                                }
                                Class<?> tpe = parameter.getType();
                                LOGGER.debug("method {} {} ", tpe, configProperty);
                                Key<?> key = Key.get(tpe, configProperty);
                                if (seen.add(key)) {
                                    String name = configProperty.name();
                                    String defaultValue = configProperty.defaultValue();
                                    if (defaultValue != null) {
                                        configBuilder.withDefaultValue(name, defaultValue);
                                    }
                                    //noinspection unchecked
                                    bind((Key<Object>) key).toProvider(() -> configProvider.get().getValue(name, tpe));
                                }
                            }
                        }
                    }
                } catch (NoClassDefFoundError e) {
                    LOGGER.debug("Error loading class {}", clsInfo, e);
                }
            }
            bind(Config.class).toInstance(configBuilder.build());
        } catch (IOException e) {
            throw new ConfigurationException(Collections.singleton(new Message(e.getLocalizedMessage())));
        }
    }
}

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