Reputation: 21
I am trying to add query params to request url using bytebuddy here is my code:
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(hasSuperType(named("org.springframework.web.client.RestTemplate")))
.transform(new Transformer.ForAdvice().include(MyByteBuddy.class.getClassLoader())
.advice(ElementMatchers.named("execute"), "agent.RestTemplateAdvice"))
.installOn(instrumentation);
and advice is
@Advice.OnMethodEnter
public static void before(@Advice.AllArguments Object[] args) {
System.out.println("!!!!!!!!!!!");
String data = args[0].toString();
data = (data + "asdgb?param=myparam");
System.out.println(data);
args[0] = (Object)data;
System.out.println(args[0]);
}
output I am getting is
!!!!!!!!!!!
http://localhost:8086/movies/5678asdgb?param=myparam
http://localhost:8086/movies/5678
I have tried below advice too but this one is not even capturing the method call.
@Advice.OnMethodEnter
public static void before(@Advice.Argument(0) String argument) {
System.out.println("!!!!!!!!!!!");
argument = (argument + "asdgb?param=myparam");
System.out.println(argument);
}
Upvotes: 1
Views: 1072
Reputation: 44007
The problem when using @AllArguments
is that you are assigning a value as such
args[0] = (Object) data;
This does not help in terms of Byte Buddy's templating capabilities. In effect, this means that you are reading all arguments into an array, assigning data
to the first index of that array and then never use it again. Instead, you would need to:
Object[] _args = args;
_args[0] = (Object) data;
args = _args;
While this does not seem to make sense in Java code, it translates into the byte code you want where all arguments are assigned the values of the supplied array. It would however be much more efficient to do what kriegaex suggests to use index base proxies for arguments.
Upvotes: 1
Reputation: 67297
Like you said, in order to change the argument you need readOnly = false
. But like I said, your advice does not cover all three execute()
methods. You would get class cast exceptions for the one taking an URI
as a first parameter. Here is how to fix it:
Helper classes to make your sample code compile:
public class MyByteBuddy {}
import org.springframework.web.client.RestTemplate;
public class MyRestTemplate extends RestTemplate {}
ByteBuddy advice:
import net.bytebuddy.asm.Advice;
import java.net.URI;
import java.net.URISyntaxException;
import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;
public class RestTemplateAdvice {
@Advice.OnMethodEnter()
public static void before(
@Advice.Argument(value = 0, typing = DYNAMIC, readOnly = false) Object url
)
throws URISyntaxException
{
String newURL = url.toString() + "search?q=scrum";
url = url instanceof URI ? new URI(newURL) : newURL;
System.out.println(url);
}
}
Driver application:
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import org.springframework.web.client.HttpClientErrorException;
import java.lang.instrument.Instrumentation;
import java.net.URI;
import java.net.URISyntaxException;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.springframework.http.HttpMethod.GET;
class BBChangeRestTemplateReturnValue_64257928 {
public static void main(String[] args) throws URISyntaxException {
applyAdvice();
performSampleRequests();
}
private static void applyAdvice() {
Instrumentation instrumentation = ByteBuddyAgent.install();
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(hasSuperType(named("org.springframework.web.client.RestTemplate")))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.include(MyByteBuddy.class.getClassLoader())
.advice(named("execute"), "RestTemplateAdvice")
)
.installOn(instrumentation);
}
private static void performSampleRequests() throws URISyntaxException {
try {
new MyRestTemplate().execute("https://www.google.com/", GET, null, null);
}
catch (HttpClientErrorException ignored) {}
try {
new MyRestTemplate().execute(new URI("https://www.google.com/"), GET, null, null);
}
catch (HttpClientErrorException ignored) {}
}
}
Console log:
https://www.google.com/search?q=scrum
https://www.google.com/search?q=scrum
Upvotes: 1