How to use spring properties in gradle.build? - gradle

How can I use properties configured in resources/application.properties in gradle.build? I would like to get something like this :
flyway {
url = MAP_WITH_PROPERTIES['spring.datasource.url']
user = MAP_WITH_PROPERTIES['spring.datasource.username']
}

import java.util.Properties
def props = new Properties()
file('src/main/resources/application.properties').withInputStream {
props.load(it)
}
def url = props['spring.datasource.url']
def user = props['spring.datasource.username']

You can load properties and use them this way:
ext.ApplicationProps = new Properties()
ApplicationProps.load(new FileInputStream("src/main/resources/application.properties"))
And use it as follows:
flyway {
url = ApplicationProps['spring.datasource.url']
user = ApplicationProps['spring.datasource.username']
}
Just note, that path to the properties is defined from the root and may vary if you have a multimodule project.

Related

Hidden parameter in springdoc-openapi doesn't work

I have Spring Boot application with version 2.3.0.
and springdoc-openapi-webflux-ui in version 1.4.1.
I have annotated parameter in operation like this.
parameters = {
#Parameter(
hidden = true, schema = #Schema(implementation = Boolean.class),
in = ParameterIn.QUERY, name = DO_NOT_FORWARD
)
With hidden = true I expected that this parameter will not be visible in swagger-ui. But it is.
Did I misunderstood this parameter or is it not doing what it was supposed to do?
I want this parameter to be in api-docs, to have generated client able to use this parameter, but I want it invisible in swagger-ui
Try
#Parameter(name = "paramName", hidden = true)
#GetMapping("/example")
public Object example(String paramName) {
return null;
}
instead of
#Operation(
parameters = {
#Parameter(name = "paramName", hidden = true)
}
)
#GetMapping("/example")
public Object example(String paramName) {
return null;
}
You just make sure that the name of in the #Parameter annotation, is the exact name of the operation parameter you want to hide.
You can have a look at the documentation as well:
https://springdoc.org/faq.html#how-can-i-hide-a-parameter-from-the-documentation-
If you are still having coniguration issue, you can add the code of sample HelloController that reproduces your problem, or you can add the link to a minimal, reproducible sample in github.
As per the doc
#GetMapping("/example")
fun someCall: Response (
#Parameter(hidden = true) String paramName
) {
return response;
}

Gradle properties not visible inside extension container closure

I'm trying to write this custom plugin for Gradle but I'm stuck in properly passing parameters to the plugin.
inside the plugin I'm creating an extension like following:
#Override void apply(final Project p) {
p.extensions.create('myPlugin', MyPluginData.class)
then inside MyPluginData I'm handling def propertyMissing(String name, value) to receive the customer parameters I expect.
And finally inside the client application build.gradle I'm trying to configure the data:
println("From root value is " + SOME_VALUE)
myPlugin {
println("From plugin value is " + SOME_VALUE)
println("But from plugin 'findProperty' value is " + findProperty("SOME_VALUE"))
clientDataSet = {
data_1 = SOME_VALUE
data_2 = findProperty("SOME_VALUE")
data_3 = "this is a string"
SOME_VALUE is defined on my project gradle.properties, and I got the following log during build:
From root value is correct value from properties
From plugin value is null
But from plugin 'findProperty' value is correct value from properties
and then of course, while receiving data_1 SOME_VALUE is null, data_2 have the correct value and data 3 is the hard-coded string I passed.
My question:
What am I doing wrong or which configuration is missing on my plugin, so that the client application can directly reference properties from their gradle.properties files?
Edit: as requested on the comments
MyPluginData is simply extends HashMap<String, MyPluginDataSet> and MyPluginDataSet is just a few strings.
So inside propertyMissing I'm simply adding the property name to the map, and creating the MyPluginDataSet with the strings, (that later is used to generate custom tasks).
The missing property function:
def propertyMissing(String name, value) {
// Create the new data set and add to the map
def data = new MyPluginDataSet()
put(name, data)
// setup and execute the client closure to configure the data
def closure = value as Closure
closure.delegate = data
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.run()
}
By making MyPluginData inherit from Map<>, I think you somehow "break" the property resolution process ( see ExtensionAware) and Gradle will not try to search for "SOME_VALUE" property in the different scopes (so it will not find this property from gradle properties extension)
Maybe you can try to simplify you MyPluginData class by storing an internal map instead of inheriting from Map ? something like that:
class MyPluginData {
Map<String, MyPluginDataSet> internalMap = new HashMap<>()
def propertyMissing(String name, value) {
println "Entering propertyMissing for name = $name"
// Create the new data set and add to the map
def data = new MyPluginDataSet()
internalMap.put(name, data)
// setup and execute the client closure to configure the data
def closure = value as Closure
closure.delegate = data
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.run()
}
}

Is there a Groovier way to access properties file?

One can access properties file like that:
def props = new Properties()
new File('my.props').withInputStream { props.load(it) }
assert props.foo == 'bar'
I think that's quite cumbersome. Isn't there a groovier way?
// does not compile
def props = Properties.from(new File('my.props'))
assert props.foo == 'bar'
I believe the answer is no.
The doc for Groovy JDK enhancements does not contain java.util.Properties (compared to, say, java.io.File). This article implies prior art for a home-grown solution.
You can always utilize metaprogramming:
Properties.metaClass.static.from = { File f ->
def p = new Properties()
f.withInputStream { p.load(it) }
p
}
p = Properties.from(new File('a.properties'))
assert p['a'] == '10'
I'm not aware of any shortcut to create a properties from a file. I'd like to suggest a simple solution without prior variable declaration:
p = new File('my.props').withReader { reader ->
new Properties().with {
load reader
it
}
}

Grails Spring Security verify access for multiple url

I would like to verify if the user has access to more than one url, in a view, like this:
<sec:access url="/user,/client">
Just like the sec:ifAnyGranted tag for roles:
<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">
In my verifications, the sec:access url just works with one url.
Is there any way or alternative to this?
I'm using the spring-security-core:2.0-RC2 plugin for grails.
I don't thing multiple URLs is supported. You can create your own tag to do this like
class CustomTagLib {
static namespace = "myTag"
def ifAnyGranted = { attrs, body ->
List<String> urls = attrs.remove('urls').split(',')
Boolean hasAccess = Boolean.FALSE
for (int i = 0; i < urls.size(); i++) {
hasAccess = sec.access(url: urls.get(i).trim()) { Boolean.TRUE }
if (hasAccess) {
out << body()
break
}
}
}
}
and use it in the view like:
<myTag:ifAnyGranted urls="/domain/index,/domain/show">
Something to display if has access to anyone of the URL
</myTag:ifAnyGranted>

Zend Framework specific module session configuration

I'm trying to get a different session configuration for 2 modules.
In my application ini i have a modules set up like :
resources.modules[] =
resources.frontcontroller.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontcontroller.throwerrors = true
resources.layout.layout = "layout"
and for the sessions
resources.session.save_path = APPLICATION_PATH "/temp/session"
resources.session.use_cookies = true
resources.session.use_only_cookies = true
resources.session.gc_maxlifetime = 3600
resources.session.remember_me_seconds = 3600
resources.session.name = "sid"
resources.session.gc_probability = 1
backoffice.resources.session.save_path = APPLICATION_PATH "/temp/bo/session"
backoffice.resources.session.use_cookies = true
backoffice.resources.session.use_only_cookies = true
backoffice.resources.session.gc_maxlifetime = 3600
backoffice.resources.session.remember_me_seconds = 3600
backoffice.resources.session.name = "BOsid"
backoffice.resources.session.gc_probability = 1
but when i go the backoffice module i still have my default configuraton
Any idea what should be the best way to get different sessions for different modules ?
Thanks
I want to advise you another method of config customization for specific modules in ZF:
1. Create for each module config file: /modules/$moduleName/configs/module.ini
2. Add to the root Bootstrap the next code:
protected function _initBootstrap()
{
$_conf = new Zend_Config_Ini(APPLICATION_PATH . "/modules/" . $this->getModuleName() . "/configs/module.ini", APPLICATION_ENV);
$this->_options = array_merge($this->_options, $_conf->toArray());
}
I finally opted for a controller plug-in.
With some code like
class App_Controller_Plugin_Session extends Zend_Controller_Plugin_Abstract
{
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$config = Zend_Registry::get('config')->toArray();
if( $this->getRequest()->getModuleName() == 'backoffice' ) {
$conf = $config['sessionBackoffice'];
} else {
$conf = $config['sessionDefault'];
}
Zend_Session::setOptions($conf);
Zend_Session::start();
}
}
The plugin need to be added at first in the registerPlugin stack if you some other plugin that require sessions.
If you have a better solution i'm open.

Resources