gradle custom war task webAppDirName - war

I have a few gradle war tasks in my build file, and I would like to change the webAppDirName per war task. I tried this:
task myWarTask(type: War) {
ext.webAppDirName = 'src/anotherfolder/webapp' // also tried just webAppDirName
version ""
destinationDir = file("$buildDir/libs")
baseName = 'myWarName'
classpath = configurations.myWarConfiguration
}
But this is still pulling in the contents of src/main/webapp instead of src/anotherfolder/webapp
Can I configure the webAppDirName on a per war file basis like this?

There is just one webAppDirName property per project, and the War plugin automatically adds a corresponding from to each War task. So the main problem is how to undo that from. I think the following should work:
apply plugin: "war"
webAppDirName = "non/existing/dir"
task myWarTask(type: War) {
from "src/anotherfolder/webapp"
...
}
An alternative is to only use the War task type, but not the War plugin. You'll have to configure a few more task properties then, and will lose a few features, mostly related to provided configurations and publishing of the War. Of course you can make up for this with explicit configuration (if necessary). If you are interested in the details, have a look at the source code for the War plugin.
PS: webAppDirName is not an extra property (ext.), but a convention property added by the War plugin. Extra properties are only meant for ad-hoc use in build scripts. You'd use ext. when writing an extra property, but omit it when reading the property.

task myWarTask(type: War) {
from 'src/anotherfolder/webapp'
version ""
destinationDir = file("$buildDir/libs")
baseName = 'myWarName'
classpath = configurations.myWarConfiguration
}

Related

Premake override for Vcpkg

I would like to be able to create a custom override to add a VcpkgConfiguration Property based on our current configuration.
We have a C++ project that uses Premake and vcpkg. We have found vcpkg to conflict with other projects that include their own versions of similar libraries, so we cannot use the global integration that it provides. Instead we have added it as a sub-module to our project and linked it through premake with a custom override:
p.override(p.vstudio.vc2010, "importExtensionTargets", function(base, prj)
p.push('<ImportGroup Label="ExtensionTargets">')
p.callArray(p.vstudio.vc2010.elements.importExtensionTargets, prj)
p.pop('</ImportGroup>')
p.push('<ImportGroup Label="ExtensionTargets">')
p.w('<Import Project="$(SolutionDir)External/vcpkg/scripts/buildsystems/msbuild/vcpkg.targets"/>')
p.pop('</ImportGroup>')
end)
Unfortunately we do not use the regular "Debug" or "Release" configurations in our project, so vcpkg by default does not link correctly. To get past that problem, we modified the vcpkg.targets file to recognize our configuration in a local branch. This is not ideal, as it forces us to rebase our branch off vcpkg in order to update it, and could potentially conflict if that file is ever modified in their repo.
The targets file allows you to set the VcpkgConfiguration property before including the target, which is what we would like to do.
Basically what we would like is to be able to call a command through the filters like this:
filter {"configurations:<SomeConfiguration>"}
VcpkgConfig "Debug"
Which would add this inside the propertygroup
<VcpkgConfiguration>Debug</VcpkgConfiguration>
How can we accomplish this?
The problem seems to be that importExtensionTargets is per project but you want this per configuration.
You can try to register your key word
api.register {
name= "VcpkgConfig",
scope = "config",
kind = "string",
}
then in your custom function
-- loop over all configurations
for _, cfgName in ipairs(prj.configurations) do
-- find config
local cfg = project.findClosestMatch(prj, cfgName)
if cfg.VcpkgConfig then
p.push('<ImportGroup Label="ExtensionTargets">')
p.push('<VcpkgConfiguration>'.. cfg.VcpkgConfig .. '</VcpkgConfiguration>')
p.w('<Import Project="$(SolutionDir)External/vcpkg/scripts/buildsystems/msbuild/vcpkg.targets"/>')
p.pop('</ImportGroup>')
end
Not tested.
Would this work ?

Can Premake propagate includedirs to dependency projects?

