Giter Site home page Giter Site logo

external-config's Introduction

External-Config

Tests

This plugin will mimic the Grails 2 way of handling external configurations defined in grails.config.locations.

It also provides scripts to convert between yml & groovy config.

Versions

Grails external-config
6.1.1 4.0.0
5.3.5 3.2.0
5.0.x 3.0.0
4.x.x 2.0.1
3.3.x 1.4.0

Creator and contributors

Plugin creator

Major contributors

Thank you!

Installation

Note: New coordinates! Not published with grails.org.plugins coordinates since BinTray went out of business. Now published under dk.glasius

Add dependency to your build.gradle:

dependencies {
    implementation 'dk.glasius:external-config:4.0.0' // or latest version
}

Usage

When you add this plugin to your Grails build, it will automatically look for the property grails.config.locations. Define this in either application.yml like this:

grails:
    config:
        locations:
            - classpath:myconfig.groovy
            - classpath:myconfig.yml
            - classpath:myconfig.properties
            - file:///etc/app/myconfig.groovy
            - file:///etc/app/myconfig.yml
            - file:///etc/app/myconfig.properties
            - ~/.grails/myconfig.groovy
            - ~/.grails/myconfig.yml
            - ~/.grails/myconfig.properties
            - file:${catalina.base}/myconfig.groovy
            - file:${catalina.base}/myconfig.yml
            - file:${catalina.base}/myconfig.properties

or in application.groovy like this:

grails.config.locations = [
        "classpath:myconfig.groovy",
        "classpath:myconfig.yml",
        "classpath:myconfig.properties",
        "file:///etc/app/myconfig.groovy",
        "file:///etc/app/myconfig.yml",
        "file:///etc/app/myconfig.properties",
        "~/.grails/myconfig.groovy",
        "~/.grails/myconfig.yml",
        "~/.grails/myconfig.properties",
        'file:${catalina.base}/myconfig.groovy',
        'file:${catalina.base}/myconfig.yml',
        'file:${catalina.base}/myconfig.properties',
]

It is also possible to define it in an environment specific block (yml):

environments:
    test:
        grails:
            config:
                locations:
                - ... 

or (groovy)

environments {
    test {
        grails {
            config {
                locations = [...]
            }
        }
    }
}   

~/ references the users $HOME directory. Notice, that using a system property you should use single quotes because otherwise it's interpreted as a Gstring.

The plugin will skip configuration files that are not found.

For .groovy and .yml files the environments blocks in the config file are interpreted the same way, as in application.yml or application.groovy.

Wildcard support

It is possible to use * as wildcards in the filename part of the configuration:

grails:
    config:
        locations:
            - file:/etc/app/myconfig*.groovy
            - ~/.grails/myconfig*.groovy

or

grails.config.locations = [
        "file:/etc/app/myconfig*.groovy",
        "~/.grails/myconfig*.groovy",
]

Note: that it only works for the file: and ~/ prefix.

Note: the wildcards are in the order they are found in the locations list, but the order of the expanded locations for each wildcard is not guaranteed, and is dependent on the OS used.

Getting configuration from another folder than /conf on classpath without moving it with Gradle script

If you wish to make your Grails application pull external configuration from classpath when running locally, but you do not wish to get it packed into the assembled war file (i.e. place the external configuration file in e.g. /external-config instead of /conf), then you can include the external configuration file to the classpath by adding the following line to build.gradle

tasks.named('bootRun') {
    doFirst {
        classpath += files("external-config")
    }
}

tasks.withType(Test) {
    doFirst {
        classpath += files("external-config")
    }
}

or alternatively add this to your dependencies:

provided files('external-config') // provided to ensure that external config is not included in the war file

Alternatively, you can make a gradle script to move the external configuration file to your classpath (e.g. /build/classes)

Micronaut support

The plugin will register the locations in grails.config.locations as micronaut.config.files. Please note, that Micronaut will fail, if it does not recognise the file extension.

Scripts

This plugin also includes two scripts, one for converting yml config, to groovy config, and one for converting groovy config to yml config. These scripts are not guaranteed to be perfect, but you should report any edge cases for the yml to groovy config here: https://github.com/virtualdogbert/GroovyConfigWriter/issues

