Title: Custom ConfigSource for Quarkus
Tags: java;datasource;cdi;quarkus;microprofile
Question: I'm trying now to configure custom ConfigSource in my Quarkus App. Like in many other manuals i'm created my own DatabaseSourceConfig and implements org.eclipse.microprofile.config.spi.ConfigSource interface.I registered my ConfigSource in: 

```/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
```

There is my ConfigSource:

```public class DatabaseConfigSource implements ConfigSource {
private DataSource dataSource;

public DatabaseConfigSource() {
    try {
        dataSource = (DataSource) new InitialContext().lookup("openejb:Resource/config-source-database");
    } catch (final NamingException e) {
        throw new IllegalStateException(e);
    }
}

@Override
public Map<String, String&gt; getProperties() {
    // Implementing Method
}

@Override
public String getValue(final String propertyName) {
    // Implementing Method
}

@Override
public String getName() {
    return DatabaseConfigSource.class.getSimpleName();
}
```

}

But this not working for Quarkus because of JNDI name. I need to use CDI. I was trying to use something like this:

```@Inject
@io.quarkus.agroal.DataSource("my_connection")
AgroalDataSource usersDataSource;
```

and declare this connection in application.properties but it didn't help me. I'm getting all the time NULL Exception.
Maybe someone have ideas, how can i get DB connection there without to use JNDI namespace?

Comment: welcome to stackoverflow. Take a tour and get your first badge-https://stackoverflow.com/tour

Here is the accepted answer: I found some answer myself, maybe it will be useful also for other ppl.
Like @Janmartiška said, CDI booted later, than ConfigSource, that's why i don't see any way to inject my connection via CDI.
I was created some HibernateUtil Class:

```package org.myproject.config;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.myproject.entities.ConfigurationsEntity;

public class HibernateUtil {
    private static SessionFactory sessionFactory;

    private static SessionFactory buildSessionFactory() {
        try {
            Properties props = new Properties();
            props.setProperty("hibernate.connection.url", "jdbc:mysql://[db-host]:[db-port]/db_name");
            props.setProperty("hibernate.connection.driver_class", "com.mysql.cj.jdbc.Driver");
            props.setProperty("hibernate.connection.username", "username");
            props.setProperty("hibernate.connection.password", "password");

            props.setProperty("hibernate.current_session_context_class", "thread");
            props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");

            Configuration configuration = new Configuration();
            configuration.addProperties(props);
            configuration.addAnnotatedClass(ConfigurationsEntity.class);
            System.out.println("Hibernate Configuration loaded");

            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("Hibernate serviceRegistry created");

            SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

            return sessionFactory;
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        if(sessionFactory == null) sessionFactory = buildSessionFactory();
        return sessionFactory;
    }

}
```

than i used it in my SourceConfig:

```package org.myproject.config;

import io.quarkus.runtime.annotations.RegisterForReflection;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.myproject.entities.ConfigurationsEntity;

import javax.persistence.NoResultException;
import javax.persistence.Query;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RegisterForReflection
public class DatabaseSourceConfig implements ConfigSource {

    public SessionFactory sessionFactory;
    public Session currentSession;

    public DatabaseSourceConfig() {

        sessionFactory = HibernateUtil.getSessionFactory();
        this.checkFactoryConnection();

    }

    public void checkFactoryConnection() {

        if (currentSession == null || (currentSession != null &amp;&amp; !currentSession.isOpen())) {
            try {
                currentSession = sessionFactory.getCurrentSession();
            } catch (NullPointerException e) {
                currentSession = sessionFactory.openSession();
            }
        }

    }

    @Override
    public Map<String, String&gt; getProperties() {
        // Implementing Method
    }

    @Override
    public String getValue(String propertyName) {
            this.checkFactoryConnection();
            ConfigurationsEntity conf = new ConfigurationsEntity();
            currentSession.beginTransaction();

            try {
                Query query = currentSession.createNamedQuery("Configuration.selectOne", ConfigurationsEntity.class);
                query.setParameter("name", propertyName);
                conf = (ConfigurationsEntity) query.getSingleResult();
                currentSession.getTransaction().commit();

            } catch (Exception ex) {
                currentSession.getTransaction().rollback();
            }

            return conf.getValue();

    }

    @Override
    public String getName() {
        return DatabaseSourceConfig.class.getSimpleName();
    }
}
```

Now i can use my ConfigSource in other classes like:

```@Inject
@ConfigProperty(name = "[property-name-like-in-db]")
public String someProperty;
```



After my further research it was found that ConfigSource has no access to CDi and application.properties. That is why there is nothing left but to establish a connection to the database in the manner described above.
However, I did a little editing of the example. I cached properties from the database and created a @ApplicationScoped Bean that looks into the database once every 5 minutes to see whether one of properties "updated_at" has a timestamp later than others from Bean loaded properties.

However, I have to say that according to Quarkus and Apache developers - this violates “immutable deployment” and is not planned to change the application settings during runtime. So it depends on you whether you write it in the app or not.


Here is another answer: You can obtain the data source via 

```AgroalDataSource dataSource = Arc.container()
    .instance(AgroalDataSource.class, new DataSource.DataSourceLiteral("my_connection"))
    .get();
```

You'll need to do this somewhere else than the constructor though, I think, because the ConfigSource instance is created before CDI is fully booted. You can cache the obtained data source instance then to avoid executing this multiple times.

Comment for this answer: Problem is, that i can't Cache result, because configuration can be changed "on the flow". I need all the Time actual configuration value. But thanks for u comment - i also suspected, that CDI booted later than ConfigSource. I solved my Problem with SessionFactory without CDI. I will post my code a little bit later. Maybe u will have some more comments to it.
Comment for this answer: I mean change Config Values in DataBase. And it’s not about Dev mode, but Produktion. Custom ConfigSource read Config values from database all the time without to cache them, to have an actual value. I can read more about it for example there: https://ralph.blog.imixs.com/2019/06/11/microprofile-customconfigsource-with-database/
Comment for this answer: What do you mean by changing the configuration? If you're referring to development mode, then if you change the config in dev mode, the application will reboot, so a new instance of your ConfigSource will be created and the cached value will be lost.
Comment for this answer: Ok, but then you can cache the data source instance so that you don't have to do the expensive CDI lookup again.  I meant caching just the instance, not the data from database.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 1, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2020:00:05/20/20', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<java><datasource><cdi><quarkus><microprofile>', 'Title': 'Custom ConfigSource for Quarkus', 'ViewCount': 1583, 'id': 61909786, 'user_AboutMe': None, 'user_AccountId': 16378945.0, 'user_DisplayName': 'MadinaS', 'user_Reputation': 21.0, 'user_Views': 3.0, 'user_id': 11830434.0}}