In a maven project, is it possible to use a plugin just built within the same project? - maven

Suppose you have some sort of input files which are to be processed in some custom way (even the file format is very particular to the package of files in question).
To process them I decide to make a maven plugin, which happens to be useful only in the context of these files.
Is it possible to have them all (the afore mentioned files and source code for the plugin) in one project, build the plugin, run the plugin over the input files and collect its output as the output of this project?

Short answer is you can't, because Maven resolves plugin classpath on start.
However you can create separate modules, first being a plugin and second would use that plugin to process files. Both modules can be invoked from parent pom.

Related

Gradle search local maven or gradle repository

I am using gradle and its local repository is at \.gradle\caches\modules-2\files-2.1 which has all the downloaded jar but not my modules.Is there any specific place I should be searching it for ?
I need it as is in settings.gradle I am having a dependency path specified like :
include ':model'
project (':model').projectDir = new File(settingsDir, './model')
in a new project. Also I don't want to give path in that way because if I have a dependency from multiple projects on this project then mentioning path will be difficult and weird.
How can I make gradle search it from local maven or gradle repositories.
I'm still not sure what is being asked here, and I suspect there is some confusion over how multi-project builds work. So I'm going to attempt to provide a general-purpose answer.
The first question you need to answer is whether you're interested in dependencies between projects that are part of the same build — as in part of a multi-project build — or in separate builds.
Project dependencies (multi-project builds)
Project dependencies are covered in the user manual and only apply to multi-project builds. They use a logical path, using colons as 'path' separators, to specify the location of the target module, like so:
dependencies {
implementation project(":model")
}
At this point, Gradle needs to know where ":model" exists on the file system. There's no getting around that. You have a few options:
Follow the convention of directory structure matching the logical path structure, i.e. have a MyBigProject/model directory containing the ":model" child project
Specify the file path of ":model" in settings.gradle, e.g. with project(":model").projectDir = new File(rootDir, "unusual/path/to/model")
Automate the discovery of projects
The most common approach is the first one. The second is not unusual, particularly if you want to put child projects into a separate directory, like subprojects — something the build of Gradle itself does. I haven't seen the last option done, and I don't know whether it runs into problems.
For the sake of completeness, and at your own risk if you use something like it, here's an example of automatic discovery of projects in the settings.gradle file:
rootDir.eachDir { File dir ->
if ("build.gradle" in dir.listFiles()*.name) {
include dir.name
}
}
This fragment basically looks for directories within the root project folder that have a build.gradle file in them and adds them as child projects. The child projects' directory names become the projects' names.
It's not particularly clever, and you should really use different names for the build files, but it may give you some ideas to work with.
Non-project dependencies
As with project dependencies, Gradle needs to know where to get the corresponding JAR or other form of artifact for a specified module. You normally specify Maven Central or something similar for this, but there are other useful, but less common, options:
Copy a project's artifacts into the local Maven repository — both the Maven Plugin and Maven Publish Plugin support this
Publish to a Maven-compatible repository using a file:// URL rather than an HTTP/HTTPS one, which protects your projects from corruption of Maven Local
Worth noting is that Gradle supports composite builds that allow you to substitute a normal dependency with (effectively) a project dependency from another build. So if model were part of a separate build but you had the source code and build locally, you could make changes and immediately test them in another build's project without going through the whole "install" intermediate step that's common in the Maven world (and Gradle pre-composite-builds).
Hope all this makes sense.

Deploy zip artifact from another build action to Nexus

Is it possible to deploy arbitrary zip archive artifacts to Nexus through Maven as snapshots?
We have a build step that is not supported through any application-specific Maven plugin. Instead, our full build and deployment process is as follows:
1) Maven POM compiles the Java component of the build, using Jenkins.
2) Shell script calls create a deployable artifact shell scripts were wrapped around calling a code generation application, which are then zipped up into an archive by the application itself. I need these artifacts deployed to Nexus as both snapshots, and as releases as appropriate.
I tried using the maven-assembly-plugin however this assumes that the plugin itself is creating the zip archive, not simply deploying an archive that was produced by some other method.
I would prefer to do this within Maven since our Nexus settings and credentials are already within the environment and do not need to be passed manually on the command line. Using the Nexus UI for this is not a viable option since this needs to be part of a standard build-deploy-test process, which may happen many times per day, for a couple dozen applications.
For completeness, I'm answering my own question (oh bother...)
I resolved this issue by using the maven-assembly-plugin, which allows you to define arbitrary artifacts, and deploy them (snapshots or releases) to Nexus. The assembly plugin uses a bill of materials (src.xml) that defines the exact contents of the artifact (either including or excluding files, directories, changing file permissions, etc). This can also be used for creating Java uber jars, but it appears that using the Maven Shade Plugin is the preferred method for creating uber jars.
Maven Assembly Plugin main webpage

Custom dependency management plugin in Gradle