grails yml-to-groovy-config has the following parameters:

  • ymlFile - The yml input file.
  • asClosure - An optional flag to set the output to be closure based or map based. The Default is closure based
  • outputFile - The optional output file. If none is provided, then the output will go to System.out.
  • indent - Optional indent. The default is 4 spaces
  • escapeList - An optional CSV list of values to escape, with no spaces. The default is 'default'

Sample usage

grails yml-to-groovy-config [ymlFile] [optional asClosure] [optional outputFile] [optional indent] [optional escape list]

grails groovy-to-yml-config has the following parameters:

  • groovy - The groovy input file.'
  • outputFile - The optional output file. If none is provided, then the output will go to System.out.
  • indent' - Sets the optional indent level for a file. The default is 4
  • flow - Sets the optional style of BLOCK or FLOWS. The default is BLOCK.

Sample usage

grails groovy-to-yml-config [ymlFile] [optional outputFile] [optional indent] [optinal flow]

external-config's People

Contributors

akrehl avatar andersaaberg avatar dvkvarma avatar erichelgeson avatar hayeskl avatar jdaugherty avatar jespersm avatar longwa avatar painfulcranium avatar raurquhart avatar rlovtangen avatar sbearcsiro avatar sbglasius avatar sdelamo avatar snimavat avatar tkvw avatar virtualdogbert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

external-config's Issues

Consistent way to reference configuration properties defined in canonical files

Let's assume in my application.groovy file (or either in application.yml with proper syntax) I defined a property

host = 'app.domain.com'

I then defined a custom configuration additionalConf.properties file with content

query = ?dummy
baseUrl = https://${host}/path${query}

Then printing the value for baseUrl (in any Controller or Bootstrap):

println Holders.config.baseUrl
> https://app.domain.com/path?dummy

which is excellent.
When switching instead from .properties to .groovy file, with revised content as

query = '?dummy'
baseUrl = 'https://${host}/path${query}'

(basically adding quotes around strings), I get:

println Holders.config.baseUrl
> https://[:]/path?dummy

It would be really great to have the resulting behavior for the source .groovy file (and also .yml) be the same as the one for .properties file.

cannot set logging parameters

I've been strugging in grails with the question of how to set an external logback.groovy location. I don't want to use -D on the command line because if you deploy in Tomcat that forces all apps to share the one config.

So I thought I'd found the solution in this external-config library. All I should have to do is set the location in an external config:

my-config.yml:

server.port: 8082
logging.config: logback.groovy
dataSource:
    url: jdbc:oracle:thin:@oracle-blah
    username: _user
    password: something

but it doesn't seem to get picked up. Note that I haven't set the parameter logging.config anywhere inside my app, or in application.yml . But I do have my application.yml set to pickup my-config.yml. I know this is working because it starts on 8082 and not the default 8080.

So if I run my app:

java -jar myapp.jar

and if logback.groovy doesn't exist, then it starts fine, no complaints. But if I do:
LOGGING_CONFIG=logback.groovy java -jar myapp.jar

It dies because logback.groovy doesn't exist.

Or in other words, setting logging.config using one of the normal grails mechanisms to some file that isn't there, crashes as expected. Setting it using this plugin does not.

Or in other words, this plugin is broken with regards to setting logging config.

I'm guessing this is because this plugin does whatever it does after logging has been initialized. But it really needs to do it earlier in the startup sequence. I think one of the spring callbacks should be able to do that, but I was hoping not to have to figure all that out by using this plugin.

Grails 3 Startup Fails on Windows

Grails Startup is failing on windows with the following exception.

Caused by: java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
	at java.util.regex.Pattern.error(Unknown Source)
	at java.util.regex.Pattern.compile(Unknown Source)
	at java.util.regex.Pattern.<init>(Unknown Source)
	at java.util.regex.Pattern.compile(Unknown Source)
	at java.lang.String.split(Unknown Source)
	at java.lang.String.split(Unknown Source)
	at grails.plugin.externalconfig.ExternalConfigRunListener.handleWildcardLocation(ExternalConfigRunListener.groovy:91)
	at grails.plugin.externalconfig.ExternalConfigRunListener$_getLocations_closure1.doCall(ExternalConfigRunListener.groovy:79)
	at grails.plugin.externalconfig.ExternalConfigRunListener$_getLocations_closure1.call(ExternalConfigRunListener.groovy)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.collectMany(DefaultGroovyMethods.java:3462)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.collectMany(DefaultGroovyMethods.java:3437)

