Replace class files before maven assembly - class

I'm facing a very unique situation and need some advice:
I'm working on a project which depends on an other project from my same company and now I need to apply some modifications to the dependency.
The problem which I have is that the source code from the dependency has been lost, so the only thing I have is a maven dependency in the repository, with the corresponding jar file.
On top of that, some of the classes in the Jar file where created using JiBX parser, mapping some XSD files which I neither have, and the resulting classes are synthetic and I found no decompiler able to handle them properly.
The only good thing of all of that is that the class which I need to change can be properly decompiled, so went for the following:
I decompiled the whole jar file and ended up with some classes (the
JiBx ones) with empty or wrongly implemented methods.
I commented out the body of the wrong methods to have stub objects, applied the required changes to the right classes and recompiled.
I took the old Jar file, opened it and manually replaced the old class with the new one.
And the resulting Jar worked as expected.
Now my question is: Can I do all of that using Maven?
The idea would be to put the JiBX class files as resources, and keep the stub equivalents as source files and then let maven:
Compile everything as usual, putting all the compiled class files
into target folder
Remove stub class files from target folder and replace them with the old precompiled class files
package the jar.
Which approach would you recommend?
UPDATE
I give some more details about the dependency project structure:
All classes are inside the same package:
my.project.domain.JiBX__c_GeneratedObfuscatedClass1.java
my.project.domain.JiBX__c_GeneratedObfuscatedClass2.java
my.project.domain.JiBX__c_GeneratedObfuscatedClass3.java
my.project.domain.CustomizableClass1.java
my.project.domain.CustomizableClass2.java
my.project.domain.CustomizableClass3.java
JiBX classes are not imported properly as dependency and if I try to put any of the CustmizableClasses into the project source and let the JiBX ones be in a dependency, the compiler reports missing methods.
I also tried using the Shade Plugin as suggested, but since I need to include the JiBX classes into my source path, I will end up having to include into package JiBX classes from jar dependency and compiled CustomizableClasses, but skipping CustomizableClasses from jar dep and compiled JiBX classes.
I looks like it can work, but I admit that I still didn't find the way of doing it.
Any clues will be very welcomed.
UPDATE 2 (RESOLUTION)
I explain here how I finally managed this using the shade plugin as suggested, just in case someone else needs to do the same:
I finally created a project with the decompiled classes inside the same package, and left the methods which didn't want to be decompiled commented out.
In the pom.xml I added the following:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>${project.groupId}:${project.artifactId}</include>
<include>TheDamnedProject:WithoutSources</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>TheDamnedProject:WithoutSources</artifact>
<includes>
<!-- These classes will be taken directly from dependency JAR -->
<include>my/package/ClassWhichCouldNotBeDecompiled1.class</include>
<include>my/package/ClassWhichCouldNotBeDecompiled2.class</include>
<include>my/package/ClassWhichCouldNotBeDecompiled3.class</include>
<include>my/package/ClassWhichCouldNotBeDecompiled4.class</include>
</includes>
</filter>
<filter>
<artifact>${project.groupId}:${project.artifactId}</artifact>
<excludes>
<!-- These classes will be overridden by the ones inside the JAR -->
<exclude>my/package/ClassWhichCouldNotBeDecompiled1.class</exclude>
<exclude>my/package/ClassWhichCouldNotBeDecompiled2.class</exclude>
<exclude>my/package/ClassWhichCouldNotBeDecompiled3.class</exclude>
<exclude>my/package/ClassWhichCouldNotBeDecompiled4.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
thanks!
Carles