How do you write a custom gradle plugin to handle dependencies in a custom module descriptor, from a custom repository? The gradle documentation says the following, but I haven't been able to find anything that tells me how.
Even if your project is using a custom dependency management system or
something like an Eclipse .classpath file as master data for
dependency management, it is very easy to write a Gradle plugin to use
this data in Gradle.
I've been maintaining a Custom Ivy resolver for ATG projects (forked from this project), but Gradle recently deprecated this with version 1.8, and I need to port the implementation to a native Gradle plugin.
Implementations of ATG use 'modules' (not unlike Gradle projects), that have a MANIFEST.MF file for a module descriptor. These files define other 'modules' that a module depends on, and also a list of paths (jars or directories) that form the (direct) classpath for the current module.
e.g.
ATG-Class-Path: lib/classes.jar lib/commons-beanutils-1.7.jar
ATG-Required: MyProj.core MyProj.integration.webservices DAF.Endeca.Assembler
Module dependencies are transitive, and may refer to custom modules or modules that sit within the ATG product installation. Hence, I need to define a custom repository that can use the ATG product installation as a source of artifacts.
Without Gradle, I need to maintain dependencies in the form of
ATG's MANIFEST.MF files
Eclipse .classpath files
Dependencies for the Ant build-script
SonarQube configurations
Since I can't get rid of the ATG MANIFEST.MF files, I would like to write a write a custom plugin to allows them to be used in Gradle builds. I can then use Gradle as my build system, which can also generate Eclipse .classpath and .project files, and run Sonar against the project.
Gradle seems to have a lot of source code, and rummaging through it for the last couple of days hasn't got me anywhere.
If someone can point me to a list of interfaces that need to be implemented to (1) implement a custom repository, and (2) implement a custom dependency resolver (to use custom files as module descriptors), that should be enough to get me started.
The Eclipse .classpath use case mentioned above can be solved by parsing that file and translating it to Gradle file dependencies. It isn't currently possible to plug in a custom repository implementation.

How should I manage post-build tasks?

I have a java application.
I can run the Maven Release task which will do some nice things for me:
Change Version number from 1.0.0-SNAPSHOT to 1.0.0
Increment the version number in my pom to 1.0.1-SNAPSHOT
Tag the release in source control
Upload the resulting package to my maven repository
I'd like to take things a step further. I have some post-build steps that I'm currently doing manually.
Update the launch4j configuration xml file with the appropriate version
Wrap the resulting jar in an executable using launch4j
Copy the resulting EXE into a package directory
Copy several supporting files into the package directory
Zip the package directory up
Email the package to my testers.
Eventually I'm going to have the additional task of building an installer leveraging the package directory.
I don't know that maven or ant are the right tools for automating my remaining 6 tasks, but it looks like either one or a combination of both could potentially accomplish what I need.
I could probably write a batch file or a simple perl script to do these things quicker than figuring out how to do them, but I would prefer to keep things as standard as possible so that I'm not taking on the additional responsibility of supporting a hack of a release process perpetually.
It seems to me that these are tasks that might not be standard part of build/release, but are commonly seen enough that there should be a best/most common practice for accomplishing them.
I would suggest to use the maven-assembly-plugin as well as the maven-launch4j-plugin during your build.
Update the launch4j configuration xml file with the appropriate version
put a placeholder into the configuration xml and let maven replace it during the
the build.
Wrap the resulting jar in an executable using launch4j
use the launch4j-maven-plugin to create the executable.
Copy the resulting EXE into a package directory
I would suggest to put the resulting artifact into a repository manager instead
of a separate folder, cause in Maven all artifacts are stored within
a repository. It might be necessary to setup your own repository manager
(Artifactory, Nexus, Archiva).
Copy several supporting files into the package directory
Using them as resources (src/main/resources) they will be copied
automatically.
Zip the package directory up
Use the maven-assembly-plugin to create a resulting zip file.
Email the package to my testers.
You can use a CI like Jenkins etc. to send the final mail or
you can take a look into maven-changes-plugin which might be solution.
This means all your mentioned steps can be handled by Maven during a usual build. This means in the end you can use the maven-release-plugin to produce a full release which contains all the above steps and produces all the wished artifacts.
If I were you, I would try a combination of the following:
Maven release plugin, unless it is not flexible enough for SCM related processes. If using SVN as SCM, I would use directly SVNKit(inside a custom Maven plugin), if flexibility is a concern.
Maven launch4j plugin.
Maven assembly plugin
Maven Ant Run plugin and/or one or more in-house Maven plugins for the remaining tasks.

Adapting ANT scripts for updating EAR file to Maven

I have an Ant script for automating a few tasks that are not build related by mainly as updates to the EAR file. These include calling SoapUI exe for some web services, unpacking the EAR file modifying a few classes and repacking it.
Now, for some reason I would like to do the same using maven scripts. From going through Stack Overflow and maven tutorial, I find that this can be replicated using Ant plugins inside maven. Also, I could not find direct substitutes for unpacking the EARs or calling executables in maven. This scripts will not have anything to do with the standard build process that maven is meant for and only caters to some cleanup or update of already deployed EAR.
So how do I go about this? Use Ant plugins inside maven or is there a better maven way to do this?
Thanks,
This may be an incomplete answer but -
Maven is more of a framework and it's going to want to build your application. What it will not do is modify source. It will process source files (.java, .ear, whatever) and put them in a target/ directory. Of course anything is possible (re: hackable) but this is off the rails as far as Maven is concerned if you want in place modification of source - besides, isn't the point of source that it's source, and if you're automating a task that should be part of your build, deploy, startup, etc.?
Maven resource filtering is how to process a source file and stamp dynamic information into your resources.
If you can provide more information regarding how you are processing your .ear files exactly you can possibly put together the pieces in the Maven process resources phase using existing plugins. Worst case you can write your own plugin.

Resources