Issue with Separator being \ in windows. \ is being considered as a regular expression.

String locationFileName = location.split(separator)[-1]

Probably replacing split with tokenize might solve the issue.

Utilize the SpringApplicationRunListener instead of trait

Right now the plugin forces the apps to implement the trait which doesnt look that clean.
Instead the plugin can utilize the SpringApplicationRunListener and implment method environmentPrepared and do the stuff what it currently does in setEnvironment.
That would make the plugin less invasive and apps wont need to implement any trait it self..
it would be more plug and play

See SpringApplicationRunListener -- will need to have a spring.factories file

Version 1.2.0+ not working in Grails 3.2

Version 1.2.0+ throws the following exception in Grails 3.2.13:

06.12.2018 01:07:03 ERROR SpringApplication - #: Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grailsApplicationPostProcessor' defined in grails.Application: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [grails.boot.config.GrailsApplicationPostProcessor]: Factory method 'grailsApplicationPostProcessor' threw exception; nested exception is org.grails.core.exceptions.GrailsRuntimeException: Failed to introspect class: class external.config.Application
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1177)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1071)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:372)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.ui.command.GrailsApplicationContextCommandRunner.run(GrailsApplicationContextCommandRunner.groovy:55)
        at grails.ui.command.GrailsApplicationContextCommandRunner.main(GrailsApplicationContextCommandRunner.groovy:102)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [grails.boot.config.GrailsApplicationPostProcessor]: Factory method 'grailsApplicationPostProcessor' threw exception; nested exception is org.grails.core.exceptions.GrailsRuntimeException: Failed to introspect class: class external.config.Application
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
        ... 17 common frames omitted
Caused by: org.grails.core.exceptions.GrailsRuntimeException: Failed to introspect class: class external.config.Application
        at grails.core.ArtefactHandlerAdapter.isArtefact(ArtefactHandlerAdapter.java:129)
        at grails.core.DefaultGrailsApplication.addOverridableArtefact(DefaultGrailsApplication.java:772)
        at org.grails.plugins.AbstractGrailsPluginManager.registerProvidedArtefacts(AbstractGrailsPluginManager.java:310)
        at grails.boot.config.GrailsApplicationPostProcessor.performGrailsInitializationSequence(GrailsApplicationPostProcessor.groovy:110)
        at grails.boot.config.GrailsApplicationPostProcessor.initializeGrailsApplication(GrailsApplicationPostProcessor.groovy:93)
        at grails.boot.config.GrailsApplicationPostProcessor.setApplicationContext(GrailsApplicationPostProcessor.groovy:225)
        at grails.boot.config.GrailsApplicationPostProcessor.<init>(GrailsApplicationPostProcessor.groovy:77)
        at grails.boot.config.GrailsAutoConfiguration.grailsApplicationPostProcessor(GrailsAutoConfiguration.groovy:68)
        at grails.Application.grailsApplicationPostProcessor(Application.groovy)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1427)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
        ... 18 common frames omitted
Caused by: java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
        at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
        at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
        at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
        at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
        at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
        at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
        at java.lang.Class.createAnnotationData(Class.java:3521)
        at java.lang.Class.annotationData(Class.java:3510)
        at java.lang.Class.getAnnotation(Class.java:3415)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlClassGetAnnotation(ReflectiveInterceptor.java:312)
        at org.grails.core.artefact.DomainClassArtefactHandler.doIsDomainClassCheck(DomainClassArtefactHandler.java:141)
        at org.grails.core.artefact.DomainClassArtefactHandler.isDomainClass(DomainClassArtefactHandler.java:130)
        at org.grails.core.artefact.DomainClassArtefactHandler.isArtefactClass(DomainClassArtefactHandler.java:118)
        at grails.core.ArtefactHandlerAdapter.isArtefact(ArtefactHandlerAdapter.java:125)
        ... 32 common frames omitted
Context failed to load: Error creating bean with name 'grailsApplicationPostProcessor' defined in grails.Application: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [grails.boot.config.GrailsApplicationPostProcessor]: Factory method 'grailsApplicationPostProcessor' threw exception; nested exception is org.grails.core.exceptions.GrailsRuntimeException: Failed to introspect class: class external.config.Application

Version 1.1.2 works fine.

Allow regex in location paths

Currently, the plugin only allow the definition of an exact file path, as /home/bruno/.grails/config.groovy (or ~/.grails/config.groovy).

