Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Q] How to remove/replace existing annotation #354

Closed
michelkaeser opened this issue Oct 5, 2017 · 8 comments
Closed

[Q] How to remove/replace existing annotation #354

michelkaeser opened this issue Oct 5, 2017 · 8 comments
Assignees
Milestone

Comments

@michelkaeser
Copy link

Is there a way to replace (or remove so it can be re-added) an existing annotation from a type?

Let's say the input is:

@PersistenceCapable
class X {}

and I want

@PersistenceCapable(value="", key="")
class X {}

How would I do that?

A simple annotateType makes the annotation appear twice.

Thanks!

@raphw raphw self-assigned this Oct 6, 2017
@raphw raphw added the question label Oct 6, 2017
@raphw raphw added this to the 1.7.5 milestone Oct 6, 2017
@raphw
Copy link
Owner

raphw commented Oct 6, 2017

It is possible but a bit tricky, there is not yet a good API for such transformations. The problem is that Byte Buddy cannot generally know if a value is represented as a default value or if it is explicitly defined but to this default value. It sounds irrellevant but as a matter of fact, it does matter for (too manny) applications.

I hopefully can add better support for this in the future. For now, using ASM is the easiest way of getting this done.

@raphw raphw added enhancement and removed question labels Apr 3, 2018
@thekingn0thing
Copy link

@raphw did you find a time to add API for removing annotation?

@raphw
Copy link
Owner

raphw commented May 1, 2018

Not yet, unfortunately. I use this issue to track the progress. With modules and the sun.misc.Unsafe cleanup, I did not had much time for features recently.

@albanf
Copy link

albanf commented Feb 4, 2019

Hi, I am new to byte buddy, and I am trying to modify the value of an annotation in an agent.
When you say

For now, using ASM is the easiest way of getting this done.

do you mean that it's possible to do this when transforming a class in an agent? I couldn't find any example of a transformer for that case.

What I am trying to do is to transform:

@MessageDriven(
        activationConfig = {
                @ActivationConfigProperty(
                        propertyName = "resourceAdapter",
                        propertyValue = "jmsra")
        }
)
public class MyClass {
}

and change the value of propertyValue

@MessageDriven(
        activationConfig = {
                @ActivationConfigProperty(
                        propertyName = "resourceAdapter",
                        propertyValue = "activemq-rar")
        }
)
public class MyClass {
}

The agent is correctly setup and processes the class:

new AgentBuilder.Default()
                .type(ElementMatchers.<TypeDescription>isAnnotatedWith(MessageDriven.class))
                .transform(new ChangeResourceAdapterTransformer())
                .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
                .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
                .installOn(inst);

But I don't know what to do in the transformer, since annotateType is creating a duplicate like mentioned before:

public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {

        return builder
                .annotateType(AnnotationDescription.Builder.ofType(MessageDriven.class)
                        .defineAnnotationArray("activationConfig", new TypeDescription.ForLoadedType(ActivationConfigProperty.class),
                                AnnotationDescription.Builder.ofType(ActivationConfigProperty.class)
                                        .define("propertyName", "resourceAdapter")
                                        .define("propertyValue", "activemq-rar")
                                        .build())
                        .build());
    }

Thanks for your help!

@raphw
Copy link
Owner

raphw commented Feb 4, 2019

As mentioned, it is not currently possible to remove the existing annotation. This is not currently solved fully satisfactory in Byte Buddy such that you have to reapply all annotations what means filtering out the first annotation using an AsmClassVisitorWrapper where the second one is picked up correctly.

@albanf
Copy link

albanf commented Feb 5, 2019

Do you have an example of a visitor which would remove that annotation (or all annotations?). At least for some use case, where you can rebuild the whole annotation or set of annotations, that would work.

@raphw
Copy link
Owner

raphw commented Feb 6, 2019

Basically, you need to implement a MethodVisitor that returns null on any annotation you want to remove. You can register such a visitor using a custom instance of AsmVisitorWrapper.

@raphw
Copy link
Owner

raphw commented Jul 14, 2021

Closing this in favor of #917

@raphw raphw closed this as completed Jul 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants