I have a web application with spring and maven. The application is divided into maven modules. I have an "application-web" module that generates war. Another "application-ear" module that generates an ear. And another "application-static" with css, js and images that generates a zip file.
This would be the outline of my application:
application
application-web (java code)
application-ear
application-static (css, js and images)
application-resources (language properties)
I want to deploy the eclipse use files of "static" module, instead of using the files in the "application/src/main/webapp" directory. How can I do this? It is possible?
Don't waste your time with unpacking resources, everything works out of the box:
Resource bundles: the are always loaded from the classpath, regardlessly it is exploded (WEB-INF/classes) or compressed (WEB-INF/lib)
Serving static resources: bundle them up in a JAR and use either Tomcat (Servlet 3.0) feature to serve from META-INF/resources, see here or use Spring's built in mvc:resources element.
Simply add the dependency snippets in your WAR POM and your are done.
You can use the maven dependency plugin to unpack your static resources included in the zip file using the following:
In your application-web.pom
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-resources</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputDirectory>resources</outputDirectory>
<includeArtifactIds>application-static</includeArtifactIds>
<includeGroupIds>your group id</includeGroupIds>
<includes>**/*.js,**/*.css</includes>
</configuration>
</execution>
</executions>
</plugin
This work:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeTypes>pom</excludeTypes>
<includeArtifactIds>application-static</includeArtifactIds>
<includeGroupIds>com.foo.foo.application</includeGroupIds>
<outputDirectory>src/main/webapp</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
But I have another problem, with this solution only copy the static files when I execute clean package. If I run the application-web with eclipse and I do changes in a js file in application-static, the changes have no effect until I execute clean package. Any solution for this?
Related
I have created a application. In this application I have doubt that when getting output I need to include lib (library folder which includes all supporting jar files) but I need in a single jar files which must be include all supporting jars. Is it possible? I am using Netbeans.
You don't tell us what you are using to build your code. I'm going to guess at maven (because I know the answer is in Maven!). What you need is:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Add your other plug-ins here -->
</plugins>
</build>
I am currently building my spring boot application as a fat jar. But because I am also building a docker image from these, I have to pull the jar with all its dependencies every time I change some of my code. So my question is: How would I have to change my gradle files to get a task called 'buildWithExternalLibs' that has all dependencies in a lib folder, but can still be started using java -jar ... as long as the lib folder is right next to the jar?
I have done it in maven project. You can use same logic in gradle too.
When you will clean install, it will copy your jar file too.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<id>install-jar-lib</id>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>com.***.*</groupId>
<artifactId>abc-library</artifactId>
<version>*.*.*</version>
<packaging>jar</packaging>
<file>${project.basedir}/src/lib/***.jar</file>
</configuration>
</execution>
</executions>
<inherited>false</inherited>
</plugin>
I am developing some little maven plugin and I need to edit some css and js files from target (not from src!). And I can't understand on what phase I can do it.
To get access to src I use the phases:generate-resources and the following code:
MavenProject project = (MavenProject) getPluginContext().get("project");
String projectDir=project.getBasedir().toString();
How can I get target when all js,css files are copied there but war file is not generated in order to edit some files from target and get final war with some modifications of js and css files?
EDIT
What for I need it. I have js files in my project: a.js, b.js. I want to obfuscate them via maven. I mean, obfuscate when I build project. And of course all files in final war must be obfuscated but the same files in src must be left unobfuscated.
Besides, I need to combine some obfuscated files into one file.
I found the answer. The problem is that we must add some logic between "prepare-package" and "package" phases. As we user maven-war-plugin we can do it using exploded goal. From official docs:
Create an exploded webapp in a specified directory.
And here it's necessary to remember one important thing that maven after version 2.0.1 copies resources twice so if we want to use maven 2.5 we must use <useCache>true</useCache>. So final solution:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>prepare-war</id>
<phase>prepare-package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<useCache>true</useCache>
</configuration>
</plugin>
<plugin>
<groupId>my plugin</groupId>
<artifactId>...</artifactId>
<version>....</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>...</goal>
</goals>
</execution>
</executions>
</plugin>
So I'm trying something I thought would be rather simple, I basically want maven to minify all my js and css files for me before building a war. My plugins look like this:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>1.0.0</version>
<configuration>
<manifestLocation>META-INF</manifestLocation>
<instructions>
<Export-Package>!test.impl,test*</Export-Package>
<Import-Package>*</Import-Package>
<!--
add ,plugin.xml if it's present i.e.
src/main/resources,plugin.xml
-->
<Include-Resource>src/main/resources</Include-Resource>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<nosuffix>true</nosuffix>
</configuration>
</plugin>
The problem is that the YUI plugin does correctly minify the files, but just before the war is built it looks like it copies over all the files from my main source directory and thus wipes out the changes the YUI plugin had done.
I'm calling maven by the following: mvn compile war:war. I've been playing around for awhile with different settings, but so far I haven't found a way around this.
What I would like is for just after the war has copied over the files it needed from the src directory it would run the YUI plugin, but I tried all the permutations of phases on the YUI plugin, but that didn't seem to make any difference.
I've googled around, but pretty much everything I've read so far seems to indiciate that I should just need to drop the YUI plugin in there like I have and everything should magically work. So far I haven't seem to have found the magic.
The accepted answer doesn't work.
Much better is this answer (as pointed out by koga in his comment):
https://stackoverflow.com/a/11495021/11451
Here is what I ended up doing:
Step 1: minify the css and js
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
<configuration>
<charset>UTF-8</charset>
<skipMerge>true</skipMerge>
<cssSourceDir>resources</cssSourceDir>
<jsSourceDir>resources</jsSourceDir>
<jsEngine>CLOSURE</jsEngine>
<nosuffix>true</nosuffix>
<webappTargetDir>${project.build.directory}/minify</webappTargetDir>
<cssSourceIncludes>
<cssSourceInclude>**/*.css</cssSourceInclude>
</cssSourceIncludes>
<cssSourceExcludes>
<cssSourceExclude>**/*.min.css</cssSourceExclude>
</cssSourceExcludes>
<jsSourceIncludes>
<jsSourceInclude>**/*.js</jsSourceInclude>
</jsSourceIncludes>
<jsSourceExcludes>
<jsSourceExclude>**/*.min.js</jsSourceExclude>
</jsSourceExcludes>
</configuration>
</plugin>
Step 2: overwrite css and js in the war with minified files
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<webResources>
<resource>
<directory>${project.build.directory}/minify</directory>
</resource>
</webResources>
</configuration>
</plugin>
Use the war generator and add the configuration to exclude the sources file.
Example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${war-plugin.version}</version>
<configuration>
<warSourceExcludes>js/**/*.js</warSourceExcludes>
</configuration>
</plugin>
After that you need to include your target files to your war. You do this by setting the "prepare-package" phase of maven lifecycle (I'm using Minify plugin) and adding the files on Minify configuration (jsSourceIncludes,cssSourceIncludes,...)
For example:
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>default-minify</id>
<goals>
<goal>minify</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<jsSourceDir>/js</jsSourceDir>
<jsSourceIncludes>
<jsSourceInclude>/**/*.js</jsSourceInclude>
</jsSourceIncludes>
</configuration>
</execution>
</executions>
</plugin>
What happens is that the config above is running the compressor on the process-resources phase, but then the package phase overwrites these files with the original ones.
By changing the phase to package, it should work:
<execution>
<phase>package</phase>
<goals>
<goal>compress</goal>
</goals>
Now the compression is done after the files where copied to target in order to build the WAR content.
The reason why this is happening is that only compressing files without concatenating them or renaming them with a suffix is not the most common use case for the plugin.
Normally we want to compress and concatenate files into only one file, and give it a new name.
The new name is usually something like originalname-min.css / original.name-min.js where .min is the suffix, so removing the nosuffix option on the config above would also work.
Edit: Log example
[INFO] --- yuicompressor-maven-plugin:1.1:compress (default) # yui-compressor-test -
[INFO] prettify.css (817b) -> prettify.css (617b)[75%]
[INFO] total input (1510b) -> output (1134b)[75%]
as stated above maven-war-plugin overwrites files created by minify plugin.
it seems that this cannot be changed. however wanted behavior may be achieved by simply changing project structure.
here example what I did with my project. I'm using minify-maven-plugin and spring framework, static files are stored in static directory.
1) move static directory from src/main/webapp to src/main/resources
2) change minify plugin config in pom.xml. so source points to resources and target points to classes:
<webappSourceDir>src/main/resources</webappSourceDir>
<webappTargetDir>target/classes</webappTargetDir>
<jsSourceDir>static</jsSourceDir>
<cssSourceDir>static</cssSourceDir>
3) change spring config. so spring is serving static files from class path:
<mvc:resources location="classpath:/static/" mapping="/static/**"/>
and now
mvn clean && mvn package
produces correct war with minified files inside /WEB-INF/classes/static
You should take a look to Minify Maven Plugin which sounds like the thing you need.
Let me know if you need any help configuring it.
How do I do something after Maven copies the webapp resources to the war directory inside of the package goal? I want to do something just after it copies the webapp resources to the target's war directory, but just before it finally archives everything into a WAR file.
The reason you're having problems is because the copying of webapp resources is done by the war plugin in the same breath that it builds the war. It's not a different lifecycle phase or even two different actions in the same phase. It's all part of the war:war goal.
There's a workaround, though. If you bind war:exploded to an earlier phase, like prepare-package, then it will build your exploded webapp, and then you can put something after that to modify the files that were built to the exploded directory. Then war:war will package up the modified exploded directory. (With newer versions of the war plugin, I believe you'll need to set the useCache property to get the desired behavior, though that doesn't seem to really be what it's for, be wary.)
I've just had to do the same thing so here's an example for egervari to show what Ryan Stewart is saying.
(This uses the YUI Compressor Maven Mojo to automatically minify js files.)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>${warName}</warName>
<useCache>true</useCache>
</configuration>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*.min.js</exclude>
<exclude>**/*.properties</exclude>
</excludes>
<nosuffix>true</nosuffix>
</configuration>
</plugin>
</plugins>
</build>
As documented in the build lifecycle
prepare-package perform any operations necessary to prepare a package
before the actual packaging. This often results in an unpacked,
processed version of the package. (Maven 2.1 and above)
package take the compiled code and package it in its distributable format, such as
a JAR.
You would want to bind your goal which does something to one of these goals, depending on how your pom executes.
I haven't tried this and hence can't say which one with authority.