But, as an application grows, it make sense to use multiple configuration files, for instance, redis.groovy (to configure redis), ldap.groovy (to configure ldap), and so on. It increases readability and organization of the configurations.

Following Grails philosophy, it would be nice if each team could create a convention, and define for instance, that all configuration files begin with a prefix, like 'config-'. In this sense, the plugin should allow to define a location like this:

/home/bruno/.grails/config-*.groovy

This way, when someone needs to add a config file, if the file name follows the convention, it can be recognized without the need of changing application.groovy.

external-config plugin is compiled with Java8

Grails3 supports Java7 (see http://docs.grails.org/latest/guide/gettingStarted.html) which is a requirement from my customer, but the external-config plugin is compiled with Java8 and that prevents us from using it.

I get the following error when using 'org.grails.plugins:external-config:1.1.1':

Exception in thread "main" java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.boot.SpringApplicationRunListener : grails.plugin.externalconfig.ExternalConfigRunListener
        at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:425)
        at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:404)
        at org.springframework.boot.SpringApplication.getRunListeners(SpringApplication.java:390)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:388)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:375)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at myapp.Application.main(Application.groovy:8)
Caused by: java.lang.UnsupportedClassVersionError: grails/plugin/externalconfig/ExternalConfigRunListener : Unsupported major.minor version 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
        at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:417)
        ... 11 more
:bootRun FAILED

I verified this by looking up the class in the external-config-1.1.1.jar:
file ExternalConfigRunListener.class
ExternalConfigRunListener.class: compiled Java class data, version 52.0 (Java 1.8)

Solution:
I downloaded the latest external-config plugin source to my local machine and added "sourceCompatibility=1.7" to build.gradle such that the produced artifact is Java7 compatible regardless of jdk version used to produce it. All the plugin tests ran (gradle check) without issues and I was able to use the external-config plugin in my application (from mavenLocal repository). I am happy to help with creating a new release, but I could use some guidance on how to release it. I have setup binTray (user: andersaaberg), but "gradle clean bintrayUpload" yields "HTTP/1.1 403 Forbidden".

In general, it would be very helpful with a mechanism to ensure that grails plugins are released with Java 7 or clearly marked as requiring a later Java version - maybe we can use some kind of rule to ensure that sourceCompatibility is always set for plugins?

Error at `password = AESCodec.decode("...")` in an external app.groovy

using an env.groovy in tomcat config folder with

environments {
   abc {
      username = "app_test"
      password = AESCodec.decode("***")
      ...
   }
   ...
}

this results in an error (log file):

...
org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive [.../webapps/ROOT.war]
	java.lang.IllegalStateException: Error starting child
		at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:714)
		at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:687)
		at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:660)
		at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1016)
		at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1903)
		at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
		at java.util.concurrent.FutureTask.run(FutureTask.java:266)
		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
		at java.lang.Thread.run(Thread.java:750)
	Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
		at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:419)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:186)
		at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:710)
		... 9 more
Caused by: groovy.lang.MissingMethodException: No signature of method: groovy.util.ConfigObject.decode() is applicable for argument types: (String) values: [***]
...

Plugin does not work with Grails 3.3.0.M2

Steps to reproduce

Create an app with Grails 3.3.0.M2

Add the dependency: compile "org.grails.plugins:external-config:1.1.0"

Run gradlew bootRun

Exception in thread "main" java.lang.AbstractMethodError
        at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:388)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:375)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at externalconfig.Application.main(Application.groovy:8)
:bootRun FAILED

Misleading release description and wrong groupId

https://github.com/sbglasius/external-config/releases/tag/2.0.1 has a misleading description: "No code changes, but has moved to a new repository and new coordinates.". There are actually some bugfixes included: 2.0.0...2.0.1 - which e.g. fixes #50 (and many thanks for that!)

the new artifact has a different groupId than mentioned in README.md - README.md says "dk.glasius.external-config" but the actual groupId is "dk.glasius": https://search.maven.org/search?q=a:external-config

PR to update the README.md: #52

Cannot Start App In Grails 4

Getting the following error after installing 1.4.0 and attempting to run a Grails 4 app:

2019-08-11 13:05:55.038 ERROR --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

