Best way to auto compile compass-style SASS via maven - maven

referring to SASS implementation for Java? :
What is the best way to auto-compile compass-style.org stylesheets in maven goal compile respectively package?
I would not like to ship too many self-compiled libraries nor do I want to dynamically ship compiled files via filters like https://code.google.com/p/sass-java ( https://github.com/darrinholst/sass-java )
Any alternatives than hooking up shellscripts / ant scripts which requires installed ruby and compass on the client?
What is the detailed difference between SASS and Compass Stylesheets, any problems with "sass-tools" when regularly using "compass"? => Which mvn plugins are "compass aware"?!

I suppose you know about this Maven plugin (mentioned in SASS implementation for Java?)? : https://github.com/Jasig/sass-maven-plugin
(I haven't tried it myself yet.)
UPDATE: that plugin is no longer supported. However, this fork seems to be healthy at present, so it might be an option for some: https://github.com/GeoDienstenCentrum/sass-maven-plugin

I found this, it's not a special compass/sass plugin but it works
https://gist.github.com/1671207

I was using the Sass Maven Plugin by nl.geodienstencentrum.maven but it uses Ruby and is very slow.
I've now switched to:
Libsass Maven Plugin
https://github.com/warmuuh/libsass-maven-plugin
This uses C and our compile times are much less (8.6 seconds to -> 2 seconds)

I tried several ways to compile my app (java, Wicket, using Zurb Foundation Sites, node-sass with depebndency of lib-sass). To tell you the truth, all the maven plugins were somewhere a deadend, especially when my scss contained the !global flag. (This flag came with foundations.)
So the final solution for us was to build with npm first then use maven.
Npm builds into src/main/webapp/"myDir" dir. I excluded this dir in git.
The jason file has a line like:
"scripts": {
....
"build-css": "node node_modules/node-sass/bin/node-sass --include-path myScssDir myScssDir/myScss.scss --output src/main/webapp/myDir/css",
....
}
Then build with maven and it will move the builded css ino my war.
For some help (create the nonexisting "myDir" dir) i used mkdirp.
In my jason there is:
"scripts": {
"create-dirs": "mkdirp src/main/webapp/myDir/",
....
}
So i run "npm i" to install all my dependencies locally into node-modules dir. This is gitignored.
Then i run "npm run create-dirs" to create the necessary myDir. This is gitignored as well.
Then i run "npm run build-css" to compile my css-s and js-s into myDir.
Finally i make a maven build.
With a hudson/jenkins build, you can easily do these in one job.
One improvement i can think of is to run npm via ant during maven build. I'll get back to you when i have a proof of concept of this.
//One extra hint: if you are developing under corporate environment and Windows7 you may have to add permissions to symbolic links for npm build. If you find errors in npm build, it worth a try: https://superuser.com/questions/104845/permission-to-make-symbolic-links-in-windows-7

Since libsass-is-deprecated, and the fork bases on the same "archived lib": https://github.com/bit3/jsass ..bases on libsass...
How do I migrate? ... Someone might find this useful:
[choco|brew|npm] install sass
Source: https://sass-lang.com/install
(I would not do it in ci, but we could!)
With the "good ole" exec-maven-plugin, adopted from Spring Petclinic (site|repo) (previously extracting webjars-bootstrap, originally they used that same libsass-maven-plugin):
<profile>
<id>css</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<!-- process-resources > genererate-resources (i.e. later)-->
<phase>process-resources</phase>
</execution>
</executions>
<configuration>
<!-- must be in $PATH !! -->
<executable>sass</executable>
<!-- it is quite silent, when everything works well -->
<useMavenLogger>true</useMavenLogger>
<arguments>
<!-- additional sass path(s), adjust to our suits -->
<argument>--load-path=${project.build.directory}/webjars/META-INF/resources/webjars/bootstrap/${webjars-bootstrap.version}/scss/</argument>
<argument>--no-source-map</argument>
<argument>--verbose</argument>
<argument>--trace</argument>
<!-- for more args, see https://stackoverflow.com/a/70228043/592355 // `sass` -->
<argument>${basedir}/src/main/scss/my.scss</argument>
<argument>/path/to/my/dest/my.css</argument>
</arguments>
<!-- more config, when we like ... -->
</configuration>
</plugin>
<!-- this is not part of the answer, but unpacks us required scss: -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<!-- genererate-resources < process-resources (i.e. prior)-->
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.webjars.npm</groupId>
<artifactId>bootstrap</artifactId>
<version>${webjars-bootstrap.version}</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/webjars</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Finally:
mvn process-resources -Pcss
(assuming no tests, no clean, no compile, "it is quite silent, when everything works well")

Related

maven - generate sources is not working

please advise if possible on this
I am running mvn package source:jar and get a module.jar and module-sources.jar as expected in the target directory
However, I have 2 issues:
1) I when I do : mvn install source:jar I get a -source.jar in my "target" in
the local projects folder, HOWEVER, NOT in the "local-repository (under .m2
on my PC). Even though, I do get a module.jar with binaries installed.
EDIT: I have figured this item (1): It works if I place "source:jar" before "install". That is mvn source:jar install instead of mvn install source:jar
2) I want to NOT HAVE TO run source:jar in the command line to generate the sources. Because, when I use GO continuous integration tool, that I have no control over, they do not have a maven goal mvn source:jar there.
I know that with the configurations in the pom.xml it can be achieved, and I did see it occuring once or twice, but it stopped working (well, obviously I made a change,that I do not know that broke this)
My pom.xml has the following
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<outputDirectory>${source.directory}</outputDirectory>
<finalName>${project.jar.name}</finalName>
<fileNameMapping>no-version</fileNameMapping>
<classifier>${source.classifier}</classifier>
</configuration>
</execution>
</executions>
</plugin>
So, ultimately, when I run either mvn package or mvn install or I want to have sources generated as a jar file next to the regular project.jar (or in the specified folder, but it is not essential)

