Gradle: Override exclude config made in a plugin - gradle

I'm developing a Liferay 7.2 theme (WAR-style) using Liferays "Gradle Theme Builder". I configured it to generate CSS source maps, too. This works fine, except that the original SCSS files are not deployed with the theme WAR file -- the source maps, on the other hand, are deployed. In the end, the DevTools in the browser ask the server for about 200 non-existent SCSS source files, which I cannot assign by hand to a local file (it looks like Firefox and Chrome removed that feature a while ago; and no matter how much I play with local files and workspaces in the DevTools, I cannot get the browser to recognize the local files as "these are the sources I'm looking for!").
I tried to configure the gradle war task to include those scss files in the resulting WAR, but:
The Theme Builder is a gradle plugin which configures the war task programmatically and sets an exclude to **/*.scss (see the sources here). Changing that plugin is out of question, so how can I override that exclude in my build.gradle?
Alternatively, I tried to run a second war task after the first, with the intention of adding those scss files to the existing WAR file (having the added benefit of a different task to run if I want a "theme development build"):
task fragmentWAR(type: War) {
group 'build'
description 'Prepares a war with scss files'
dependsOn war
from('build/buildTheme') {
include '**/*.scss'
exclude '**/.sass-cache'
}
}
task fragmentDeploy {
group 'build'
description 'Goes to war with scss files'
dependsOn += fragmentWAR
dependsOn += deploy
}
deploy.mustRunAfter(fragmentWAR)
But that messes up the WAR file: some files are now created twice in the WAR, others are missing completely.
In the end, I need a way to deploy the scss files along with the transpiled css and the css source maps into my testing server. Has anybody got any idea how to circumvent that exclude configured by the theme builder plugin -- or any other idea that might help me here?

Have you tried using the generator-liferay-theme NPM module instead of the Gradle Theme Builder plugin? Use v9.x of generator-liferay-theme for Liferay 7.2.
See
https://github.com/liferay/liferay-js-themes-toolkit and
https://github.com/liferay/liferay-js-themes-toolkit/tree/master/packages/generator-liferay-theme for more details.
When I generate my theme using this module, I see that both .scss and .css.map are files included in my theme .war file.
Hope it helps.

Related

Add a file to a specific folder with gradle build