java.lang.AbstractMethodError: null
	at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:71)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:317)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:97)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:458)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:445)
	at com.collegeswapshop.Application.main(Application.groovy:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

And then later in the logs:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field urlMappingsHolder in org.grails.web.mapping.DefaultLinkGenerator required a bean of type 'grails.web.mapping.UrlMappingsHolder' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)
	- @org.springframework.beans.factory.annotation.Qualifier(value=grailsUrlMappingsHolder)


Action:

Consider defining a bean of type 'grails.web.mapping.UrlMappingsHolder' in your configuration.

Still digging and with post a workaround if I find one.

Plugin doesn't handle environment specific values

In my application.yml when I specify a list a grails.config.locations item in the main block, everything works as expected and it loads the configuration files as listed. If I include the same list of items in the environments.development.grails.config.locations (for example), the list of files is not read in nor processed. As an experiment, I was able to work around this by copying the ExternalConfig trait and editing it to load the environment properties if they exist and the general ones otherwise:

String environmentString = "environments.${environment.getActiveProfiles()[0]}.grails.config.locations"
List environmentLocations = environment.getProperty(environmentString, ArrayList, [])
List locations = environmentLocations.size() > 0 ? environmentLocations : environment.getProperty('grails.config.locations', ArrayList, [])

Grails 4: Issue on startup with Grails 4 and JDK 11

Grails 4 master & JDK 11.0.1 zulu

Example:
https://github.com/erichelgeson/grails4/compare/eric/externalConfig

2019-01-14 16:50:38.293 ERROR --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

java.lang.AbstractMethodError: Receiver class grails.plugin.externalconfig.ExternalConfigRunListener does not define or inherit an implementation of the resolved method abstract started(Lorg/springframework/context/ConfigurableApplicationContext;)V of interface org.springframework.boot.SpringApplicationRunListener.
	at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:72)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:95)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:447)
	at grails.boot.GrailsApp.run(GrailsApp.groovy:434)
	at four.Application.main(Application.groovy:11)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

runtime classpath is extensive.

The inclusion of the grails-bom as a platform brings in a lot of unneeded dependencies into the runtimeClasspath for users of this plugin

runtimeClasspath - Runtime classpath of source set 'main'.