Maven : exclude target/generated-sources from compilation

This question, just to be sure my interpretation is correct :
I'm using Mojohaus jaxb2-maven-plugin to generate java classes from .xsd files, and by default it puts them in target/generated-sources
Now, I want to get track of these classes in source control (target is of course excluded), and I may one day slightly customize one with an annotation or a line of code, and I may even change my class generation plugin, so what do is I copy these classes and packages in src/main/java
This upsets Maven when I try to compile because he considers "target/generated-sources" as a source directory and he finds all clases twice. For what I understand, I can exclude classes inside a source directory, but I can't remove a source directory from Maven build, am I right ?
So the only solution would be to configure my jaxb2 plugin to generate the classes elsewhere, right ?
UPDATE :
Ok, this doesn't work as I thought, if I change the outputDirectory of my jaxb plugin, it's still included as a source directory by Maven, and I have no clue why.
<configuration>
<outputDirectory>${project.build.directory}/tatata/jaxb</outputDirectory>
</configuration>
UPDATE 2 : The explanation is the plugin is adding the outputDirectory as a maven source directory during the generate-sources phase of the build, and it's not optionnal or customizable.
First things first, do not add generation code to source control. Do not modify it manually. You will get into trouble. Believe me, I've seen it too many times. A new version of the schema and you're lost.
Ok, now to your question.
With maven-jaxb2-plugin you could turn off adding generation directory as a compile source root with:
<configuration>
<addCompileSourceRoot>false</addCompileSourceRoot>
</configuration>
Disclaimer: I'm the author of maven-jaxb2-plugin.
The answer from Lexicore is an interesting lead but my question was about the plugin I'm currently using, not how to do it with an other plugin.
So here is the workaround for the Mojohaus plugin : you can just skip the generate-sources by default (no need to do this task at every build when your model changes once in a week, then once in a year), and trigger it only when needed using a dedicated maven profile : How to skip generate-sources in Maven
you can always specify the target directory(generateDirectory) in pom config file as below. Hope it helps
`
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generateDirectory>${basedir}/src/main/java</generateDirectory>
<generatePackage>com.myproj.proxy</generatePackage>
<schemas>
<schema>
<!-- <url>${project.basedir}/src/main/resources/wsdl/test.wsdl</url> -->
<fileset>
<!-- Defaults to schemaDirectory. -->
<directory>${basedir}/src/main/resources/wsdl</directory>
<!-- Defaults to schemaIncludes. -->
<includes>
<include>*.wsdl</include>
</includes>
</fileset>
</schema>
</schemas>
</configuration>
</plugin>
`

Maven + AspectJ/SpringAOP + Lombok + Surefire = test broken in a specific scenario

