Override property in application.groovy with external config in grails 3 - grails

There is no grails.config.locations property in grails 3 anymore, now Grails 3 uses Spring's property source concept instead, but how can I achieve the same behavior in grails 3 as it was in previous versions? Suppose I want to override some property property.to.be.overridden in application.grovy file with my external configuration file. How can I do it?

The equivalent of grails.config.locations is spring.config.location
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
Here is an example specifying configuration locations while launching a jar from the command line(These same arguments can be used inside of your ide)
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Also since you mention wanting to override properties it's useful to learn the way Spring Boot handles profile specific property files(Multiple profiles may also be specified)
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties

I solved this a slightly different way, so I could load an external YAML file.
Application.groovy
package com.mycompany.myapp
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean
import org.springframework.context.EnvironmentAware
import org.springframework.core.env.Environment
import org.springframework.core.env.PropertiesPropertySource
import org.springframework.core.io.FileSystemResource
import org.springframework.core.io.Resource;
class Application extends GrailsAutoConfiguration implements EnvironmentAware {
static void main(String[] args) {
GrailsApp.run(Application)
}
#Override
void setEnvironment(Environment environment) {
String configPath = System.properties["myapp.config.location"]
if (configPath) {
Resource resourceConfig = new FileSystemResource(configPath);
YamlPropertiesFactoryBean propertyFactoryBean = new YamlPropertiesFactoryBean();
propertyFactoryBean.setResources(resourceConfig);
propertyFactoryBean.afterPropertiesSet();
Properties properties = propertyFactoryBean.getObject();
environment.propertySources.addFirst(new PropertiesPropertySource("myapp.config.location", properties))
}
}
}
Then I specify the YAML file when I run it
command line
java -jar -Dmyapp.config.location=/etc/myapp/application.yml build/libs/myapp-0.1.war

Related

Not able to load LOG4J2.xml File from system environment variable

I am doing a web application using Tomcat in eclipse and I kept the log4j2.xml file in environment variable location.
using System environment variable
Variable name : sys_logroot
Variable value : D:\user\gouse
In this directory I have my log4j2.xml file.I am trying to use this log4j2.xml file in my application I am not able to load this xml file and no log files are created to my application.
How can I load an Log4j2.xml file into my application to get logs for my application?
Apache says (from here):
How do I specify the configuration file location?
By default, Log4j looks for a configuration file named log4j2.xml (not
log4j.xml) in the classpath.
You can also specify the full path of the configuration file with this
system property:
-Dlog4j.configurationFile=path/to/log4j2.xml
i.e. you have to set the system property at runtime to let log4j use it. Something like this:
String value = System.getenv("sys_logroot");
value = "file:" + value;
System.setProperty("log4j.configurationFile", value);
Important is to call this part before using classes logging. Here is my test code:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger logger = LogManager.getLogger(Main.class.getName());
public void doSomething() {
logger.debug("Do something");
}
}
Tester:
public class Tester {
public static void main(String[] args) {
String value = System.getenv("sys_logroot");
value = "file:" + value;
System.setProperty("log4j.configurationFile", value);
new Main().doSomething();
}
}

access configuration/property files from src/groovy

I have a file under src/groovy and I have some properties that are in my Config.groovy and in external property file too. Normally if one want access properties its possible to use grailsApplication .configuration.property.name expression. I want to be able to access all those properties from this file that is under src/groovy directory. What I've tried so far
import grails.util.Holders
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
println Holders.grailsApplication.config.property.name
}
}
gave me NPE saying that grailsAppliction is null
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
def grailsAppliction = ctx.grailsApplication.getObject()
println grailsAppliction.config.property.name
}
}
the same - NPE because grailsAppliction is null
Is it possible to handle this situation somehow? Thank you!
Use the below and see if it works
println Holders.config.property.name
You don't need grailsApplication when using Holders.
The examples below are probably a little more complex than what you need, but they show how to get a configuration property at build time. I use them to merge two configuration files, but you might not need to do that.
This method returns a config property when called here at the CompileEnd event.
You could define a similar method in your app's _Events.groovy file that calls your own configuration holder class.
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
class KeyAndSecret{
public static String consumerKey = ConfigurationHolder.config.consumerKey;
public static String consumerSecret = ConfigurationHolder.config.consumerSecret;
}
Try like this

Vaadin 7 : How to import JS files from custom path?

