maven-assembly-plugin holds lock on file - java

I'm using the maven-assembly-plugin to produce a zip file for some database scripts. I am having an intermittent problem in that if my build fails for whatever reason, when I come to rebuild it often (but not always) fails immediately when trying to delete the target directory. The reason for this is that the zip assembly file (used by maven-assembly-plugin) that it has copied there is locked.
If I repeatedly try to build, or leave a long enough period between the failed build and a rebuild, the lock is eventually dropped and the build proceeds as normal.
This is proving very frustrating - any ideas what the problem might be? I am using Windows XP Pro.
My pom.xml snippet is :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/sql/zip-assembly.xml</descriptor>
</descriptors>
<finalName>db-deployment</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-database-scripts</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
Thanks!

Using 'process explorer' I can see that there is a java process that still holds onto this file handle even though the maven build has failed. This java process is actually owned by eclipse which is interesting as my build is running from the command line. I suspect that eclipse has seen a file change in the workspace and decided to update its project. After eclipse has finished doing the update, the handle is dropped and my build is able to continue without problem.
Looking further I can see that the assembly file is being built under the main/ directory, which would confirm why eclipse would get involved. I'll move it!

Related

How to debug a Maven application in Eclipse

Let me start by clarifying I have check every possible resource, tutorial, video, other stackoverflow questions that I could get my hands on that are related in order to try and find an answer to this. I'm using java 8 and Eclipse Luna Service Release 2 (4.4.2) with m2e plugin, It's quite hard to believe but it seems there isn't a single example that clearly explains how you actually debug a Maven Java application USING ECLIPSE. There are no less than 40 different sources here are some
Debugging with exec-maven-plugin
https://blog.jooq.org/how-to-debug-your-maven-build-with-eclipse/
Eclipse not stopping at java breakpoints during remote debug
https://github.com/howlger/Eclipse-IDE-improvements-videos/tree/2022-03/sample_code
IntelliJ IDEA Maven project StackOverflowError when running debug configuration
Debugging in Maven?
What I'm trying to do is click the debug button in eclipse and run a debug configuration that allows me to hit my breakpoints.
I have the following configuration in Eclipse
this runs the exec:exec goal from my pom.xml which looks like this
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath />
<argument>core.app.server</argument>
<argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=*:49875 </argument>
</arguments>
<workingDirectory>${project.build.outputDirectory}</workingDirectory>
</configuration>
</plugin>
Ok, so far so good. At this point if I run the debug configuration the app launches and then hangs which I'm assuming it is waiting for the debugger to remotely connect based on the arguments in my pom.xml. So the app starts hangs and in Eclipse at this point I'm looking at this
At this point I've tried everything I can imagine. I notice the exec plugin launcher starts on a random port which in the picture is 51661, when in my exec arguments in the pom.xml I have it set to 49875 so this seems off. Another thing I noticed if I removed the <argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=*:49875 </argument> line from my pom.xml the app launches completely , runs fine but this gets me no where. I have tried to connect using a "Remote Java Application" configuration after the app launches this also does not work. I normally use IntelliJ which makes it an absolute breeze since everything is handled OOTB, unfortunately I have to get this working in Eclipse as well in a similar fashion.
How do I configure the Debug Configuration in a way that will allow me to launch the app and hit my breakpoints?
EDIT 1
When setting suspend=n the app still hangs when launching with the argument agentlib:jdwp
EDIT 2
In an effort to get this figured out without wasting another day on something that should be effortless, I tested running a clean install from and debug configuration and then tested using the run as commands provided by m2e shown below and the m2e commands work perfectly where as the same exact commands ran with a debug configuration fail for missing references.
EDIT 3
Reading the documentation on the exec maven plugin here https://www.mojohaus.org/exec-maven-plugin/index.html it says the difference between exec:exec and exec:java is that the ladder execute programs and Java programs in a separate process and the former execute Java programs in the same VM. I think this might be somewhat related to the issue I'm having. This should be really easy to test for someone familiar with MAven/Eclipse I would think, is anyone able to create a super basic hello world app maven project and see if they can set and hit a break point in the main method, should take but 5-10 min?
I got it working like so:
Download, extract (latest!?) Luna SR2 JavaEE Edition
set (correct) JAVA_HOME/vm in eclipse.ini (oracle-8 latest)
Welcome Screen, create new Maven project, simple, skip achetype...
(So with fresh defaults, simple project):
With the following pom section :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>C:\Program Files\Java\jdk1.8.0_333\bin\java.exe</executable>
<arguments>
<argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=49875</argument>
<argument>-classpath</argument>
<classpath />
<argument>com.example.Demo</argument>
</arguments>
<workingDirectory>${project.build.outputDirectory</workingDirectory>
</configuration>
</plugin>
</plugins>
</build>
(very similar to yours, only significant difference: address, server is crucial in this approach, suspend either)
With the same (Maven) Run configuration, as you show:
We now additionally need:
"Debug Configurations..."
Remote Java Application(! ..because we chose "server"..)
we select the (sources) project as "Project"
Connection Type: attach
Host: localhost
Port: the one configured in jdwp
Looks like:
Set "my" breakpoint in:
package com.example;
public class Demo {
public static void main(String[] args) {
int x = 0;
x++; // just to set breakpoint somewhere
System.out.println(x);
}
}
"Run" "Exec_Java" (suspend, and server flags (and all) have effect!)
Console(Exec_Java) should report:
...
[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) # luna-res ---
Listening for transport dt_socket at address: 49875 //!!
"Debug" "New_Configuration".
..and the breakpoint halts(, and we get the "switch perspective dialog";)

How to compile Maven based Java project to run it from command line

I have a Maven project that I need somehow to compile so I'd be able to transfer the compiled file to a different machine and then execute there (with potentially different Java version).
I looked at this SO question
and was able to execute:
mvn clean install
mvn dependency:copy-dependencies
Yet when I tried:
cd target/
java -cp myApp-0.0.1.jar:dependency myApp
I got
Error: Could not find or load main class myApp
My pom.xml does not have mvn-assembly-plugin or maven-jar-plugin (and I successfully get the .jar in target/ after mvn clean install).
I am not sure whether those steps are related to my goal because what I need is to create something that will run without any java -jar or mvn and could be ported and run on a different machine.
There is Maven build plugin that would bundle all your dependencies in a JAR. You could execute it simply with
java -jar mybundled.jar
without caring about class path dependencies.
And here comes the Maven plugin. Replace the MainClass with your entry point.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.yourdomain.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
As it is bound to the package lifecycle, you would find your bundled JAR in your target directory after doing a ...
mvn package
Regarding your concern that your code won't run on another machine, Java is platform-independent and generally you can rely on that. However, three things come to my mind that can make life hard:
Your code depends on the system encoding. Maven should give you a warning on that in the log, advising you to specify it explicitly.
You interact with the runtime, like executing system commands. ps won't work on windows and dir /s probably not on *nix.
The version of your Java environment differ. Of course, JavaFX code won't run with a Java 1.5. If you use the latest features, make sure your clients already have the respective version or, at least, are able to get it from somewhere. You might want to take a look at the source and target compile options, too: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#crosscomp-example

Unable to use Intellij with a generated sources folder

Related question
How to configure IntelliJ IDEA and/or Maven to automatically add directories with Java source code generated using jaxb2-maven-plugin?
I have a custom plugin that generates sources under target/generated-sources (Note no toolname here). So I get sources like target/generated-sources/com/mycompany...etc.
This format cannot be changed at all, so will I be able to configure Intellij into adding it as a source folder. As of now, I can see that Intellij has added target/generated-sources/com as the source folder.
Please note that I do not have the option of configuring the plugin !
UPDATE 1: I do not agree with the fact that I MUST put my generated sources under a tool name folder. It may be a good convention, but if I have only one generator there is no need for me to put it there? Again, in my pom.xml I have a resources section which clearly indicates that target/generated-sources should be treated as a source folder. This works perfectly fine in Eclipse so I have no idea why Intellij would not respect my settings.
TL;DR -> When I put target/generated-sources in the resource section of pom.xml why is Intellij overzealous to add target/generated-sources/com to the classpath?
I'm using Maven (SpringBoot application) solution is:
Right click project folder
Select Maven
Select Generate Sources And Update Folders
Then, Intellij automatically import generated sources to project.
You can just change the project structure to add that folder as a "source" directory.
Project Structure → Modules → Click the generated-sources folder and make it a sources folder.
Or:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>test</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
With gradle, the project settings will be cleared whenever you refresh the gradle settings. Instead you need to add the following lines (or similar) in your build.gradle, I'm using kotlin so:
sourceSets {
main {
java {
srcDir "${buildDir.absolutePath}/generated/source/kapt/main"
}
}
}
The fix
Go to Project Structure - Modules - Source Folders and find the target/generated-sources/antlr4/com/mycompany - click Edit properties and set Package prefix to com.mycompany.
This is exactly the reason why we can set Package prefix on source dirs.
Different but related problem here
Its very simple:
Just right click on the directory and mark it as generated sources root. See the below screenshot.
Solved it by removing the "Excluded" in the module setting (right click on project, "Open module settings").
Whoever wrote that plugin screwed up big time. That's not the way to do it!
Any workaround would be a huge hack, make the plugin developer aware of his bug.
Sorry, that's the only thing to do.
OK here's a hack, directly after your plugin's execution, use the antrun plugin to move the directory somewhere else:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>process-sources</phase>
<configuration>
<target>
<move todir="${project.build.directory}/generated-sources/toolname/com"
overwrite="true">
<fileset dir="${project.build.directory}/generated-sources/com"/>
</move>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
In this example, toolname should be replaced by anything that uniquely identifies the plugin that created the code and com stands for the root of the created packages. If you have multiple package roots, you probably need multiple <move> tasks.
But if the plugin adds the folder as source folder, then you're screwed.
For someone still struggle to fix the generated source not picking up by IntelliJ,
One reason could be the generated file size too big for it to load, then you need to put following line into your "custom IntelliJ IDEA properties" (under menu help)
idea.max.intellisense.filesize=7500
i ran mvn generate-resources and then marked the /target/generated-resources folder as "sources" (Project Structure -> Project Settings -> Modules -> Select /target/generated-resources -> Click on blue "Sources" icon.
I had the same issue with Eclipse a couple of months ago when importing my project. Now I had the same with intelliJ.
Here is how someone helped me to solve this in IntelliJ:
Menu => View => Tools windows => Maven Project
In the spring_user value => Run Configuration, choose clean install.
This should do a clean install and after this you should be able to see the classes
Maybe you can add a step to the generate-sources phase that moves the folder?
The only working condition, after several attempts, was to remove the hidden .idea folder from the root project folder and re-import it from Intellij
I wanted to update at the comment earlier made by DaShaun, but as it is my first time commenting, application didn't allow me.
Nonetheless, I am using eclipse and after I added the below mention code snippet to my pom.xml as suggested by Dashun and I ran the mvn clean package to generate the avro source files, but I was still getting compilation error in the workspace.
I right clicked on project_name -> maven -> update project and updated the project, which added the target/generated-sources as a source folder to my eclipse project.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>test</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
I wanted to ask that sometimes even if the pom is correct, Intellij does not see the directory. One way to solve this problem is to close the project, remove the .idea directory and reopen the project. The 'generated-sources' is added to the classpath (the directory is in blue (it was in red) and we see a star ('*') on the left).
When you run mvn clean install, if you want to mark directory as a generated sources you can use this solution

Organize imports with Maven2, Eclipse-style?

I'm a lone Emacs user in a group that's hung up on Eclipse. Time and again, code diffs are made larger by imports that have been "organized" or "cleaned up" by Eclipse.
I don't have a strong opinion on the subject of import style in Java, but I do want to minimize our diffs. What can I do?
We use Maven2 for builds; is there a plugin that can help me? Can a piece of Eclipse be abstracted out & turned into a Maven plugin? I currently use ImportScrubber and have encountered a few other stand-alone pieces that do the same thing. What I'm really looking for is a Maven plugin that can integrate with the build.
Barring the above, I'll put an ImportScrubber invocation into my .git/hooks/post-commit.
The Hybridlabs beautifier which is used internally in the openArchitectureWare project (an open source generator framework) is doing what you're looking for. As explained in this blog entry, the beautifier is available as a Google Code project and its documentation describes a maven 2 plugin:
<plugin>
<groupId>org.hybridlabs</groupId>
<artifactId>maven-beautifier-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>beautify-imports</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Recursively scan for *.java and beautifies imports -->
<inputDirectory>${pom.basedir}/..</inputDirectory>
<!--outputDirectory>${pom.basedir}/..</outputDirectory>
<runBeautifier>true/runBeautifier>
<runJalopy>false</runJalopy-->
</configuration>
</plugin>
There is indeed a mojo in the source tree but it doesn't match the groupId mentioned above (this is a bit confusing) and I've not been able to find the plugin in maven's public repository.
Maybe you'll be more lucky with the version available in AndroMDA plugin repository as documented in this thread (the plugin is indeed present in http://team.andromda.org/maven2/).
The plugin is under
org.apache.maven.plugins.maven-beautifier-plugin.
It can be run with the short form:
mvn beautifier:beautify-imports. It
can also be run as part of a project
pom by adding the plugin declaration
under <build><plugins>:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-beautifier-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<goals>
<goal>beautify-imports</goal>
</goals>
</execution>
</executions>
<configuration>
<inputDirectory>${pom.basedir}/target/src</inputDirectory>
</configuration>
</plugin>
Or contact the project's author (e.g. through twitter or by mail).
I think all of you (Eclipse, Emacs or whatever users) should use something like Jalopy which supports both Eclipse and Maven. This way it becomes irrelevant where the code was modified as long as it has been run through pretty-printer as part of checking code in. Said that - I'm not sure if Jalopy supports organizing imports beyond sorting these up
I have also found an ImportScrubber plugin. Can't as of yet attest to its quality.
Does your shop have code standards for how imports should be organized? If so then you are out of luck. Minimizing diffs is a small sacrifice to make towards incremental code improvement.

Creating a self-contained source release with Maven

Up until now we used Ant in my company. Whenever we wanted to send the application to the client we run a special Ant script that packaged all our source code with all jar libraries and Ant itself along with a simple batch file.
Then the client could put the files on a computer with no network access at all (and not even Ant) and run the batch file. As long as the computer had a valid JDK the batch script would compile all the code using the jars and create a WAR/EAR that would finally be deployed by the client on the application server.
Lately we migrated to Maven 2. But I haven't found a way to do the same thing. I have seen the Maven assembly plugin but this just creates source distributions or binary ones. Our scenario is actually a mix since it contains our source code but binary jars of the libraries we use (e.g. Spring, Hibernate)
So is it possible to create with Maven a self-contained assembly/release/package that one can run in a computer with no network access at all??? That means that all libraries should be contained inside.
Extra bonus if Maven itself is contained inside as well, but this is not a strict requirement. The final package should be easily compiled by just one command (easy for a system administrator to perform).
I was thinking of writing my own Maven plugin for this but I suspect that somebody has already encountered this.
From your dev environment, if you include the following under build plugins
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
and invoke mvn assembly:assembly, you would get yourApp-version-with-dependencies.jar in the target folder. This is a self-sufficient jar, and with a Main-class MANIFEST.MF entry, anybody can double click and run the application.
You might try this approach:
Use mvn ant:ant to create ant build
scripts from a maven project
Make sure ant is a project dependency
Use the assembly to build an ant
system
or plan b:
Use mvn ant:ant to create ant build
scripts from a maven project
Make sure ant is a project dependency
Write a "bootstrap class" to call Ant and run the build
Use appassembler to build a
scripted build and install environment
In plan b, you'd write scripts to set up a source tree someplace from the packaged source jars, and then use the appassembler build bat or sh scripts to call the bootstrap and build via ant. Your bootstrap can do anything you need to do before or after the build.
Hope this helps.
Perhaps an answer that I submitted for a similar question could be of some assistance. See Can maven collect all the dependant jars for a project to help with application deployment? The one piece missing is how to include the source code in the assembly. I have to imagine that there is some way to manage that with the assembly plugin. This also doesn't address the inclusion of Maven in the distribution.
What was the reason for moving from Ant to Maven? It sounds like you had everything worked out well with the Ant solution, so what is Maven buying you here?
If it is just dependency management, there are techniques for leveraging Maven from Ant that give you the best of both worlds.
the source plugin will give you a jar containing the source of a probject "source:jar". you could then use the assembly plugin to combine the source jars from your internal projects (using the sources to reference these source jars) and the binary jars from the external projects into one distribution.
however, as for turning this into a compilable unit, i have no suggestions. you could certainly bundle maven, but you'd need to create a bundle containing all the plugins you need to build your project! i don't know of any existing tool to do that.
This is how I do it... on the build part of the pom add in this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And then on the profiles section add this bit in:
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
And when I do a maven install it builds the jar and also checks in a jar of the source.

Categories