|    +--- dk.glasius:external-config:3.1.1
|    |    +--- org.grails:grails-bom:5.2.3
|    |    |    +--- org.grails:grails-bootstrap:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-codecs:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-core:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-databinding:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-encoder:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-gradle-model:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-logging:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-codecs:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-controllers:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-databinding:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-datasource:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-domain-class:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-i18n:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-interceptors:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-mimetypes:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-rest:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-services:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-url-mappings:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-plugin-validation:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-shell:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-spring:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-boot:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-common:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-databinding:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-fileupload:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-mvc:5.2.3 -> 5.3.2 (c)
|    |    |    +--- org.grails:grails-web-url-mappings:5.2.3 -> 5.3.2 (c)
|    |    |    +--- javax.annotation:javax.annotation-api:1.3.2 (c)
|    |    |    +--- jakarta.annotation:jakarta.annotation-api:2.0.0 (c)
|    |    |    +--- io.micronaut:micronaut-aop:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-bom:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-inject:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-runtime:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-inject-groovy:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-core:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-http-client:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-http:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-buffer-netty:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut:micronaut-http-netty:3.5.4 -> 3.8.4 (c)
|    |    |    +--- io.micronaut.cache:micronaut-cache-core:3.4.2 -> 3.5.0 (c)
|    |    |    +--- io.micronaut.spring:micronaut-spring-context:4.1.1 -> 4.5.0 (c)
|    |    |    +--- org.grails:grails-datastore-core:7.3.2 -> 7.3.4 (c)
|    |    |    +--- org.grails:grails-datastore-web:7.3.2 -> 7.3.4 (c)
|    |    |    +--- org.grails:grails-datastore-gorm:7.3.2 -> 7.3.4 (c)
|    |    |    +--- org.grails:grails-datastore-gorm-support:7.3.2 -> 7.3.4 (c)
|    |    |    +--- org.grails:grails-datastore-gorm-validation:7.3.2 -> 7.3.4 (c)
|    |    |    +--- org.grails:grails-datastore-gorm-hibernate5:7.2.2 -> 7.3.1 (c)
|    |    |    +--- org.grails:scaffolding-core:2.1.0 (c)
|    |    |    +--- org.codehaus.groovy:groovy:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.codehaus.groovy:groovy-xml:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.codehaus.groovy:groovy-json:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.codehaus.groovy:groovy-sql:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.codehaus.groovy:groovy-templates:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.codehaus.groovy:groovy-dateutil:3.0.11 -> 3.0.13 (c)
|    |    |    +--- org.springframework:spring-aop:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-beans:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-context-support:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-context:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-core:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-expression:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-jdbc:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-jms:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-messaging:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-orm:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-test:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-tx:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-web:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.springframework:spring-webmvc:5.3.20 -> 5.3.25 (c)
|    |    |    +--- org.grails.plugins:async:4.0.0 (c)
|    |    |    +--- org.grails.plugins:events:4.0.0 (c)
|    |    |    +--- org.grails.plugins:gsp:5.2.1 -> 5.3.0 (c)
|    |    |    +--- com.h2database:h2:1.4.200 (c)
|    |    |    +--- org.grails.plugins:cache:5.0.1 (c)
|    |    |    +--- org.grails.plugins:scaffolding:4.1.0 (c)
|    |    |    +--- org.grails.plugins:fields:3.0.0.RC1 (c)
|    |    |    +--- org.grails.plugins:views-json:2.3.2 (c)
|    |    |    \--- org.grails.plugins:hibernate5:7.3.0 -> 7.3.1 (c)
|    |    +--- org.grails:grails-core -> 5.3.2 (*)
|    |    +--- org.codehaus.groovy:groovy-yaml:3.0.8 -> 3.0.13
|    |    |    +--- org.codehaus.groovy:groovy:3.0.13
|    |    |    +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.3 -> 2.13.5
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.13.5 (*)
|    |    |    |    +--- org.yaml:snakeyaml:1.31 -> 1.33
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.13.5 (*)
|    |    |    |    \--- com.fasterxml.jackson:jackson-bom:2.13.5 -> 2.14.0 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.13.3 -> 2.13.5 (*)
|    |    |    \--- org.codehaus.groovy:groovy-json:3.0.13 (*)
|    |    +--- io.micronaut:micronaut-core -> 3.8.4 (*)
|    |    +--- io.micronaut:micronaut-inject -> 3.8.4 (*)
|    |    +--- com.virtualdogbert:GroovyConfigWriter:1.1
|    |    \--- org.yaml:snakeyaml:1.30 -> 1.33

I don't think the below in the build file is the way this should be brought in as it includes the BOM content on the classpath

implementation(platform("org.grails:grails-bom:$grailsVersion"))

Grails 6 support

Grails 6.1 is out now and we have to upgrade our apps before Grails 5 becomes end-of-life (probably when Grails 7.x is released), but in order to upgrade we need this plugin upgraded to Grails 6.x as well.

Do let us know if upgrading of plugin to Grails 6.x is already in progress, otherwise we will attempt to do the upgrade in a pull request.

Enable default locations

It would be great if some locations would be searched by default for external configuration(s).

For this purpose I customized your grails.plugin.externalconfig.ExternalConfig this way:

...
@Override
    void setEnvironment(Environment environment) {
        println "start reading external config-file"
        List<String> defaultLocations = [
                "classpath:${appName}-config.properties",
                "classpath:${appName}-config.groovy",
                "file:${userHome}/.grails/${appName}-config.properties",
                "file:${userHome}/.grails/${appName}-config.groovy"]

        List locations = environment.getProperty('grails.config.locations', ArrayList, defaultLocations)
        String encoding = environment.getProperty('grails.config.encoding', String, 'UTF-8')

        for (location in locations) {
        ....

Maybe you got an idea how to add something like this.

Regards, Birger

The plugin does not work with Grails 5

I was using this plugin with Grails 4, and it does work like a charm.

But after updating to Grails 5, it stopped working.

Are there any plans to support Grails 5? Thanks in advance, and congratulations for this great plugin!

Is it possible to use logback.groovy configurations?

This is not a bug, but a question. I have different logback files per environment. In development mode, I would like to have it in a specific dir from my pc. In production, I would like to have it at my classpath. Is it possible to use the External Config plugin to achieve this? Thanks in advance.

Micronaut configuration properties cannot be loaded with external-config grails-plugin

In one of my projects, I'm using @ConfigurationProperties from Micronaut and that works very well... except when I put the configuration properties in an external configuration file and attempt to load the external configuration file using external-config grails plugin.

Here is a repo that reproduces the problem: https://github.com/andersaaberg/external-config-micronaut-configuration-property
If you start the application using ./gradlew bootRun, then it fails on upstart because @ConfigurationProperties does not receive the configuration from the external configuration file external-config/my-external-config.yml

However, the application starts up without any issue, if I comment out "- classpath:my-external-config.yml" in application.yml and comment in "my.number: 42".

Using application.yml is not really an option for me as I wish to put the properties in external config files. It work with external propertiy files if I use the JVM arguments "-Dspring.config.additional-location" + "-Dmicronaut.config.files", but I strongly prefer to use the external-config grails plugin.

Filter configuration files that don't exist from micronaut.config.files

A change in Micronaut made it such that startup fails if a specified configuration file doesn't exist (micronaut-projects/micronaut-core#2674)

This is different than the expectation for grails.config.locations where it is often used as a way to specify optional configuration.

I have opened a ticket on Micronaut suggesting they revert this change. However, in the mean time, if you try to run with Grails 5 and have any optional configuration files, startup will fail.

I have a change to this plugin to filter any missing configuration from the micronaut property. I will submit a PR shortly once I've finished fully testing.

Cannot inject lettuce from micronaut, when specifying redis.uri in external-config instead of application.yml

With Grails 4.0, I wanna use all the new fancy Micronaut tech. In my example project (https://github.com/andersaaberg/grails-external-config-lettuce), I have injected StatefulRedisConnection (from io.micronaut.configuration:micronaut-redis-lettuce) into a Grails controller (MyController) and made the index action ping redis. This does not work when "redis.uri"" is specified in an external config (external-config/my-config.groovy). It only works if "redis.uri" is specified in application.yml. To test that I have set "redis.uri" correct in the external-config, I have made an extra controller (ExtraController) which injects the configuration value using Spring @value.

I have made an integrationTest (ControllerSpec) that demonstrates this. The first test fails during injection of StatefulRedisConnection, because "redis.uri" cannot be read from the external config. The test will pass if "redis.uri" is set in application.yml. The second test always passes and just checks that "redis.uri" @value can be injected.

Maybe external-config is loaded too late, such that Micronaut injection has already happened?

Merging multiple groovy properties fails

Due to the way ConfigSlurper works, it is not possible to merge groovyConfig1.groovy:

base {
    config {
        groovy = 'groovy-expected-value'
    }
}

and groovyConfig2.groovy:

base.config.groovy2 = 'groovy2-expected-value'

and then retrieve base.config.groovy2

transitive external configs are not loaded

I have the following configuration block in my application.yml:

grails:
    config:
        locations:
            - classpath:envConfig.yml

The file envConfig.yml contains the following block:

test:
    grails:
        config:
            locations:
                - file:///path/to/file/dbConfig.yml

The dbConfig.yml file is not loaded, and so I am unable to use configuration values defined in it.

Failed to introspect class: class external.config.Application

Using grails 3.3.9 with external-config:1.3.0 or external-config:1.2.2 I have this error on startup.

Error creating bean with name 'grailsApplicationPostProcessor' defined in applicationname.Application: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [grails.boot.config.GrailsApplicationPostProcessor]: Factory method 'grailsApplicationPostProcessor' threw exception; nested exception is org.grails.core.exceptions.GrailsRuntimeException: Failed to introspect class: class external.config.Application

I checked Application.groovy file but is clean...

I can't understand where is the error...

Is there a way to reference external config from logback ?

Hi,
This is a question not a bug, but is there a way to reference external config file from logback.
I have an external properties file that contains the datasource, some variables I use in controllers and log configurations. Is there a way to retrieve this variables from logback ?
grails.util.Holders.applicationContext.getBean('grailsApplication') does not work.

Plugin wont work with Grails 3.3.x And spring boot 1.5.3

The contract for SpringApplicationRunListener interface has changed,
started() method has been renamed to starting()

Out ExternalConfig run listener does not provide the implementation for the new method, resulting in
Below exception while application is starting up

java.lang.AbstractMethodError
	at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)

It will prevent the app from starting.

Does not work with spring @Value annotation

Steps to reproduce:
In application.yml

some.value = 'initial'

In external/config.yml

some.value= 'overriden'

In someService:

@Value('${some.value'})
String value /// <-- initial

grailsApplication.config.getyProperty('some.value') // <--- overriden

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.