I have an interesting problem in a project where all of the technologies mentioned in the title are used. I've been able to track it down up to the diagnosis (the test classpath prepared by Surefire), but I don't understand whether it can be fixed and how. It's not a showstopper, indeed it's a minor issue for me, but I'd like to solve it anyway.
First a rough description.
The problem is related to executing tests in a specific module of the project, and only in a specific way.
Everything works (tests pass) when I run from the master pom level:
cd ${projHome}
mvn install
Everything works (tests pass) when I run:
cd ${projHome}/modules/CoreImplementation/
mvn test
That means that I can build and test with no problems, the same for my Jenkins, and NetBeans can run tests from the IDE when I need them.
But that module fails testing when I run from the master pom level:
cd ${projHome}
mvn test
with this error:
java.lang.NoSuchMethodError: it.tidalwave.northernwind.profiling.RequestProfilerAspect.aspectOf()Lit/tidalwave/northernwind/profiling/RequestProfilerAspect;
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewController.processRequest(DefaultSiteViewController.java:82) ~[classes/:na]
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewControllerTest.must_call_some_RequestProcessors_when_one_breaks(DefaultSiteViewControllerTest.java:161) ~[test-classes/:na]
Running mvn test as a second pass (after a mvn install -DskipTests) happens to be the way Drone.io and Travis do their job. While I could change their configuration, I'd like to stay with the standard configuration and fix the problem if possible.
The diagnosis in short and my question.
Now, the question in short (details are further below). I was able to track down the problem to different ways in which Surefire prepares the classpath to execute the tests.
When I run mvn install the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/it-tidalwave-northernwind-core-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/it-tidalwave-northernwind-core-profiling-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
When I run mvn test (from the project home) the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/unwoven-classes
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/unwoven-classes
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
The different portions are the indented ones. In the former case, SureFire uses the classes directory (forget for a moment that in my case they are named unwoven-classes) only for the module under test, and the installed jar files for every dependency. In the latter case, it seems to be using classes for all dependencies in the reactor.
The reason for which this difference in the classpaths gives me troubles is explained below in the "Gory details" section. In short, that unwoven means that they contain bytecode not augmented by AspectJ, hence the methods that can't be found at runtime.
I'm running with SureFire 2.16, but I've also tried the latest 2.19 with no changes. Being able to force SureFire to always use jar files for dependencies would fix my problems. If you have the answer, you can stop reading my post here.
Gory details (just for curiosity).
The faulty module artifactId is it-tidalwave-northernwind-core-default and it depends on aspects available in it-tidalwave-northernwind-core-profiling - that's where the offending RequestProfilerAspect is. The aspect library dependency is both in the regular dependencies of the faulty module and in the configuration of the aspectj plugin:
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<aspectLibraries combine.children="append">
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
</aspectLibraries>
</configuration>
</plugin>
</plugins>
</build>
AspectJ integration is by means of the following profile in a Super POM, which is activated in the build, whose relevant part is:
<profile>
<id>it.tidalwave-aspectj-springaop-v1</id>
...
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<configuration>
<outputDirectory>target/unwoven-classes</outputDirectory>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<configuration>
<outputDirectory>target/unwoven-test-classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
The aspectj plugin is configured in the profile to statically weave binaries in the unwoven-test-classes directories. The reason for this approach is that it's the only feasible solution AFAIK to have both Lombok and AspectJ work together.
Now, back to the two classpaths described above: the fact that SureFire is using unwoven-classes means that it's pointing to bytecode that has not been augmented with AspectJ methods, hence the error.
References
The project is a FLOSS one and can be found at
https://bitbucket.org/tidalwave/northernwind-src
or
https://github.com/tidalwave-it/northernwind-src
A changeset where the problem can be reproduced is f98e9a89ac70138c1b6bd0d4570a22d59ed71be6. JDK 1.8.0 is required to build the project (even though it doesn't use Java 8 code yet).
The SuperPOM can be found here:
https://bitbucket.org/tidalwave/thesefoolishthings-superpom-src

Setting Maven for scripting languages?

Maven is for building and managing any Java-based project. But what happens if a project is in a scripting language?
All maven can do now with TCL is copy the files around and put them in the right place in the target directory.
My problems are as follows:
Code is in TCL-> need of an interpreter not of a compiler.
It doesn't see any Java code, so it doesn't compile anything.
It doesn't see any Java tests, so it doesn't run them.
There's no java to run coverage against, so the jococo won't have anything to do.
Is there any way to set up maven for supporting a TCL project?
I've searched a lot in the internet and I found only 'jacl', but I don't really know how I can use it for setting up Maven.
Tcl isn't closely integrated with Maven (unlike Java) so you'll have to do more work. To run a Tcl script from Maven, the simplest way is to use the Exec Maven Plugin, but you have to bind the executions to explicit lifecycle phases yourself instead of relying on defaults. For example, to run a script during the test phase (i.e., to do tclsh testscript.tcl anotherArgument), you use:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>run-tcl-tests</id>
<phase>test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>tclsh</executable>
<arguments>
<argument>testscript.tcl</argument>
<argument>anotherArgument</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Maven's long-winded! Don't forget that you can probably put much of the complexity in a parent POM, and you can use properties and profiles to do interesting things.
You can also use the java goal to run Jacl or jTcl interpreters (in a sub-process). It depends on what exactly you want to do.
Unless you're using jTcl I don't see what Maven will do, apart from complicate your build process. Unless you understand Maven well and can develop some supporting plugins. As you've pointed out TCL is a scripting language, meaning your real challenge is a run-time deployment problem.
So, how would a TCL build process make deployment simpler? I would propose building RPM, Debian or MSI package for each targeted environment. These native installers can use dependency management to ensure the TCL interprertor is also installed. Another useful build option are starkits, which would bundle the TCL interpretor in a single file.
Once built, these binaries can be stored in your Maven repository (like jar files) and used as part of your deployment process. And finally don't forget you are not forced to use Maven as your build tool.
Disclaimer: Been a while since I've programmed with TCL, so hope this helps.
It is very much "not the maven way" to make dependencies on external build tools outside the maven ecosystem. Linking to tclsh will break your builds if tclsh isn't available. Not saying I haven't done worse (sometimes you just have to get it done and forget "the maven way"). Fortunately, there is an alternative - jacl.
First download the latest (probably 1.4.1) prebuilt jacl binary zip file from sourceforge.
Next, unzip and go into the lib/tcljava1.4.1 subdirectory. There are four jar files here you need to publish to your local repository (or another repo you use):
mvn install:install-file -Dfile=tjc.jar -DgroupId=jacl -DartifactId=tjc -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=tcljava.jar -DgroupId=jacl -DartifactId=tcljava -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=jacl.jar -DgroupId=jacl -DartifactId=jacl -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=itcl.jar -DgroupId=jacl -DartifactId=itcl -Dversion=1.4.1 -Dpackaging=jar
You'll also need to add these as dependencies to the project where you're calling the tcl script:
<dependency>
<groupId>jacl</groupId>
<artifactId>itcl</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>jacl</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>tcljava</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>tjc</artifactId>
<version>1.4.1</version>
</dependency>
Then just call the tcl (or really jacl) script using the exec goal of the exec-maven-plugin, passing in the script file path as the first argument (customize the execution as necessary to bind to the proper phase, etc.):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>runTcl</id>
<phase>process-resources</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Dbasedir=${basedir}</argument>
<argument>-classpath</argument>
<classpath/>
<argument>tcl.lang.Shell</argument>
<argument>${basedir}/src/main/scripts/myScript.tcl</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Update: Note that I had to use the "exec" goal above instead of the java goal. That's because jacl calls System.exit() in it's main function, so it kills the jvm. With this config, you can fail the build by using:
package require java
java::call System exit 1
From within your tcl code (or any exit value other than zero or other successCodes configured in the plugin). Hope that helps.

Maven Multiple platform dependent Packages

I have written an application in Java that can be used on both Linux and Windows. Currently by running mvn package, my maven build system will generate a .msi using WiX.
Is there a way of creating two package 'tasks' so I can say either mvn package-windows ormvn package-linux`
If you want to package both versions (Linux and Windows), you can bind your mvn package phase to an extra phase that would build another artifact.
...
<plugin>
<groupId>org.group.extra</groupId>
<artifactId>extra-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
[...]
</configuration>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
...
It was probably what you have already done with maven-wix-plugin.
You can use either use profile to do that or a better thing would be to have three project.
One for the core and then one for Linux and one for Windows that uses the core project.

Resources