Here's how I would do that:
Create a new Maven project for this Jar file, with packaging type jar
Include the original Jar file as a dependency
Add the one decompiled .java file in the src folder
This should get you to a point where the .java file can be compiled, since the other classes from the jar file are available.
You now have two Jar files: one original, and one that should just contain the single recompiled and changed class.
Adding both to your application class path might work, but will depend on the order on the classpath.
If you want to end up with one jar file, I recommend to take a look at the Maven Shade Plugin (http://maven.apache.org/plugins/maven-shade-plugin/), which will allow you to create a new Jar file with contents from multiple sources. It will allow you to filter what goes into the new Jar file.
The Maven Shade plugin allows you to specify which classes from each artifact are included. It uses wildcards and include/exclude tags for this, as described here: http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html
Once that Jar file is created, I would release it using the Maven Release plugin, and then include that artifact downstream. This will allow you to only update the patched Jar when it is really required, it probably doesn't have to be on every build. But that depends on your usage pattern.
For the version number of the new Jar file, I recommend to use a variation of the original one. Use the same groupId and artifactId, then modify the version number. If the original has 1.0.2, your new, patched file should be released as 1.0.2-1, to indicate that it's based on the 1.0.2 sources. If you need to make an additional change, release that as 1.0.2-2 and so on. This will make it easy to understand which version your patches are based on, and the incrementing patch number will give you a means to distinguis the releases.

Related

p2-maven-plugin -- bundle conflicts with other existing bundle

I’m starting to use the p2-maven-plugin in order to integrate non-OSGi JARs into our project in a (hopefully) convenient manner.
I have an artifact which I want to OSGi-ify, called com.thirdparty.artifact. I’m current using p2-maven-plugin’s standard configuration, and I list my artifact in the pom.xml like so:
<artifact><id>com.thirdparty:artifact:1.2.3</id></artifact>
This artifact has a transitive dependency called com.thirdparty:library:2.5, which exports a package com.thirdparty.library which is in turn imported by com.thirdparty:artifact. When I run mvn p2:site, I get a P2 site which contains com.thirdparty:artifact:1.2.3 and com.thirdparty:library:2.5 -- all fine so far.
Now, things are turning messy. My existing target platform already contains an artifact called com.othervendor:library (different vendor, it’s there and I cannot change that), which also exports the very same package com.thirdparty.library (but an entirely different version).
At runtime, the OSGi/Eclipse black magic (which I’ll probably never fully understand) tries to resolve com.thirdparty:artifact’s dependency on the package com.thirdparty.library using the com.othervendor:library and not my provided com.thirdparty:library:2.5 -- and I’m obviously in trouble. Here’s a visualization of my situation:
Being absolutely no OSGi rocket scientist, my first idea was to inspect the MANIFEST.MF in com.thirdparty:artifact. Beside others, this shows the following:
Import-Package: com.thirdparty.library
So, this obviously just tells com.thirdparty:artifact to import this package from some bundle, and OSGi/Eclipse thinks “okay, com.othervendor:library is more adequate than com.thirdparty:library”.
There seem to be two methods of narrowing down the dependencies to actually use. However: I’m not sure (a) how to integrate them into my p2-maven-plugin workflow, and (b) I do not understand why p2-maven-plugin does not automatically require the concrete package version in the Import-Package directive (this information is after all already specified in the source pom.xml).
Probably I’m not seeing the forest for the trees here. So any general advice beside my questions above is very welcome!
[edit] Here’s my pom.xml (the concrete library which I’m about to OSGi-ify is Selenium):
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>com.example.p2dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.reficio</groupId>
<artifactId>p2-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<artifacts>
<artifact><id>org.seleniumhq.selenium:selenium-java:3.4.0</id></artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
[edit2] Problem seems to be solved, it seems, the issue was an additional package which was only exported by com.othervendor:library.

Check the inheritance chain from module; it may not be inheriting a required module or a module may not be adding its source path entries properly

I want to create a gwt maven project with multiple gwt modules. some of them are just utility modules means they have no entry point. Basically I have already a gwt project with multiple gwt modules in it and I have converted it to maven but while compilation its giving me following exception :
[ERROR] Unable to find type
'in.appops.showcase.web.gwt.uploadservice.client.UploadService' [INFO]
[ERROR] Hint: Previous compiler errors may have made this type
unavailable [INFO] [ERROR] Hint: Check the inheritance chain
from your module; it may not be inheriting a required module or a
module may not be adding its source path entries properly
My project has core and dispath modules which are utility modules without entry point and other uploadservice module which has entry point which is inheriting the core module .
So I put core.gwt.xml ,dispatch.get.xml in their packages i.e in src/main/java itself and uploadservice.gwt.xml in resources folder of maven.
also in pom.xml I am providing the modules to compile:
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<goals>
<goal>clean</goal>
<goal>resources</goal>
<goal>compile</goal>
<goal>i18n</goal>
<goal>generateAsync</goal>
</goals>
<configuration>
<runTarget>Index.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
<modules>
<!-- <module>platform.bindings.web.gwt.dispatch.Dispatch</module>
<module>platform.core.Core</module> -->
<module>showcase.web.gwt.addressbook.AddressBook</module>
<module>showcase.web.gwt.uploadservice.UploadService</module>
</modules>
</configuration>
</pluginExecutionFilter>
<action>
<execute />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
can anybody help me to get out of this exception. Is it neccessary that I need to provide the order to compile the modules or anything else?
Note 1 -
When using gwt standard approach your folder structure
src/main/java/showcase/web/gwt/yourmodule/yourmodule.gwt.xml
src/main/java/showcase/web/gwt/yourmodule/client
src/main/java/showcase/web/gwt/yourmodule/public
Your pom references
<module>showcase.web.gwt.addressbook.AddressBook</module>
<module>showcase.web.gwt.uploadservice.UploadService</module>
Your .gwt.xml file location
src/main/java/showcase/web/gwt/addressbook/AddressBook.gwt.xml
src/main/java/showcase/web/gwt/uploadservice/UploadService.gwt.xml
Note 2 - <lifecycleMappingMetadata> is for your m2e = maven eclipse plugin. For clear example of GWT MAVEN POM example - http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/validation/pom.xml
Note 3 - Exactly follow the extremely simple example of gwt maven sample project - http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/validation/
DO NOT CHANGE FOLDER LOCATION. *FOLLOW THE NAMING CONVENTION.* even folder names like public, client are picked by "name" in GWT.
If this error occurs upon loading the entry point, you may need to change the tags in your *.gwt.xml file.
After changing my package structure, I was able to successfully fix the error, "Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly".
In your .gwt.xml file, find the source tags near the bottom of the file.
revert to an earlier working commit, or open a known working project
take note of the pattern that the working source tags follow relative to the package structure of your working project.
roll forward to the broken commit
modify your source tag(s) to correspond to the current package structure, following the same pattern.
In addition, you should check to make sure you have the appropriate inherits tags in your .gwt.xml file. For example, you will get a similar error if you attempt to use SmartGWT without the tag inherits name="com.smartgwt.SmartGWt"
Your UploadService.gwt.xml file should be in src/main/resources/in/appops/showcase/web/gwt/uploadservice. Others GWT module descriptors should be in their packages as well.

GWT. Maven. GWT Module <module_name> not found in project sources or resources

I have a maven multi-module project. One of this modules (compiled as .jar) contains only domain objects, which will be used at client and server sides (I add this .jar as dependency to other my modules).
I know that GWT module, where will be used objects from shared .jar, must also have source files for successful compilation. So I tried to add to my pom.xml both:
<resources>
<resource>
<directory>src/main/java/<path></directory>
<includes>
<include>**/*.java</include>
<include>**/*.gwt.xml</include>
</includes>
</resource>
</resources>
and
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<versionRange>[${gwt.version}]</versionRange>
<goals>
<goal>resources</goal>
</goals>
<plugin>
But resulting .jar don't contain GWT module source (i.e gwt.xml). All sources of domain classes are added as well (at root directory of .jar), but ModuleName.gwt.xml not.
Where is problem? Thanks.
If your .gwt.xml file is in src/main/resources/ then it won't get copied if you specify src/main/java/ as the resource path...
You should probably omit the <resource> section and let the GWT plugin include the source in the jar or at least have two sections, one for the .gwt.xml file (src/main/resources or where you put it) and one for the source code (as you have it now).
Cheers,
I was troubleshooting this error today so I'm just posting my fix:
Multi-module gwt project being build with the maven gwt plugin needs an entry in the pom.xml like:
<modules>
<module>../theothermodule</module>
</modules>
In order to compile.
This error have multiple explanations. Check list:
if you are referencing a gwt module you need to point to the *.gwt.xml file in dot notation without the file extension. E.g. com.example.ThirdParty refers to com/example/ThirdParty.gwt.xml module
to import the 3rd party module, add <inherits name="com.example.ThirdParty" /> to your *.gwt.xml file
the ThirdParty.gwt.xml should contain one or more source elements pointing to translatable code. E.g. <source path='shared' />.
all translatable code in ThirdParty.jar needs to include plaintext *.java sources. E.g. com/example/shared/Widget.class and com/example/shared/Widget.java are both present
the ThirdParty.jar is on your classpath
Notes:
if the ThirdParty gwt module does not have entry point it does not need to be compiled with gwt compiler
the gwt compiler does not require extra configuration to include the ThirdParty module as long as its jar is on classpath and your *.gwt.xml inherits ThirdParty.gwt.xml; the same applies to the gwt maven plugin

Including scala-library.jar in Maven generated package

I'd like to use Maven to include all the dependencies needed to run any Scala programs I write. I imagine this would mean at least scala-library.jar as well as any libraries I may use.
I don't mind where these dependencies are stored (inside the generated JAR or outside), I'm just looking for a solution that sets up stuff like the manifest file classpath and generally requires a minimum amount of manual intervention and boilerplate configuration.
Thanks.
You can use the jar-with-dependencies descriptor format that comes with the Assembly plugin:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
When you run mvn assembly:assembly you'll get a jar with all dependencies (including any necessary Scala libraries) in your target directory.
Use scala-archetype-simple archetype. Here are the list of other archetypes.

deploying a maven project

I have a maven project and I'd like to create a distribution of it with the dependencies. I've tried the maven-assembly-plugin and built the jar with dependencies, but that unpacked all of the jars and repackaged them all into a big, single jar. What I'd like is something like my jar file and a lib folder that has all of the dependencies. Then when I run it, I could run "java -cp lib/* my.package.MainClass".
What's the best way to go about doing this with maven? Or the recommended way to deploy?
thanks,
Jeff
I have used the Maven assembly just for that in my project.
First enable your plugin in your POM and call your assembly config :
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<!--I recommend 2.1 as later versions have a bug that may
Duplicate files in your archive
-->
<version>2.1</version>
<!--Executes the packaging along with the mvn package phase
-->
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<!--Relative path to your descriptor -->
<descriptor>src/main/assembly/package.xml
</descriptor>
</descriptors>
</configuration>
</plugin>
Then in your descriptor you can decide how you want your layout to be before you package the whole thing
<assembly>
<!-- this will create an extra resource project-1.1.1-package.zip, you can
choose jar as well in the format-->
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<!-- Insert here extra files as configs or, batch files, resources, docs etc-->
<fileSets>
<fileSet>
<directory>src/main/assembly/files</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/conf/*.*</include>
<include>**/doc/*.*</include>
</includes>
</fileSet>
<!-- I like to integrate the jre as well... simplifies my deployement -->
<fileSet>
<directory>target/jre</directory>
<outputDirectory>/jre</outputDirectory>
</fileSet>
</fileSets>
<!-- This will scrub your dependencies and add them to your lib folder, I excluded
Test stuff as it is not needed, could have declared the resource as a test
only phase as well would not have had to exclude it here
-->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<excludes>
<exclude>junit:junit</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
This will create a zip file with the layout you have specified in your output directory config, package the whole thing as a zip file (you can choose zip, jar, war ...) and deploy it in my repository with the rest.
I skipped bits and pieces to make it simpler but my package expands to include batch files, dlls, config, doc and the JRE so everything needed is in the same zip... all is needed to run the thing is extract and click start.bat !
I could also probably make it in to a jar properly formatted with METADATA and just double click the jar itself to start it all, I did not need or have time to toy around this option but you may try it as well.
Beware of versions above 2.1 of the assembly plugin, it will create duplicate entries if your directives enable it to find the same file in different locations, this will give you a lib folder with the same jars repeating twice. not very dangerous as unzipping will collapse them but still annoying to have the unzip ask you if you want to overwrite files. Plus the fact that you do not know which won if somehow they turned out to be different in content.
Maven is great but I find that it is sometimes frustrating to get it working, Plus documentation can sometimes be hard to find and use. However, used appropriately it will save you tons of time.
good luck
See:
http://maven.apache.org/shared/maven-archiver/index.html
You should be able to use the maven-jar plugin to package up an archive, specify the main class to execute along with the classpath. It can generate a manifest file for you for your project.
http://maven.apache.org/shared/maven-archiver/examples/classpath.html#Prefix