Comments (14)
The documentation states: A Byte Buddy plugin that transforms a project's production class files where all scopes but the test scope are included.
This means that the dependant classes will be resolved, and can be analysed during the build, for example as annotation properties. Any Maven module can however only transform the (test) classes that it defines. Dependencies cannot be instrumented during a build.
from byte-buddy.
I found a related issue where you advise to use Plugin.Engine.Default
to transform a library's jar file. How do I do that?
Does my custom plugin need to implement Plugin.Engine
or do I to extend the ByteBuddy mojo to load the library jar and pass the classes as Source
?
from byte-buddy.
You can apply an engine to any folder or jar file, just as you can specify any folder or jar file as a destination. If you downloaded the jar during a build and transformed it, you might be able to substitute the dependency later. This is however related to how you run your app.
from byte-buddy.
But to apply the engine to the jar file I need to use a custom mojo or can I configure the ByteBuddyMojo to do that? Downloading the jar during the build is no problem.
from byte-buddy.
There is now, good point, this was missing.
Could you build Byte Buddy from master and see if that works for your real-life scenario? You would need to use the transform-location target and specify source and target. If you want to add other locations for class file resolution, you would need to specify locations as dependencies which will be resolved and added.
from byte-buddy.
The goal fails with a PluginConfigurationException:
Unable to parse configuration of mojo net.bytebuddy:byte-buddy-maven-plugin:1.14.19-SNAPSHOT:transform-location for parameter dependency: Cannot create instance of class net.bytebuddy.build.maven.MavenCoordinate
due to public List<MavenCoordinate> dependencies;
.
I changed it to List<CoordinateConfiguration>
and resolved it to an artifact in resolveClassPathElements()
.
Map<Coordinate, String> coordinates = new HashMap<Coordinate, String>();
if (project.getDependencyManagement() != null) {
for (Dependency dependency : project.getDependencyManagement().getDependencies()) {
coordinates.put(new Coordinate(dependency.getGroupId(), dependency.getArtifactId()), dependency.getVersion());
}
}
String managed = coordinates.get(new Coordinate(project.getGroupId(), project.getArtifactId()));
for (CoordinateConfiguration dependency : dependencies) {
MavenCoordinate mavenCoordinate = dependency.asCoordinate(project.getGroupId(), project.getArtifactId(), managed == null ? project.getVersion() : managed, project.getPackaging());
I also had to change the apply
method to pass the classpathElements
as a compound source since the library jar was never transformed when I configured my source as ${project.build.sourceDirectory}
List<Plugin.Engine.Source> resolved = new ArrayList<Plugin.Engine.Source>();
List<String> combined = new ArrayList<String>(elements);
combined.add(this.target);
for (String element : combined) {
File e = new File(element);
if (e.isDirectory()) {
resolved.add(new Plugin.Engine.Source.ForFolder(e));
} else if (e.exists()) {
resolved.add(new Plugin.Engine.Source.ForJarFile(e));
} else {
throw new MojoFailureException("Source location does not exist: " + e);
}
}
Plugin.Engine.Source compound = new Plugin.Engine.Source.Compound(resolved);
however I still have issues with missing classes from my compile classpath (located in a 3rd jar, not the one I pass in the configuration/that I try to transform). Since the transform
goal works fine, I tried adding project.getCompileClasspathElements
to the compound source as well but without any luck. Do you have any advise?
I also noticed, that you changed a line in ByteBuddyMojo.transform
to .apply(source, target, factories);
so I tried changing it back to .apply(source, new Plugin.Engine.Target.ForFolder(file), factories);
(since you passed root
before the change which became file
) but could not see any difference.
Also the mvnw
fails due to checksums, but since the README advises to use mvn
to build, I guess that's fine.
from byte-buddy.
Thanks for the first hint, I have fixed that on master.
As for the exception: You have to specify any dependencies as: <dependencies><dependency>...</dependency></dependencies>
in the configuration block of the plugin. As you point to a location or jar file, the plugin does not know about any possible Maven coordinates that need to be included, so you would need to specify those manually. I just gave this a test myself and this seems to work.
from byte-buddy.
Maybe I misunderstood. I figured the list of dependencies for the goal was a way to specify the libraries that should be additionally transformed, while I hoped other project dependencies would still be available on the classpath. I think I can work around it though, I will test it tomorrow.
from byte-buddy.
I can add a flag to include the class path. You are right that it will make sense in many scenarios. As it is right now, you can transform any jar or folder, even outside the project, so it is a bit more generic. Also, a library will likely have less classes available than the project itself, so the scope can be reduced. But I will add a convenience option.
from byte-buddy.
Can you try with the latest version? transform-location will now include the class path. transform-location-empty is now the previous behavior.
from byte-buddy.
I tried transform-location and transform-location-extended but I probably still do something wrong.
<configuration>
<transformations>
<transformation>
<groupId>mygroup</groupId>
<artifactId>myplugin</artifactId>
<version>1.0.0</version>
<plugin>my.Plugin</plugin>
</transformation>
</transformations>
<source>${project.build.outputDirectory}</source>
<target>${project.build.outputDirectory}</target>
<dependencies>
<dependency>
<groupId>3rd.party</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</configuration>
If I set source
to ${project.build.outputDirectory}
my own classes are being transformed, but not the 3rd party library.
If I use the maven-dependency-plugin to download the 3rd party jar inbefore and set source
to ${project.build.directory}/dependency
it transforms neither the java classes nor the library (since that folder does not contain class files but jar files which are not detected).
I have to specifiy the full jar name to transform the 3rd party library, which will only ever work for one jar file (and likely skips the purpose of configuring the dependency separately).
<source>${project.build.directory}/dependency/library-1.0.0.jar</source>
Maybe it's not necessary to add 5 new mojos but instead just extend the existing mojos with List<CoordinateConfiguration> dependencies
to specify additional libraries to be processed (additionally to the local classes, that the other mojos already process and without configuring a source
)?
from byte-buddy.
I am not sure what you are trying to accomplish, but I would copy your compiled classes and the dependencies to a custom location using: https://maven.apache.org/components/plugins/maven-dependency-plugin/examples/unpacking-project-dependencies.html
Then you can apply the Byte Buddy plugin on this exploded folder and pack the modified app in one app.
The reason I need to add that many Mojos is that Maven requires annotations to resolve a given dependency scope.
from byte-buddy.
I added another target for this exact use case. Given the Maven API, I think this is the best approach. If you have a folder with all dependencies, using transform-dependencies should now do what you expect if that folder contains all relevant jar files.
Could you try this out?
from byte-buddy.
I was able to achieve what I wanted by using two goals at once now:
- transform for my local project classes where my transformation also needs project dependency from the classpath and
- transform-location/transform-location-empty to transform another 3rd party library after copying and unpacking it with the maven-assembly-plugin (since maven-dependency-plugin does not support transitive dependencies on copy/unpack).
I also tested out transform-dependencies to transform a folder of jar files, however with the maven-assembly-plugin it's easier to just unpack the dependencies immediately. This way I also skipped the need to specify the dependency in the plugin configuration so I can't say if that works as expected.
Overall, achieves what I'd like to use the plugin for :) I can also run my tests with gradle, if you plan on bringing this feature to the byte-buddy-gradle-plugin.
from byte-buddy.
Related Issues (20)
- latest guava cause [ unexpected type reference on method: 16 ] HOT 5
- `MemberSubstitution` can't replace instructions within synthetic methods. HOT 2
- IllegalArgumentException for Kotlin bytecode with erased type argument HOT 9
- Can byte-buddy modify bytecode in parallel? HOT 4
- Java 17 reflection changes
- A lazy `TypePool` will change with type resolution and thus deviate from its initial configuration. HOT 2
- JDK 23 Valhalla-EA: IllegalState Illegal modifiers 33 for class HOT 2
- Multiple transformation issue with JMH benchmarks HOT 1
- [question] How can replace field access with another class? HOT 2
- Eclipse project compilation error using mockito and byte-buddy HOT 5
- Runtime attachment causing VerifyError during class transformation HOT 13
- not able to intercept java.lang package HOT 9
- Questions about alternatives to the LocalVariablesSorter class obsoletization HOT 4
- How to create a class with updated private field using ByteBuddy? HOT 2
- Byte buddy access to package protected class HOT 4
- mockito-android:5.12.0 cannot mock class HOT 1
- How to invoke the method of injecting objects into a class? HOT 2
- [Question] Why would a new field var2 be added after replace field access with method? HOT 3
- How to redefine dynamically created classes? HOT 2
- EntryPoint property breaks gradle build HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from byte-buddy.