Get parameter values of the calling method [duplicate] - java

This question already has answers here:
How to get arguments passed to method that called this method?
(6 answers)
Closed 3 years ago.
How to get parameter values of the calling method?
I have scenario where there are two classes viz., Class A and Class B containing two methods mthA(in Class A) and mthB(in Class B). mthA calls mthB. now I want to know in mthB that what all parameters have been passed to mthA. This is basically for logging and handling exceptions. I am able to get the class name of the calling class i.e Class A and the method name which is calling mthB i.e mthA. but I am stuck at getting the parameters of mthA.
Thread.currentThread().getStackTrace()[1].getClassName()
this gives me the class name of the calling method i.e Class A.
Thread.currentThread().getStackTrace()[2].getMethodName()
This gives me the method name of the calling method i.e mthA.
If somehow I can get the whole method itself then I can get the method parameters passed to this method by using getParameters().

There's no easy way to get calling method's arguments values, (if you can not change the parameters of called method to include and pass calling parameters values).
Using some APIs like what Thread provides, we can get the static info like class/method name, but not runtime info like arguments values. One way could be to store and manage that kind of info somewhere and show when required in case of logging/exception. I dont think there's an API for that in java.

There is simplest way or is it necessary to use Reflection..?
If you want to know what parameter is passed for mthA then pass same parameter to mthB also Ex:
mthA(1stParam, 2ndParam, ...){
mthB(1stParam, 2ndParam, ..., OtherParamertsForMthB);
...
}

If it is just for logging purpose only, then you should log in mthA itself all the arguments passed into the method.
Why should mthB know about mthA's argument values to handle exceptions? If you are doing that, then you should consider refactoring the code and handle exceptions at the appropriate levels. If values passed to mthA is leading to an exception, then it should be handled there itself before calling mthB.
Reflection only helps in getting static information of the class and methods and does not provide runtime values of the arguments passed into a method.

Why don't you use some AOP tool like AspectJ to capture these values and log? You can use execution() point cut along with after() advice. For non production deployment you can log all the method calls along with passed values and returned value. This will be too much overhead for production env. For that you can just store the passed values (Object args[] as you get in AspectJ advice) in local variable and only log it in case of exception. But even in that case there will be some performance penalty as primitive values will be boxed to be passed as Object[] to your advice.

Related

Prohibiting passing certain values for method parameters

