How to unjar, and edit source and jar it back using maven? - java

I have a situation where i need to Unpack a spring jar and replace a file in that package with my .class file and repackage it back as jar. I understood that this can be done in Maven. So i created a maven project and i added the .java(to be replace in the Spring jar) to it . Here is my Project structure.
here is my pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<name>repackage</name>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.4.6</version>
<packaging>pom</packaging>
<build>
<plugins>
<!-- Unpacking -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.6.SEC03</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>target</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- Packing -->
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>target</classesDirectory>
<classifier>sample</classifier>
</configuration>
</execution>
</executions>
</plugin>-->
</plugins>
</build>
</project>
I am able to unpack the spring jar using maven dependency plugin and i figured out how to pack it back to a jar using maven-jar-plugin. The part i am struggling to understand 1) how convert my .java file into a .class file. As the packaging is pom type <packaging>pom</packaging> I am not able to compile the java file(JdkVersion.java). if successful in creating the class file 2) How to replace this .class file into unpacked spring jar as the file i need to replace is inside the sub directory of /springpackage

You don't have to. Spring is an open source project just clone its source code https://github.com/spring-projects/spring-framework?files=1 and update the code and create a package using simple mvn package command

Related

Spring Boot Layered jar: Extract layers.xml to separate dependency

I'm starting to catch up on the capabilities of the repackage goal in spring-boot-maven-plugin.It looks promising, but I need to fine-tune it a little.
I can easily do that by creating a layers.xml file somewhere in my project, but the problem is that I don't only have 1 project, but rather half a dozen. All of the projects need the same kind of layering, but I don't really want to copy the same configuration for every project I want to use it on.
A nice-looking solution would be to extract that configuration file into a separate jar for example and have the plugin take the config file from there, but I see no way of doing it. Is there any other solution that doesn't involve me copying the configuration file to every project I have?
Unfortunately, even though the projects I have use the same parent, but are not in the same multi-module project.
I managed to work out a solution.
Before asking the question my spring-boot-mave-plugin config looked something like this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<phase>package</phase>
<configuration>
<layers>
<enabled>true</enabled>
<configuration><!-- something like classpath:layers.xml --></configuration>
</layers>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>artifact</groupId>
<artifactId>with-layers.xml</artifactId>
<version>...</version>
</dependency>
</dependencies>
</plugin>
The solution becomes one step more convoluted, by bringing in the maven-dependency-plugin, which downloads the before mentioned dependency and unpacks it in the build folder with this configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-shc-build-tools</id>
<goals>
<goal>unpack</goal>
</goals>
<phase>package</phase>
<configuration>
<artifactItems>
<artifactItem>
<groupId>artifact</groupId>
<artifactId>with-layers.xml</artifactId>
<version>...</version>
<type>jar</type>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>**/layers.xml</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
<configuration>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</plugin>
In turn, the line <configuration><!-- something like classpath:layers.xml --></configuration> becomes <configuration>${project.build.directory}/layers/layers.xml</configuration>.
The documentation for Spring Boot Maven Plugin states you can set the path to the layers.xml manually, so why not have all pom.xml point to the same location?
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.2.RELEASE</version>
<configuration>
<layers>
<enabled>true</enabled>
<configuration>${project.basedir}/../layers.xml</configuration>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
The /../ means one level higher from the project directory. So say you have a bunch of projects in one directory, put the layers.xml there and it'll work.
Another approach could be to reuse the Maven Plugin declaration by moving it to a so-called parent POM. This is a technique where the common/shared parts of the POM files of a series of projects is moved to a single POM file (the parent POM). Here's an example

Maven copy only specific dependencies

I'm developping an OSGI email client with Maven following component-based software engineering. I must make sure that the dependencies between all my components are resolved inside of the OSGI container, so I cannot copy the dependencies inside the generated JARs, otherwise there would be no point using OSGI. But there is one dependency I really have to copy inside of the JAR, it's javax.mail, because I cannot find any OSGI-compatible bundle that does emailing.
To do that, I have seen this page: https://maven.apache.org/plugins/maven-dependency-plugin/examples/copying-artifacts.html
So I edited my pom.xml:
<project>
...
<build>
<plugins>
<plugin> <!-- to edit the MANIFEST.MF, required for OSGI -->
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>4.2.1</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Class-Path>lib/</Class-Path>
... OSGI instructions ...
</instructions>
</configuration>
</plugin>
<plugin> <!-- to copy the dependencies -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
But the <artifactItems> tag doesn't seem to work. When I mvn install, it copies ALL the dependencies into a dependency/ folder and not a lib/ folder. How can I do to copy only the javax.mail JAR into a folder named lib/?
Thank you for your help.
The maven-bundle-plugin allows to embed dependencies:
https://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html
<Embed-Dependency>javax.mail|javax.mail-api</Embed-Dependency>
You mixed up the goals copy-dependencies and copy. Replace copy-dependencies by copy.
http://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

