I have a modular layout of my project sources which are built using ant. After having built the project with javac, I am running (for a particular module) the iajc task to advise binary classes scattered over the inpath that composes binary output directories from my dependency modules:
<iajc destDir="${dest.dir}" >
<inpath refid="modules.binaries.path" />
<classpath>
<path refid="module.classpath" />
</classpath>
<aspectpath refid="aspects.path" />
</iajc>
The problem is that like this the woven output from all the binaries is merged into ${dest.dir} which means that I am losing my modular structure of binaries as a result. But I need it kept in runtime. Not specifying destDir at all has no effect. Is there any way to have the woven classes stay where they are thus overwriting their originals (unwoven) within the inpath?
Thanks for any help or hint on this.
I've ended up with iterating over elements of the path that composes binary directories of the dependency modules. inpath and destDir are being set equal to the current path element at each iteration:
<for param="path.item" >
<path refid="modules.binaries.path" />
<sequential>
<iajc destDir="#{path.item}" >
<inpath>
<pathelement location="#{path.item}" />
</inpath>
<classpath>
<path refid="module.classpath" />
</classpath>
<aspectpath refid="aspects.path" />
</iajc>
</sequential>
</for>
This way classes are being advised in their places by overwriting the original version.
I'd like to pass extraClasses parameter when I generate java2wsdl. Here is my Ant task:
<target name="rews.all" depends="xews.aar">
<echo message="${axis2.classpath}" />
<delete file="${build.dir}/wsdl/XEWS.wsdl" />
<taskdef name="java2wsdl"
classname="org.apache.ws.java2wsdl.Java2WSDLTask"
classpathref="axis2.classpath">
</taskdef>
<java2wsdl className="com.dd.xews.XEWS"
outputLocation="${build.dir}/wsdl/"
targetNamespace="http://xews.dd.com/"
schemaTargetNamespace="http://xews.dd.com">
<classpath>
<pathelement path="${axis2.classpath}"/>
<pathelement location="${build.dir}/classes"/>
<pathelement location="${vendor.dir}/AWS/lib/aws-java-sdk-1.2.1.jar"/>
</classpath>
</java2wsdl>
<copy todir="${build.dir}/" file="${build.dir}/wsdl/XEWS.wsdl"/>
</target>
Tried everything but no luck.
Does anyone know the syntax? How do I add extraClasses here?
Test1 (failed)
This failed with error java2wsdl doesn't support the "extraClasses" attribute:
<java2wsdl className ="com.dd.xews.XEWS"
outputLocation ="${build.dir}/wsdl/"
targetNamespace ="http://xews.dd.com/"
schemaTargetNamespace ="http://xews.dd.com"
extraClasses ="com.dd.xews.XEWS.Emailer.java">
</java2wsdl>
How to find out which attributes java2wsdl Ant task does support?
My Axis2 version is 1.5.4.
Here's a link to the source code of Ant task: Java2WSDLTask.
#setExtraClasses accepts String parameter, and then tries to split it using comma delimiter. So try passing something like
<extraClasses>com.test.Class1,com.test.Class2</extraClasses>
EDIT
This will not work in older versions of Axis2 (to be more precise -- versions prior 1.6.0). It's because of 'extraClasses' attribute was specified as an array-type, which is obviously not supported as Ant task attribute. You can find all the details in this JIRA issue: AXIS2-4634: Ant task Java2WSDLTask does not allow the use of extraClasses
The easiest way to make it work is to upgrade Axis2 JARs to a newer 1.6.x version. If you are stuck with Axis2 version for some project-specific reasons (I don't see there should be any), you could take the source code of Java2WSDLTask from the newer version (see link to GrepCode above), and make a copy of this task in your project (you'll have to use different class name, or package), then use it as an Ant task just like you are using it currently. Except for it will be possible to use 'extraClasses' attribute.
Axis2 1.4 and up support the "-xc" attribute. Here's how I did it:
<java classname="org.apache.ws.java2wsdl.Java2WSDL" fork="true">
....
<arg value="-xc"/>
<arg value="com.example.mypackage.MyClass"/>
<arg value="-xc"/>
<arg value="com.example.anotherpackage.MyOtherClass"/>
....
</java>
I'm interested in hearing how you prefer to automate Javascript minification for your Java web apps. Here are a few aspects I'm particularly interested in:
How does it integrate? Is it part of your build tool, a servlet filter, a standalone program post-processing the WAR file, or something else?
Is it easy to enable and disable? It's very unfunny to try and debug a minified script, but it's also useful for a developer to be able to test that the minification doesn't break anything.
Does it work transparently, or does it have any side effects (apart from the ones inherent in minification) that I have to consider in my day-to-day work?
Which minifier does it use?
Does it lack any features that you can think of?
What do you like about it?
What don't you like about it?
This will mostly serve as a reference for my future projects (and hopefully other SOer's will find it informative, too), so all kinds of tools are interesting.
(Note that this is not a question about which minifier is best. We have plenty of those around already.)
Round-up post
If you post something new in this thread, edit this post to link to yours.
Ant apply task (using YUI Compressor)
Custom YUI Compressor Ant task
Maven YUI Compressor plugin
Granule (for JSP, JSF, Grails, Ant)
Ant macros for Google Closure compiler
wro4j (Maven, servlet filters, plain Java, etc)
ant-yui-compressor (ant task for compressing JS+CSS)
JAWR
Minify Maven Plugin
humpty
Ant exec task using Terser
We are using Ant task to minify js files with YUICompressor during production build and put result into a separated folder. Then we upload those files to a web server.
Here is an example:
<target name="js.minify" depends="js.preprocess">
<apply executable="java" parallel="false">
<fileset dir="." includes="foo.js, bar.js"/>
<arg line="-jar"/>
<arg path="yuicompressor.jar"/>
<srcfile/>
<arg line="-o"/>
<mapper type="glob" from="*.js" to="*-min.js"/>
<targetfile/>
</apply>
</target>
I think one of the best and right tool for the job is wro4j Check out https://github.com/wro4j/wro4j
It does everything you need:
Keep project web resources (js & css) well organized
Merge & minify them at run-time (using a simple filter) or build-time (using maven plugin)
Free and open source: Released under an Apache 2.0 license
several minification tools supported by wro4j: JsMin, Google Closure compressor, YUI etc
Very easy to use. Supports Servlet Filter, Plain Java or Spring Configuration
Javascript and CSS Meta Frameworks Support: CoffeeScript, Less, Sass etc
Validation: JSLint, CSSLint etc
Can run in debug as well as production modes. Just specify all the files it should handle/pre-process and it does the rest.
You can simply include merged, minified and compressed resource like this:
<script type="text/javascript" src="wro/all.js"></script>
I have written ant macros for Google Closure compiler and Yahoo compressor and include this file in different web projects.
<?xml version="1.0" encoding="UTF-8"?>
<!-- CSS and JS minifier. -->
<!DOCTYPE project>
<project name="minifier" basedir=".">
<property name="gc" value="compiler-r1592.jar" />
<property name="yc" value="yuicompressor-2.4.6.jar" />
<!-- Compress single js with Google Closure compiler -->
<macrodef name="gc-js">
<attribute name="dir" />
<attribute name="src" />
<sequential>
<java jar="${gc}" fork="true">
<!--
- - compilation_level WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS
Specifies the compilation level to use. Default: SIMPLE_OPTIMIZATIONS
- - warning_level QUIET | DEFAULT | VERBOSE
Specifies the warning level to use.
-->
<arg line="--js=#{dir}/#{src}.js" />
<arg line="--js_output_file=#{dir}/#{src}-min-gc.js" />
</java>
</sequential>
</macrodef>
<!-- Compress single js with Yahoo compressor -->
<macrodef name="yc-js">
<attribute name="dir" />
<attribute name="src" />
<sequential>
<java jar="${yc}" fork="true">
<arg value="#{dir}/#{src}.js" />
<arg line="-o" />
<arg value="#{dir}/#{src}-min-yc.js" />
</java>
</sequential>
</macrodef>
<!-- Compress all js in directory with Yahoo compressor -->
<macrodef name="yc-js-all">
<attribute name="dir" />
<sequential>
<apply executable="java" parallel="false">
<fileset dir="#{dir}" includes="*.js" excludes="*-min*.js" />
<arg line="-jar" />
<arg path="${yc}" />
<srcfile />
<arg line="-o" />
<mapper type="glob" from="*.js" to="#{dir}/*-min-yc.js" />
<targetfile />
</apply>
</sequential>
</macrodef>
<!-- Compress all css in directory with Yahoo compressor -->
<macrodef name="yc-css-all">
<attribute name="dir" default="${build.css.dir}" />
<sequential>
<apply executable="java" parallel="false">
<fileset dir="#{dir}" includes="*.css" excludes="*-min*.css" />
<arg line="-jar" />
<arg path="${yc}" />
<arg line="-v --line-break 0" />
<srcfile />
<arg line="-o" />
<mapper type="glob" from="*.css" to="#{dir}/*-min.css" />
<targetfile />
</apply>
</sequential>
</macrodef>
</project>
Integration: <import file="build-minifier.xml" /> in your build.xml, then invoke as usual ant tasks: <gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />
Choice of two minifiers: Google Closure compiler and Yahoo compressor, you should download them manually and place near the xml file
Minifiers skip already compressed files (ending with -min*)
Usually I make three versions of script: uncompressed (e.g. prototype.js) for debugging, compressed with closure compiler (prototype-min-gc.js) for production server, compressed with Yahoo (prototype-min-yc.js) for troubleshooting because closure compiler uses risky optimizations and sometimes produces invalid compressed file and Yahoo compressor is more safe
Yahoo compressor can minify all files in a dir with single macro, Closure compiler cannot
I tried two ways:
using a servlet filter. When in production mode, the filter is activated and it compress any data bounded to URL like *.css or *.js
using maven and yuicompressor-maven-plugin; the compression is perfomed una-tantum, (when assembling the production war)
Of course the latter solution is better since it does not consume resources at runtime (my webapp is using google app engine) and it doesn't complicate your application code. So assume this latter case in the following answers:
How does it integrate? Is it part of your build tool, a servlet filter, a standalone program post-processing the WAR file, or something else?
using maven
Is it easy to enable and disable? It's very unfunny to try and debug a minified script, but it's also useful for a developer to be able to test that the minification doesn't break anything.
you activate it only when assemblying the final war; in development mode you see the uncompressed version of your resources
Does it work transparently, or does it have any side effects (apart from the ones inherent in minification) that I have to consider in my day-to-day work?
absolutely
Which minifier does it use?
YUI compressor
Does it lack any features that you can think of?
no, it is very complete and easy to use
What do you like about it?
it is integrated with my favourite tool (maven) and the plugin is in the central repository (a good maven citizen)
I think you need a compression library, for example Granule tag.
http://code.google.com/p/granule/
It gzip and combine javascripts wrapped by g:compress tag using different methods, also has Ant task as well
code sample is:
<g:compress>
<script type="text/javascript" src="common.js"/>
<script type="text/javascript" src="closure/goog/base.js"/>
<script>
goog.require('goog.dom');
goog.require('goog.date');
goog.require('goog.ui.DatePicker');
</script>
<script type="text/javascript">
var dp = new goog.ui.DatePicker();
dp.render(document.getElementById('datepicker'));
</script>
</g:compress>
...
I'm really surprised no one mentioned JAWR - https://j-a-w-r.github.io
It's pretty mature and supports all standard features that are to be expected, and a bit more. Here is how it holds against the OP's excellent criteria.
How does it integrate? Is it part of your build tool, a servlet
filter, a standalone program post-processing the WAR file, or
something else?
It originally did the processing/heavy-lifting at application startup and serving was based on a servlet. Starting with 3.x they added support for integrating at build time.
Support for JSP and Facelets is provided through a custom JSP tag library to import processed resources. In addition to that, a JS resources loader is implemented which supports loading the resources from static HTML pages.
Is it easy to enable and disable? It's very unfunny to try and debug a
minified script, but it's also useful for a developer to be able to
test that the minification doesn't break anything.
A debug=on option is available to use before application startup, and a custom GET parameter can be specified at individual requests in production to toggle debug mode selectively at runtime for said request.
Which minifier does it use?
For JS it supports YUI Compressor and JSMin, for CSS I'm not sure.
Does it lack any features that you can think of?
SASS support comes to mind. That said, it does support LESS.
Really late to the party here, but figured this might help someone still looking for a different answer:
After trying to use YUI Compressor, I was disappointed that it was incompatible with more recent versions of jQuery and Prism (the two main 3rd party JS libraries I needed for my project which I wanted compressed into a single file). So I decided to use Terser, which is a fork of Uglify-JS that supports ES6+. I wasn't able to get it to run directly using the <exec> task, but using the Windows command line method works for Win 10, at least (not saying it can't work otherwise, but this was a very easy work-around). No need to add anything else to the Path system variable (as Node.JS is typically added during installation). I first use the ANT <concat> task to make a big, uncompressed file. Use <fileset> as it will preserve the order (if that's important, anyway).
<concat destfile="${js-big-file}" encoding="UTF-8" outputencoding="UTF-8" fixlastline="true">
<filelist refid="js-input-filelist"/>
</concat>
Then use the <exec> task to run any NPM program, such as Terser. The Apache manual page on this task indicated this is the Windows workaround for running .bat files, but it really allows you run just about any command line application (even those that <exec> mysteriously cannot find otherwise).
<exec executable="cmd">
<arg value="/c"/>
<arg value="terser"/>
<arg value="${js-big-file}" />
<arg value="-o" />
<arg value="${smaller-js-file}"/>
</exec>
Integrate? It is part of an ANT build script (a DITA Open Toolkit plugin to support custom JavaScript, among other things - not a Java Web application, per se, but using Java to build HTML5 output), so integration was not much more than adding those tasks to a new target (there's more code regarding setting defaults and checking input parameters!).
Easy to Enable/Disable? In my case, I have a parameter I pass to the ANT Build in order to include building and minifying the JS file. So yes, it only performs this target if I set the param to 'Yes'. That's a pretty easy thing to set up in an ANT build.
Transparent So far, it appears to have no effect on any of the several JS files I'm including. Some of those are my own (and I'm no JS expert, by any means) and some are, as I mentioned, common JS libraries.
Minifier Terser, but you could use just about any minified with command line input with this method.
Lack features? Terser only works with JavaScript. If I want to do the same for my CSS files (which I do), I use YUI Compressor.
Like That it is a currently active project and has good support. Plus, the current implementation (only calling it via the ANT <exec> target) allows me to swap out minifiers should I need to use something else down the road.
Don't like That it requires Node.JS. Nothing against Node.JS, mind you, just that this particular project doesn't need it otherwise. I'd much prefer to use a Java .jar file like YUI Compressor for this (I can easily distribute that with a plugin should I need to).
Our project has handled it a number of ways but we have continued to use the YUI Compressor through our different iterations.
We initially had a servlet handle the compression for JavaScript the first time that particular file was accessed; it was then cached. We already had a system in place to handle custom property files so we simply updated our configuration files to support enabling or disabling the compressor depending on the environment we were working in.
Now the development environments never use compressed JavaScript for debugging purposes. Instead we handle the compression in our build process when exporting our application to a WAR file.
Our client has never raised concerns about the compression and the developers don't notice it until they decide to debug JavaScript. So I'd say it's rather transparent with minimal, if any, side affects.
This worked for me: https://bitbucket.org/m6_russell_francis/yui-compressor-ant-task/wiki/Home
<!-- minimize all static *.css & *.js content -->
<target name="static-content-minify">
<taskdef name="yuicompressor"
classname="com.metrosix.yuicompressor.anttask.YuiCompressorTask">
<classpath>
<pathelement location="${jar.yui.compressor}"/>
<pathelement location="${jar.yui.anttask.compressor}" />
</classpath>
</taskdef>
<yuicompressor todir="${build.static.content.min}" charset="utf-8"
preserveallsemicolons="true" munge="true" >
<fileset dir="${src.static.content}">
<include name="**/*.css"/>
<include name="**/*.js"/>
</fileset>
</yuicompressor>
</target>
I'm writing a framework for managing web assets, called humpty. It aims to be simpler and more modern than jawr or wro4j by using WebJars and ServiceLoaders.
How does it integrate? Is it part of your build tool, a servlet filter, a standalone program post-processing the WAR file, or something else?
In development, a servlet processes the assets as necessary. The assets would then be pre-compiled before production and placed in a public folder, so that the only part that is used is generating the correct includes in the HTML.
Is it easy to enable and disable? It's very unfunny to try and debug a minified script, but it's also useful for a developer to be able to test that the minification doesn't break anything.
That would be done by switching between development and production modes.
Does it work transparently, or does it have any side effects (apart from the ones inherent in minification) that I have to consider in my day-to-day work?
I believe it is transparent, but does strongly favour the use of WebJars.
Which minifier does it use?
Whichever one the plugin you put on your classpath uses. Currently looking at writing a plugin for the Google Closure Compiler.
Does it lack any features that you can think of?
Still pre-release, though I'm using it in production. The maven plugin still needs a lot of work.
What do you like about it?
The simplicity of just adding a dependency to configure the framework
What don't you like about it?
It's my baby, I love it all ;)
I have a legacy product, spread across dozens of repositories. I'm currently trying to refactor (and understand...) the given build process. First step was moving from the old version control system to mercurial, which was encouraging and easy.
The build process mainly uses ant build scripts (good news) but has to run 'on' the repository file structure (bad news...) because the ant scripts take files from all repositories and leave artifacts on .. lets say, several places... But that's not a blocker.
Before I trigger the build (now with hudson CI), I have to make sure, that all repositories are updated to the tip or a selected tag. I could write a script/batch or write a custom ant task (again) but, I don't want to ignore existing features (again):
is it possible to update a set of mercurial repositories by using existing ant tasks or mercurial features? All repositories are located in one folder (like /repo) and have a common prefix (like SYSTEMNAME_module) so it's easy to locate them/create a fileset.
The most simple solution today is to start the hg executable from Ant (using the exec task. Note: MacroDef is your friend). Just create a "main" build file in one of the projects, change to the parent directory (where you can access all the local copies) and then update each one.
I found a different ant based solution, based on the 'apply' task:
<apply executable="hg">
<arg value="update" />
<arg value="--verbose" />
<arg value="--revision" />
<dirset dir="/repos" include="REPO_SUFFIX*" />
</apply>
Thanks to Aaron, his very helpful answer showed me the right direction.
I think this would be a more flexible way to update a mercurial depo. From a set of directories it chooses which ones are depots and updates those. Note that you can also do this with the foreach tag of ant contrib but the 'for' seems to consume a lot less memory.
<!-- See if the directory looks like a mercurial depo, if so update it -->
<target name="-mercurial-update">
<dirset dir="${dir.deps}" id="lib.dirs">
<exclude name="build"/>
<present targetdir="${dir.deps}">
<mapper type="glob" from="*" to="*/.hg" />
</present>
</dirset>
<for param="file">
<path>
<dirset refid="lib.dirs"/>
</path>
<sequential>
<echo>Trying to update mercuriali depo #{file}</echo>
<exec executable="hg" dir="#{file}">
<arg line="pull" />
</exec>
<exec executable="hg" dir="#{file}">
<arg line="up" />
</exec>
</sequential>
</for>
</target>
We have an Apache ANT script to build our application, then check in the resulting JAR file into version control (VSS in this case). However, now we have a change that requires us to build 2 JAR files for this project, then check both into VSS.
The current target that checks the original JAR file into VSS discovers the name of the JAR file through some property. Is there an easy way to "generalize" this target so that I can reuse it to check in a JAR file with any name? In a normal language this would obviously call for a function parameter but, to my knowledge, there really isn't an equivalent concept in ANT.
I would suggest to work with macros over subant/antcall because the main advantage I found with macros is that you're in complete control over the properties that are passed to the macro (especially if you want to add new properties).
You simply refactor your Ant script starting with your target:
<target name="vss.check">
<vssadd localpath="D:\build\build.00012.zip"
comment="Added by automatic build"/>
</target>
creating a macro (notice the copy/paste and replacement with the #{file}):
<macrodef name="private-vssadd">
<attribute name="file"/>
<sequential>
<vssadd localpath="#{file}"
comment="Added by automatic build"/>
</sequential>
</macrodef>
and invoke the macros with your files:
<target name="vss.check">
<private-vssadd file="D:\build\File1.zip"/>
<private-vssadd file="D:\build\File2.zip"/>
</target>
Refactoring, "the Ant way"
It is generally considered a bad idea to version control your binaries and I do not recommend doing so. But if you absolutely have to, you can use antcall combined with param to pass parameters and call a target.
<antcall target="reusable">
<param name="some.variable" value="var1"/>
</antcall>
<target name="reusable">
<!-- Do something with ${some.variable} -->
</target>
You can find more information about the antcall task here.
Take a look at Ant macros. They allow you to define reusable "routines" for Ant builds. You can find an example here (item 15).
Also check out the subant task, which lets you call the same target on multiple build files:
<project name="subant" default="subant1">
<property name="build.dir" value="subant.build"/>
<target name="subant1">
<subant target="">
<property name="build.dir" value="subant1.build"/>
<property name="not.overloaded" value="not.overloaded"/>
<fileset dir="." includes="*/build.xml"/>
</subant>
</target>
</project>
You can use Gant to script your build with groovy to do what you want or have a look at the groovy ant task.