I have a method like this:
void method(int number){some code}
and i will call it like this:
method(-1)
is there a way in java to only allow passing positive integers to number parameter other than checking in the method body or making a checked exception?
Declaring a checked exception doesn't make method parameters automatically validated somehow, it just means that the caller is obligated to check whether it was thrown, even if the code calls a literal method(1).
If your application is complex enough, you can use Bean Validation and put a constraint on the method parameter:
void method(#Min(1) int number) { }
This is only worthwhile if you're already using a system complex enough to provide support for it, such as Spring or CDI. Otherwise, just stick to checking in the method body and throwing IllegalArgumentException if the requirements fail. Guava's Preconditions utility can be helpful here.
(Additionally, your code will be much easier to read if you follow the universal Java code standards. Type names start with capitals, but member and parameters names start with lowercase.)

How to convert the string to methods (like .Sendkeys) in Java?

Need to convert variable contains String to a method call.
Example:
Variable:
//Enter the name and value of the locator
public String[] LoginID_Button = {"name","Log in"};
In my another class:
driver.findElement(By.name(loc1.LoginID_Button[1])).isDisplayed();
But I need to write as:
driver.findElement(By.loc1.LoginID_Button[0](loc1.LoginID_Button[1])).isDisplayed();
The name is the variable string but should be changed as Method. How to do this?
This is called Reflection. Which, is the ability to change structure/behavior in runtime.
This is a nice question about it.
For your problem, you can do the same as in that question's accepted answer.
driver.findElement(By.class.getMethod(loc1.LoginID_Button[0],String.class).invoke(null,loc1.LoginID_Button[1])).isDisplayed();
In the above code, the method getMethod() is used to dynamically find a method by its name which in this case LoginId_Butt[0]. It is required also to specify the type of the parameters that target method is accepting, in our case, it is String.
The found method is then invoked using the invoke() method. The invoke() method takes two arguments, the first one is the instance that the dynamic method is executed against. In our case, the instance is null because the dynamic method is static.
The second argument is a params of the arguments passed to the dynamic method. In this case, we have only one parameter to pass, that is LoginId_Butt[1].
Notes
Please don't forget to wrap this code with ty/catch against many exceptions can be thrown.
Please use the java naming convention for variable names i.e. loginID_Button

Single method class - pass dependcies to constructor or method

I have a very simple class that has a single method.
The method needs two objects passed to it to prepare an output and return the output.
Should the class be instantiated with these two objects passed to the constructor, or should those be passed to method when being called?
Currently I can see that the method will always be called only once per request and always with the same objects passed to it.
There are a lot of factors involved, but in general, the constructor should take arguments for configuration (if any configuration is needed), and the actual input should be passed to a method. Methods should be the "verbs" or "actions" in an object-oriented design, while classes should be the "nouns" or "machines."
Simply buying or building a toaster doesn't result in toast. Someone creates the toaster (think of that as constructing an object), then they or someone else executes an operation with it to make toast (think of that as calling a method).
So, in the absence of more information, I would recommend passing the objects to the method, not the constructor. Even if it's the same objects being passed every time.

Find calling Method in Java

Short version:
I need to find a way in Java to locate the previous Method in the call stack (note the capital 'M' in Method--I need the actual java.lang.reflect.Method object).
Background:
I'm working on an extension to the Google Guava Preconditions.checkNotNull(...) concept that will allow the programmer to simultaneously check ALL of the parameters for null, and construct an NPE based on the parameter names of the calling method. For example:
public class MyClass
{
public void myMethod(Object arg1, Integer arg2, String arg3)
{
MyPreconditions.checkAllNotNull(arg1, arg2, arg3);
}
}
So if the first argument was null, then the NPE might read arg1 cannot be null (MyClass:myMethod(Object, Integer, String)
I've already worked out how to get the calling Class and I can get the parameter names via the Spring LocalVariableTableParameterNameDiscoverer (or via the Paranamer library) one I have the Method. The only part that I can't figure out is how to get Method itself.
I'm aware that you can use the stack trace to get the method name, but that doesn't help if the method is overridden. Is there a way (even with internal com.sun classes) to get the actual stack? Alternatively, I can get the line number for the calling method, so is there a way to find the line number of a Method as retrieved from the Class object?
Thread.getStackTrace() gives you the current stacktrace. From there you can get the class name and method name (even if the method is overridden, you will see the exact class there), and get the method through reflection.
But imo - this is strange and not needed. And thing about it - you are providing a message that is mostly already present in the stacktrace that will be generated if the Preconditions call fails.
"I'm aware that you can use the stack trace to get the method name, but that doesn't help if the method is overridden." -- The stack trace contains the class name (and source file) as well, though, in a manner that is correct even if the method has been overridden.
I don't think there is any (good, consistent) way to get the actual Method object. Particularly not one that works with an active security manager. The Java security code itself uses some tricks to do that, but replicating that would not be portable between various VMs.

How can a Java method retrieve the method object pertaining to that particular method? (Java)

I am writing a Java method with the following signature.
void Logger(Method method, Object[] args);
If a method (e.g. ABC() ) calls this method Logger, it should retrieve the Method object that encapsulates data about itself (ABC()) and pass it as an argument.
How can a method retrieve the Method object that is storing all the information about that method?
A simple way is that I use
Method[] methods = ExampleClass.Class.getMethods();
and search the whole array for the Method with the correct name. (Which is quite inefficient). Also, if two or more methods have the same names, then I will have to retrieve their parameter types too (to distinguish them) and have different code for each method. This would be inefficient as well as painful.
Is there a better way?
Thanks for the help.
Don't do it. Rather obtain the method name from the stack.
public void log(Object object) {
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
// ...
}
This is however pretty expensive and that's why most self-respected logging frameworks offer an option to turn it on/off (which I would recommend to use instead of homegrowing one).
Even better, don't implement this method at all. Use logback, or some other modern logging framework.
If you are writing a wrapper over existing logger frameworks then the already provide a way to print the method name in the log message - if that's what you are trying to implement.
You can read from the log4j documentation, for example, that this extraction (as the other answer suggests) is done from the stack trace and is expensive : http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

Categories

Resources