I am using Vaadin-7 and this answer was not fix for me .
I am trying to import my js file under myproject/WebContent/js/test.js . I used #JavaScript in my UI class as below..
#Theme("myTheme")
#SuppressWarnings("serial")
#Title("VaadinTest")
#JavaScript("js/test.js")
public class VaadinTest extends UI {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
}
}
But I got "NetworkError: 404 Not Found - http://localhost:8080/myproject/APP/PUBLISHED/js/test.js" error log in my firebug console.
So , how can I import js files from my custom directories ?
PS: Please don't be force me to create APP/PUBLISHED/ directory manually ! Thanks.
You can use app://:
#JavaScript({ "app://js/test.js" })
or use:
#JavaScript({ "vaadin://js/test.js" })
Generated url inside VAADIN folder:
http://localhost:8080/myproject/VAADIN/js/test.js
the file you refer to must be reachable by the classloader relative to the package you are using it in. according to your example, lets say your package of VaadinTest is com.example.app and you want to access it as js/test.js you have to put it in the directory com/example/app/js/test.js in a "root" for the classloader to find it (e.g. src/main/java,groovy or where resources are loaded from in your config).

Can't initialize Service in Grails Integration Test because of JNDI lookup

I have a service that implements InitializingBean and DisposableBean
class MyService implements InitializingBean, DisposableBean {
static transactional = false
def grailsApplication
#Override
void afterPropertiesSet() {
System.setProperty("JMS_TIMEOUT", grailsApplication.config.JMS_TIMEOUT);
// code performing a JDNI lookup
}
}
enter code here
The system properties are used to initialize some other components in the service. I have added the configs in Config.groovy.
grails.config.locations = [ "file:${basedir}/grails-app/conf/myconfig.properties" ]
This works fine when running the application. However I'm writing an integration test in test/integration that injects the service.
class MyServiceIntegrationTests extends GrailsUnitTestCase {
def myService
void testMyService() {
}
}
When running the test I get a StackTrace with the folllowing root cause:
Caused by: javax.naming.NameNotFoundException: Name [ConnectionFactory] not bound; 0 bindings: []
at javax.naming.InitialContext.lookup(InitialContext.java:354)
at com.ubs.ecredit.common.jmsclient.DefaultConnector.<init>(DefaultConnector.java:36)
Seems that the Config could not be loaded or are different in the Integration Tests. Any idea how I can change the config or code, so that these properties are also set for my integration test, before the service is instantiated?
UPDATE:
It turned out the cause was not the configurations but a JDNI lookup and a bug in Grails.
See: http://jira.grails.org/browse/GRAILS-5726
${basedir} gets different paths in different environments. As an alternative, you can use PropertiesLoaderUtils.loadProperties to load your customized configurations:
import org.springframework.core.io.support.PropertiesLoaderUtils
import org.springframework.core.io.ClassPathResource
....
void afterPropertiesSet() {
def configProperties = PropertiesLoaderUtils.loadProperties(
new ClassPathResource("myconfig.properties"))
System.setProperty("JMS_TIMEOUT", configProperties.getProperty("JMS_TIMEOUT"))
....
}
It turned out the cause was a JNDI lookup used by a library method, I have not shown in afterPropertiesSet() in my Service, which can be seen in the StackTrace.
After doing some research I found that this was a bug in Grails: http://jira.grails.org/browse/GRAILS-5726
Adding the mentioned workaround, resolved the issue for now.

Can't import java jar file into STS Grails project

I have built a new basic grails project. I have a basic java object I've written outside of grails, and jarred up. I've added the jar file to the grails project, via the properties > Java build path > Libraries tab > Add Jars.
Then I try to access it in a grails controller, and get a class def not found error.
What am I doing wrong?
TestController.groovy
package testproject
import test.TestClass
class TestController {
def index() {
def testClass = new TestClass()
render 'Index page'
}
}
and:
in the jar, TestClass.java
package test;
public class TestClass {
private String string;
public void setString(String string)
{
this.string = string;
}
public String getString()
{
return string;
}
}
The error is:
C:\Users\One\TestProject\grails-app\controllers\testproject\TestController.groov
y: 3: unable to resolve class test.TestClass # line 3, column 1.
import test.TestClass
The STS classpath generated from the Grails classpath, but it's unidirectional. Adding items in STS has no effect on Grails.
Put the jar file in your lib directory and run grails compile --refresh-dependencies. Then re-sync STS from Grails by right-clicking the project node in the tree and running Grails Tools | Refresh Dependencies.
You still need to import it in the Grails controller.
import your.java.ClassName

Resources