Class Config

java.lang.Object
com.codename1.backend.Config

public final class Config extends Object

Where a server's settings come from, in one resolution order.

The shape is the one a Spring Boot developer already knows, because the problem is the same one: the SAME code has to run against a SQLite file on a laptop and a managed PostgreSQL in production, and the difference between those two cannot live in the source. It lives here.

# application.properties, committed
cn1.datasource.url=${DATABASE_URL}
cn1.server.port=8080

# application-dev.properties, also committed
cn1.datasource.url=:memory:
CN1_PROFILE=dev ./server                       # SQLite, nothing installed
DATABASE_URL=postgres://user:pw@db/app ./server # production

A key is looked for in this order, and the first layer that has it wins:

  1. a system property of exactly that name (-Dcn1.server.port=9000), which only the local JVM loop can set;

  2. an environment variable of the name in upper case with dots as underscores (CN1_SERVER_PORT), which is how a container sets one;

  3. the environment variable a platform already sets for it, where one exists: PORT and DATABASE_URL are set for you by every PaaS worth the name, and a server that ignored them would need a wrapper script to start at all;

  4. application-<profile>.properties;

  5. application.properties;

  6. the default the caller passed in.

A value may reference an environment variable as ${NAME} or ${NAME:fallback}. That resolution happens when the value is READ rather than when the file is loaded, which is what lets a committed application.properties name a variable that only production sets: the dev profile overrides the key, so the unset variable is never looked at. A reference that IS read and cannot be resolved is an error rather than a value with a dollar sign in it -- the alternative is a server that tries to open a SQLite file named "${DATABASE_URL}".

Nothing here is required. A binary with no properties file beside it reads its whole configuration from the environment, which is the normal shape for a container built FROM SCRATCH: there is no file next to the binary because there is nothing next to the binary.

  • Field Details

    • PROFILE

      public static final String PROFILE
      Which profile is active. Defaults to "default".
      See Also:
    • LOCATION

      public static final String LOCATION
      The directory the properties files are read from. Defaults to ".".
      See Also:
    • SERVER_PORT

      public static final String SERVER_PORT
      The port to listen on. Also read from PORT.
      See Also:
    • SERVER_BACKLOG

      public static final String SERVER_BACKLOG
      The listen backlog.
      See Also:
    • SERVER_WORKERS

      public static final String SERVER_WORKERS
      The size of the request thread pool.
      See Also:
    • SERVER_SHUTDOWN_MILLIS

      public static final String SERVER_SHUTDOWN_MILLIS
      How long a stop waits for requests in flight, in milliseconds.
      See Also:
    • TLS_CERTIFICATE

      public static final String TLS_CERTIFICATE
      A PEM certificate chain to terminate TLS with.
      See Also:
    • TLS_KEY

      public static final String TLS_KEY
      The private key for TLS_CERTIFICATE.
      See Also:
    • TLS_HTTP2

      public static final String TLS_HTTP2
      Whether to offer HTTP/2 through ALPN when TLS is terminated here.
      See Also:
    • STATIC_ROOT

      public static final String STATIC_ROOT
      A directory to serve static files from.
      See Also:
    • STATIC_PREFIX

      public static final String STATIC_PREFIX
      The path prefix those files are served under. Defaults to /static.
      See Also:
    • STATIC_INDEX

      public static final String STATIC_INDEX
      The file a directory request is answered with. Defaults to index.html.
      See Also:
    • STATIC_CACHE_CONTROL

      public static final String STATIC_CACHE_CONTROL
      The Cache-Control header those files carry.
      See Also:
    • DATASOURCE_URL

      public static final String DATASOURCE_URL
      The database, as a SQLite path or a PostgreSQL or MySQL URL. Also read from DATABASE_URL.
      See Also:
    • DATASOURCE_POOL_SIZE

      public static final String DATASOURCE_POOL_SIZE
      How many connections the pool holds.
      See Also:
    • DATASOURCE_BORROW_MILLIS

      public static final String DATASOURCE_BORROW_MILLIS
      How long a borrow waits for a free connection, in milliseconds.
      See Also:
    • DATASOURCE_BUSY_MILLIS

      public static final String DATASOURCE_BUSY_MILLIS
      How long SQLite waits on a locked database, in milliseconds.
      See Also:
    • ORM_CREATE_TABLES

      public static final String ORM_CREATE_TABLES
      Whether the generated daos create their tables at start-up. Defaults to true on a development profile and false everywhere else: a laptop wants a schema without being asked, and production wants its migrations run by whatever runs migrations.
      See Also:
  • Method Details

    • load

      public static Config load() throws IOException
      Reads the configuration for this process: the active profile, then the two properties files, from LOCATION or the working directory.
      Throws:
      IOException
    • load

      public static Config load(String directory) throws IOException
      Reads the configuration from properties files in directory.
      Throws:
      IOException
    • of

      public static Config of(java.util.Properties values, String profile)
      A configuration with no files behind it, holding exactly what it is given. The process environment still wins over it, for the same reason it wins over a file: the deployment has the last word.
    • getProfile

      public String getProfile()
      The active profile: "default" unless something named another.
    • isDevelopmentProfile

      public boolean isDevelopmentProfile()

      Whether the active profile is a development one -- dev, development, test or local.

      This decides two defaults and nothing else: an unconfigured database becomes an in-memory SQLite one rather than a refusal, and the ORM creates its tables. Both are wrong in production and right on a laptop, and both are overridable by naming the key.

    • get

      public String get(String key) throws IOException
      The value for key, or null when no layer has one.
      Throws:
      IOException
    • get

      public String get(String key, String fallback) throws IOException
      The value for key, or fallback when no layer has one.
      Throws:
      IOException
    • getInt

      public int getInt(String key, int fallback) throws IOException
      The value for key as a number, or fallback.
      Throws:
      IOException
    • getBoolean

      public boolean getBoolean(String key, boolean fallback) throws IOException

      The value for key as a flag, or fallback.

      "true", "yes", "on" and "1" are true; "false", "no", "off" and "0" are false; anything else is an error rather than false. A setting the operator spelled "ture" is a setting they believe is on.

      Throws:
      IOException
    • describe

      public String describe()
      What was read, for a start-up line. NEVER any value: the datasource URL holds a password, and a configuration dump is how it reaches a log.