I am currently working with a project (using gradle) that needs a properties file in the same package to the class that consumes it (I can't change this config). I have added the file in my package, but when I execute the gradle build command omits the file, and only adds the .class file. The app is deployed as a war file.
I have tried editing the war task, but I can't find the way to make the properties file to be added:
war {
from('src/main/com/foo/bar') {
include 'b.properties'
into 'WEB-INF/classes/com/foo/bar'
}
}
The war task does execute (I have added a prinln and it executes). Also, I have tried changing the paths, but no results. Also replacing from('path') to from (file('path')), but still doesn't seem to add the file anywhere.
How should I achieve this? Thanks!
Is there anything stopping you from following Gradle's convention for resources?
Eg put your property file at src/main/resources/com/foo/bar/b.properties
If you do this you won't need any task customisations

Where to put external config files in a Kotlin Gradle project?

I use a standard Maven/Gradle project structure putting source code under src/main/kotlin and automatically collected resources under src/main/resources:
\myapp
-\src
-\main
-\kotlin
-\com
-\projectname
-\MyApp.kt
-\resources
- som_file.txt
This works fine to package my distribution with the distZip task and all resources end up in a jar which is then zipped into the following structure:
myapp
-\bin\
-\libs\
I am not sure where to put external config files in my Kotlin project (e.g. db.config) which the user could edit later. Is there a correct location for external config files in Gradle project?

Corda: Import a local javascript library into a node

I'm using the J2V8 library to run some javascript functions in the cordapp, but I'm having troubles to access the js files (or refer to them) during runtime, because when the project is built the js code is copied into the build/resources folder, not reachable from any running node (as far as I know).
I realized that I need to include the js source code into the corda.jar files, produced when I run gradle deployNodes.
I tried to add the following to the build.gradle file:
jar {
baseName = 'something'
from('src/main/resources/js_library') {
include '*.js'
}
}
but it doesn't solve my problem. Do I need to extend some tasks in the net.corda.plugins in some way? Or is there a way to access the build/resource folder once the cordapp is running?
The corda.jar is the node JAR that your applications are intended to run on/against and it isn't intended to be modified for apps.
Your own CorDapp JAR should be generated automatically by the "jar" task if you're applying the correct gradle plugin (cordformation for V1, cordapp for later versions). This JAR will be on the classpath and contain all of the files in your resources directory. For example "src/main/resources/js_library" will be available in the root of the CorDapp JAR and can be accessed directly during runtime from the classloader of any of the classes in your CorDapp. See the answer here to learn how to access files within a JAR.

How do I prevent Gradle from building a non-project directory?

In the Gradle samples (included with version 2.2.1) there is a java/multiproject project.
The settings.gradle file defines the following projects:
include "shared", "api", "services:webservice", "services:shared"
Note that services is not itself a project, merely a directory which contains the webservice and shared projects.
When I run the command gradle build from the root directory, I notice that after gradle successfully builds it creates inside the /services directory a /build directory containing /lib and a /tmp directories.
Inside of /services/build/lib is a jar: services-1.0.jar which contains very little; specifically just a META-INF/MANIFEST.MF file containing:
Manifest-Version: 1.0
provider: gradle
So what is causing Gradle to build a jar for this non-project? And how can I prevent this behavior in my similarly structured multiproject project?
/services isn't a project, I don't want to create anything inside /build folder at all. Yes I could just delete it, but I would like to avoid the unnecessary work of building this jar/running any tasks on this non-project in the first place.
To be honest I've no reasonable idea why gradle builds this folder. I guess that because it's a kind of a transient folder. However it can be excluded by adding the following piece of code to main build.gradle script:
project(':services').jar { onlyIf { false } }
Desired effect (services.jar elimination) can be also obtained with the following settings.gradle content:
include "shared", "api", "services/webservice", "services/shared"
File instead of project paths are included.
My guess would be that this is a combination of the next 2 gradle rules:
When you're including subprojects in the build.settings file using the include keyword according to Gradle Documentation here:
the inclusion of the path 'services:hotels:api' will result in
creating 3 projects: 'services', 'services:hotels' and
'services:hotels:api'.
In simple words, this means that the inclusion of services::webservice will also build the services project
The bulid.gradle file in your root that applies the 'java' plugin. According to Gradle Documentation here every configuration defined in the root.gradle takes effect for all sub projects. This means that it will also hold as the default configuration for the services project. As the 'java' plugin was applied a jar will be created, but as there is no src/main folder under the services directory nothing will be compiled and the jar will include only a META-INF/MANIFEST.MF file.

Gradle dependency destination on non-jar config file

I can create a dependency to something other than a jar file like this:
dependencies {
compile files("../other-project/config.txt")
}
The above works fine, except that config.txt ends up in the WEB-INF/lib folder of my war file. Instead I need it to be in WEB-INF/classes in the war file, and in src/main/resources for jettyRun.
How can I control where the dependency ends up? Or am I going about this the wrong way?
I can also solve this with a copy task, but this really is a dependency in that I don't need the file updated unless it changes. An unconditional copy would work, but I'd rather do this the right way.
The war task (as configured by the war plugin) puts dependencies into WEB-INF/lib, the web project's own code/resources into WEB-INF/classes, and web app content (which by default goes into src/main/webapp) into WEB-INF. Other content can be added by explicitly configuring the war task. For example:
war {
into("WEB-INF/classes") {
from "../other-project/config.txt"
}
}
One way to make this work with embedded Jetty (though maybe not the most convenient during development) is to use jettyRunWar instead of jettyRun. Another solution that comes to mind, particularly if the content to be added resides in its own directory, is to declare that directory as an additional resource directory of the web project (sourceSets.main.resources.srcDir "../other-project/someResourceDir"). This is in fact an alternative to configuring the war task. If the web project already has a dependency on the other project, you could instead configure an additional resource directory for that project.
Let's say you have configured a multi-project build with the following directory and file structure:
/combined-war
/main-project
/src
/webapp
/WEB-INF
web.xml
build.gradle
/other-project
/resources
/WEB-INF
/classes
config.txt
build.gradle
build.gradle
In order to allow jettyRun to combine the contents of the webapp directory from main-project with the contents of the resources directory in other-project you need to add a workaround to your build.gradle of main-project (I've adapted the one posted by the user siasia on gist).
Adding the same directory content to the war file is quite simple and is documented in the Gradle User Guide and and the DSL reference.
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'jetty'
import org.gradle.api.plugins.jetty.internal.JettyPluginWebAppContext
def newResourceCollection(File... resources) {
def script = '''
import org.mortbay.resource.ResourceCollection
new ResourceCollection(resources)
'''
def shell = new GroovyShell(JettyPluginWebAppContext.class.classLoader)
shell.setProperty("resources", resources as String[])
return shell.evaluate(script)
}
jettyRun.doFirst {
jettyRun.webAppConfig = new JettyPluginWebAppContext()
jettyRun.webAppConfig.baseResource = newResourceCollection(
// list the folders that should be combined
file(webAppDirName),
file("${project(':other-project').projectDir}/resources")
)
}
war {
from("${project(':other-project').projectDir}/resources")
}
Whenever you execute gradle jettyRun a new ResourceCollection is created that combines the given directories. Per default Jetty locks (at least on Windows) all the files it's serving. So, in case you want to edit those files while Jetty is running take a look at the following solutions.
Update
Since other-project in this case is not another Gradle project the two tasks in build.gradle should look like that:
jettyRun.doFirst {
jettyRun.webAppConfig = new JettyPluginWebAppContext()
jettyRun.webAppConfig.baseResource = newResourceCollection(
file(webAppDirName),
file("$projectDir/../other-project/resources")
)
}
war {
from("$projectDir/../other-project/resources")
}
I'm not aware of any solution that adds only one file (e.g. config.txt). You'll always have to add a complete directory.
As I mentioned above, it's simple enough to do an unconditional copy that solves the problem. Again, not the question I originally asked. But here's my solution that works for both war and jettyRun tasks:
processResources.doFirst {
copy {
from '../other-project/config.txt'
into 'src/main/resources'
}
}

Resources