I have a project that's roughly structured as:
main.c
premake5.lua
moduleA/
premake5.lua
include/modulea.h
src/modulea.c
moduleB/
premake5.lua
include/moduleb.h
src/moduleb.c
My top level premake5.lua is fairly simple:
workspace "myproject"
configurations { "Debug", "Release" }
include "moduleA"
include "moduleB"
project "myproject"
kind "ConsoleApp"
language "C"
files { "main.c" }
includedirs { "." }
links { "moduleA" , "moduleB" }
I would like to be able to express my modules' configuration/dependencies without hard-coding conventions used in the containing project. Modules A and B will be re-used in other projects, so I want to avoid having to do:
project "moduleA"
kind "StaticLib"
-- files, etc
include { "..", "../moduleB/include" }
links { "moduleB" }
The include lines containing .. makes assumptions about a parent project structure that may not always hold.
Is there some way for a higher-level Premake script to "tell" these sub-projects "here is the base for includedirs/sysincludedirs"? Even if it involves writing those dependency projects in a different way to accept that information?
For example (and let me stress I don't know enough Lua or Premake to know how much sense this makes), my modules could say "make sure you set MODULE_INCLUDE_BASE and MODULE_SYS_INCLUDE_BASE" and then use:
project "moduleA"
-- etc
include { "%{MODULE_INCLUDE_BASE}/moduleB/include" }
Higher-level dependent projects could then... set?... these variables before including the dependency configs. (Again, this is just an example, maybe there's a more elegant way to do it.)
One option is to defer evaluation by wrapping the project call in a function itself:
function project_A()
project "moduleA"
kind "StaticLib"
language "C"
files { "moduleA/src/*.c" }
includedirs { '.' }
end
When this is called from the top level premake5.lua, the '.' is evaluated in the context of the top level script:
workspace "myproject"
configurations { "Debug", "Release" }
include "moduleA"
include "moduleB"
module_process()
module_protocol()
-- ...
Includes are then done relative to this top level script.
I would suggest checking the export module for premake
https://github.com/Meoo/premake-export
projects can define stuff that the need to export to other libraries or applications.
In turn other libraries can import the projects that they depend on
It's very handy and the syntax is very expressive !

spring boot/spring web app embedded version number

What are the strategies to embed a unique version number in a Spring application?
I've got an app using Spring Boot and Spring Web.
Its matured enough that I want to version it and see it displayed on screen at run time.
I believe what you are looking for is generating this version number during build time (Usually by build tools like Ant, Maven or Gradle) as part of their build task chain.
I believe a quite common approach is to either put the version number into the Manifest.mf of the produced JAR and then read it, or create a file that is part of the produced JAR that can be read by your application.
Another solution would be just using Spring Boot's banner customization options described here: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-banner
However, this will only allow you to change spring-boot banner.
I also believe that Spring Boot exposes product version that is set in Manifest.MF of your application. To achieve this you will need to make sure Implementation-Version attribute of the manifest is set.
Custom solution for access anywhere in the code
Lets assume you would like to have a version.properties file in your src/main/resources that contains your version information. It will contain placeholders instead of actual values so that these placeholders can be expanded during build time.
version=${prodVersion}
build=${prodBuild}
timestamp=${buildTimestamp}
Now that you have a file like this you need to fill it with actual data. I use Gradle so there I would make sure that processResources task which is automatically running for builds is expanding resources. Something like this should do the trick in the build.gradle file for Git-based code:
import org.codehaus.groovy.runtime.*
import org.eclipse.jgit.api.*
def getGitBranchCommit() {
try {
def git = Git.open(project.file(project.getRootProject().getProjectDir()));
def repo = git.getRepository();
def id = repo.resolve(repo.getFullBranch());
return id.abbreviate(7).name()
} catch (IOException ex) {
return "UNKNOWN"
}
}
processResources {
filesMatching("**/version.properties") {
expand (
"prodVersion": version,
"prodBuild": getGitBranchCommit(),
"buildTimestamp": DateGroovyMethods.format(new Date(), 'yyyy-MM-dd HH:mm')
)
}
}
processResources.outputs.upToDateWhen{ false }
In the code about the following is happening:
We defined a function that can take a build number out of the VCS
(in this case Git). The commit hash is limited to 7 characters.
We configure the processResources task to process
version.properties file and fill it with our variables.
prodVersion is taken from Gradle project version. It's usually set
as version in gradle.properties file (part of the general build
setup).
As a last step we ensure that it's always updated (Gradle
has some mechanics to detect if files ened to be processed
Considering you are on SVN, you will need to have a getSvnBranchCommit() method instead. You could for instance use SVNKit or similar for this.
The last thing that is missing now is reading of the file for use in your application.
This could be achieved by simply reading a classpath resource and parsing it into java.util.Properties. You could take it one step further and for instance create accessor methods specifically for each field, e.g getVersion(), getBuild(), etc.
Hope this helps a bit (even though may not be 100% applicable straight off)
Maven can be used to track the version number, e.g.:
<!-- pom.xml -->
<version>2.0.3</version>
Spring Boot can refer to the version, and expose it via REST using Actuator:
# application.properties
endpoints.info.enabled=true
info.app.version=#project.version#
Then use Ajax to render the version in the browser, for example using Polymer iron-ajax:
<!-- about-page.html -->
<iron-ajax auto url="/info" last-response="{{info}}"></iron-ajax>
Application version is: [[info.app.version]]
This will then show in the browser as:
Application version is: 2.0.3
I'm sure you've probably figured something out since this is an older question, but here's what I just did and it looks good. (Getting it into the banner requires you to duplicate a lot).
I'd recommend switching to git (it's a great SVN client too), and then using this in your build.gradle:
// https://github.com/n0mer/gradle-git-properties
plugins {
id "com.gorylenko.gradle-git-properties" version "1.4.17"
}
// http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
springBoot {
buildInfo() // create META-INF/build-info.properties
}
bootRun.dependsOn = [assemble]
And this in your SpringBoot application:
#Resource
GitProperties props;
#Resource
BuildProperties props2;
Or this way to expose those properties into the standard spring environment:
#SpringBootApplication
#PropertySources({
#PropertySource("classpath:git.properties"),
#PropertySource("classpath:META-INF/build-info.properties")
})
public class MySpringBootApplication {
and then referencing the individual properties as needed.
#Value("${git.branch}")
String gitBranch;
#Value("${build.time}")
String buildTime;

Asset management - maintaining reference to relative assets after concatenation and versioning

I know that L5 and Elixir are still under development, but I'm excited to start thinking about ways to reorganize my code. I think my question has more to do with asset management, in the context of L5 and Elixir.
Want to clarify how concatenation and versioning should be handled (in my case I'm using Elixir's styles() and version()). The issue I'm having is that the new file after concat/version will be located in a new folder, breaking any references to assets from the original css or js files.
For example, an original CSS file that has background-image: url('../img.png') will no longer work. I've tried a couple of things, but both are not ideal especially in the case of vendor plugins:
Move required assets over one-by-one (using mix.copy() for each folder of assets), to the new build path (ie. the build path used by Elixir's versioning).
Manually edit the paths in each asset file to refer to an absolute path
Although both of these options will make things work, I feel as though I may be missing something. It also becomes quite impractical when working with javascript plugins (ex. ones that come with their own images, fonts, stylesheets, etc).
Is there a more practical way of managing relative paths when concatenating and versioning?
Here is the solution for Laravel Elixir after you build for versioning.
For copy command you need reference it as full path.
var elixir = require('laravel-elixir');
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Less
| file for our application, as well as publishing vendor resources.
|
*/
elixir(function(mix) {
mix.version('themes/default/assets/css/styles.css')
.copy('public/themes/default/assets/img/', 'public/build/themes/default/assets/img/');
});
EDIT:
I just submitted a pull request to Elixir, so you can just do:
mix.version(
['css/style.css', 'css/vendor/style.css'], //files to be versioned
['fonts', 'css/vendor/icons'] //dependent files/dirs to be copied
);
OLD ANSWER:
Actually, if you use mix.copy(...) alone, you just can't use gulp watch and you'll need to recompile your entire stack in order to get this working.
You can achieve the same results with the solution below and don't need to recompile everything, because it'll just work when you change a versioned file:
var shell = require('gulp-shell');
gulp.task('cp', shell.task(['cp -R public/fonts public/build/',
'cp -R path/to/vendor/dir public/build/vendor/',
'... etc ...']));
elixir(function(mix) {
...
//register a watcher to run 'cp' when you rebuild
mix.task('cp','public/build/**/*.(js|css)');
}
They are relative paths - so keep the relative relationship.
Just move the images over to the public/build/ directory as part of the gulp command, after the visioning.

JDO + datanucleus API enhancement

I want to load dynamically XML meta-data files that are not in the classpath (the XML meta-data files will be generated after launching my app).
I thought I could call the method
MetaDataManager.registerFile(java.lang.String fileURLString, FileMetaData filemd, ClassLoaderResolver clr)
Then, I tried the API enhancement, so I added the following lines:
JDOEnhancer enhancer = JDOHelper.getEnhancer();
enhancer.setVerbose(true);
enhancer.addClasses(ClassToPersist.class.getName()).enhance();
getClass().getClassLoader().loadClass(ClassToPersist.class.getName());
The following jars are in the classpath: datanucleus-api-jdo.jar, datanucleus-connectionpool.jar, datanucleus-core.jar datanucleus-rdbms.jar, jdo-api.jar, asm.jar.
But when I launch my app, I get this exception:
Caused by: mypackage.MyException:
org.datanucleus.api.jdo.exceptions.ClassNotPersistenceCapableException: The class "mypackage.ClassToPersist" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
Do you please have any idea how to fix this ?
PS: I also noticed that the method enhance returns 0 which indicates that the class has not been enhanced (we could exclude the other options)
Thanks
I think I found an easy way to fix this.
At runtime, I created a jar that contains the updated metadata file as META-INF/package.jdo. Then I added this jar to the classpath as described here
Using this hacks, I didn't need to re-enhace my class since it is enhanced after compilation.
(But for information, I had to call JDOEnhancer.addFiles() to enhance my class.)
So your call to loadClass has loaded the unenhanced class (since it would have been loaded in order to perform the enhancement presumably), and you didn't follow the tutorial that is provided at http://www.datanucleus.org/documentation/development/dynamic_class_metadata_enhance_runtime.html

Resources