Maven wsdl import. How to use the generated files?

i have a problem and I'm not able to solve or understand the hole workflow behind this process.
I use eclipse with maven.
This is my simple test pom.xml
...
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.2.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xdebug>true</xdebug>
<verbose>true</verbose>
<keep>true</keep>
<packageName>abc.model</packageName>
<sourceDestDir>${project.build.directory}/generated-sources/wsimport/</sourceDestDir>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/wsimport/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
The jaxws-maven-plugin generate the files in the sourceDestDir. The build-helper-maven-plugin add the files during the maven install process the to the correct folder and also into the resulting jar file. So far so good.
But I'm not able to use the generated files/classes in eclipse. So in eclipse maven does not recognize the files as source or does not but this in the source path. Did I make an mistake or did I miss something?
Thanks for your help.
Update:
I observer a strange behavior. Same test project same pom file. If I import this existing Maven Project in eclipse it works like expected. I can directly use the generated files as source.
But if I delete this source folder, I'm still not able to restore this with maven.

Unpack Maven dependency into classes, keeping transitive dependencies

I am trying to unpack a maven dependency jar's contents into my classes folder, and at the same time include the transitive dependencies. I also don't want to unpack all of my project's dependencies. Only one would be good, even better if I could do this to a list of them. Found similar solutions but nothing addressing my exact issue.
Example Main Project Pom:
.
.
.
<dependencies>
<dependency>
<groupId>com.test.dep</groupId>
<artifact>first-dependency</artifact>
</dependency>
<dependency>
<groupId>com.test.dep</groupId>
<artifact>second-dependency</artifact>
</dependency>
</dependencies>
.
.
.
Example second-dependency Pom:
.
.
.
<dependencies>
<dependency>
<groupId>com.test.dep</groupId>
<artifact>third-dependency</artifact>
</dependency>
<dependency>
<groupId>com.test.dep</groupId>
<artifact>fourth-dependency</artifact>
</dependency>
</dependencies>
.
.
.
I want second-dependency to be unpacked into my classes folder nested under target and also want any of the artifacts (third-dependency, fourth-dependency) it depends on to still be included in my lib folder (not unpacked).
I tried the following (without including the the artifact in my dependencies):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.test.dep</groupId>
<artifactId>second-dependency</artifactId>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>**/*</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
And this did include the contents of second-dependency in my classes folder, but did not include third-dependency or fourth-dependency in my main projects lib directory.
Any ideas?
Try to use following plugin configuration, based on the described parameters of dependency:unpack-dependencies, instead:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includeArtifactIds>second-dependency</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
Im not sure about your use case.
But if you want to build jar, that sounds like a use case for the maven-shade-plugin. This plugin is able to package the classes and resources of the project itself as well as of a specified set of artifacts (dependencies) into one jar.
Just define the artifact itself ("${project.groupId}:${project.artifactId}") and the "second dependency" to be included.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<configuration>
<artifactSet>
<includes>
<include>${project.groupId}:${project.artifactId}</include>
<include>com.test.dep:second-dependency</include>
</includes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>

How to move (or copy) a war's jar to another war's folder?

I have maven prj with 2 modules: a JAR and a WAR that depends on the JAR.
after the MAVEN INSTALL I have into a WAR the classic WEB-INF/lib folder that contains all the jar dependencies(including the first module's JAR).
I need the first module's JAR is moved to another folder, for example WEB-INF/resources.
as I can?
I was able to move the jar but only within the TARGET, the WAR remains the same.
I used the following plugin:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>copy-installed</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.0</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/.../WEB-INF/services</outputDirectory>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/.../WEB-INF/services</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
For now, I surrendered.
I could not move this JAR from WEB-INF/lib to WEB-INF/services of the EAR.
The workaround I used is to say MODULE1 to copy its JAR in the WEB-INF/services of MODULE2. Consequently, the JAR will be present in the WEB-INF/services of the sources folders, in the WEB-INF/services of the TARGET folders and in the end in the WEB-INF/services of the EAR.
i used:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<outputDirectory>..MOSULE1/src/main/webbapp/WEB-INF/services</outputDirectory>
</configuration>
</plugin>
</plugins>
into MODULE1 pom.
I had to give up to make module1 independent module2 ;(
i hope i will found a clean solution..
Maybe this will help:
<project.warSourceDirectory>${basedir}/src/main/webapp</project.warSourceDirectory>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>copy-installed</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.0</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.warSourceDirectory}/WEB-INF/services</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>

Categories