I have several methods in a class that require a boolean to be set to true in order to execute correctly.
I could write the if statement in each method, but it is not convenient if I or someone else wants to ad another method. I or he could forget about the check.
Is there a way in java to execute a method before each other methods (exactly like JUnit does with #BeforeEach ) in a class ?
Edit: Lots of very interesting techniques/answers/concepts proposed. I'll be in touch when I've understood them. Thanks.
Lets make a method turnBooleanTrue() where effectively the boolean is set to true in order for the method to be execute correctly.
Then, you can write up your very own InvocationHandler that would intercept calls to your objects, and then reflectively (using reflection API) invoke first the turnBooleanTrue() method followed by the method to which the call was made.
Will look something like this
public class MyClassInvocationHandler implements InvocationHandler {
// initiate an instance of the class
MyClass myClass = new MyClassImpl();
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// look up turnBooleanTrue() method
Method turnBooleanTrue = myClass.getClass().getMethod("turnBooleanTrue");
// invoke the method
turnBooleanTrue.invoke(...); // toggle the boolean
// invoke the method to which the call was made
// pass in instance of class
Object returnObj = method.invoke(myClass, args);
return returnObj;
}
EDIT
Added some lines to have an object of MyClass initialized. You need something to invoke the method on and maintain the state. Changed util to myClass in the code example above.
Considering my use case, it was a bit overkill to use AOP or other concepts. So I basically did a check in each functions.
With AOP, this is how what you need would look:
// wraps around all methods in your class that have a boolean parameter
#Around(value = "#target(*..YourClass) && args(yourBool)", argNames = "jp,yourBool")
Object scheduleRequest(ProceedingJoinPoint jp, boolean yourBool) {
if (yourBool) {
jp.proceed(yourBool);
} else {
throw new RuntimeException("cannot execute this method!");
}
}
This would handle the case that the method take the boolean you say needs evaluation as its (only) parameter. If it comes from a different source, you may need to wire it into the aspect somehow, that depends on your overall design.
I suggest a simple solution by dividing your workflow in four components.
You have an interface you use to execute commands.
You have an interface that defines which commands you can use.
You have one wrapper that analyzes your boolean value.
You have an implementation of the work performing class, that implements the second interface.
Your wrapper initialize the worker.
Your wrapper exposes an action performing command that accepts the executing interface.
if the boolean is true, pass the worker to the executing interface work method.
the executing interfaces work method calls the work function on the command instance interface, the worker.
See it online: https://ideone.com/H6lQO8
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
WorkDistributer wd = new WorkDistributer();
wd.enable();
wd.performAction((w) -> {w.printHello();});
wd.disable();
wd.performAction((w) -> {w.printHello();});
wd.enable();
wd.performAction((w) -> {w.printAnswer();});
wd.disable();
wd.performAction((w) -> {w.printAnswer();});
}
}
class WorkDistributer
{
private boolean enabled = false;
private ActionPerformer worker;
public WorkDistributer() {
this.worker = new Worker();
}
public void enable() {
enabled = true;
}
public void disable() {
enabled = false;
}
public void performAction(ActionCommand command) {
if(this.enabled) {
command.run(this.worker);
}
}
}
class Worker implements ActionPerformer {
public void printHello() {
System.out.println("hello");
}
public void printAnswer() {
System.out.println(21 * 2);
}
}
interface ActionPerformer {
public void printHello();
public void printAnswer();
}
interface ActionCommand {
public void run(ActionPerformer worker);
}
Suppose I have class with simple dependency:
public interface Dependency {
int doSomething(int value);
void doMore(int value);
int doALotMore(int value);
}
public final class A implements SomeInterface {
private final Dependency dep;
public A (Dependency dep) {
this.dep = dep;
}
#Override
public int add(final int x) {
dep.doMore(x);
return x + dep.doSomething(x) + dep.doALotMore(x);
}
}
And I'm writing test using mocks:
public class TestA {
private Dependency mockDep;
private SomeInterface a;
#Before
public void setUp() {
mockDep = Mockito.mock(Dependency.class);
a = new A(mockDep);
}
#Test
public void shouldAdd() {
final int x = 5;
when(mockDep.doSomething(x)).thenReturn(6);
when(mockDep.doALotMore(x)).thenReturn(7);
int actual = a.add(x);
assertThat(actual, is(18));
verify(mockDep, times(1)).doSomething();
verify(mockDep, times(1)).doALotMore();
verify(mockDep, times(1)).doMore();
verifyNoMoreInteractions(mockDep);
}
}
So far so good.
So the question is: do we violate encapsulation of class A by verifying how exactly the dependency was used? Does it really needed to test that dependency was used in exactly that way? Shouldn't we test A like a black-box (delete verify invocations from test case and leave just assertThat)? And how to deal with dependencies in such case?
The reason I'm asking is that I caught myself writing good amount of verification dependency code and it seems that we start to test actual internal realization details about class. And I feel uncomfortable about that because when I will try to rewrite this realization details in another way I need to rewrite test cases although the result of add for example will be the same. If I would test my class as a black-box I can change realization details and still be sure that given input will give same output.
Or it is necessary to actually test exactly the realization details and that is the point of unit-test itself? It seems somewhat wrong for me.
Consider this test instead:
public class TestA {
private Dependency mockDep;
private SomeInterface a;
private final int x = 5;
#Before
public void setUp() {
mockDep = Mockito.mock(Dependency.class);
a = new A(mockDep);
when(mockDep.doSomething(x)).thenReturn(6);
when(mockDep.doALotMore(x)).thenReturn(7);
}
#Test
public void shouldAdd() {
int actual = a.add(x);
assertThat(actual, is(18));
}
}
It really depends on logic which you're testing. Since your example don't provide any context, I'll give you a case when I feel not only comfortable to test such interaction, but even mandatory:
Let's say you're testing authentication token validation. You pas some token to your validator and it returns true/false. Inside of your validator you're calling some jwt.validate or any other 3rd party hash validation method. In this case I need to know that this validator will be called every time, because I can introduce some if token == null condition inside which will bypass this validation call and just return false. Then your tests could still pass but your code is now vulnerable to timing attack.
It's one kind of example. The other type of test I'm comfortable of testing that way is so called border testing. I want to know that my class triggers stripe payment gateway - so I mock it and just make sure it gets called without checking anything sophisticated in this particular test.
I have some code like below.
#RetryOnFailure(attempts = Constant.RETRY_ATTEMPTS, delay = Constant.RETRY_DELAY, unit = TimeUnit.SECONDS)
public void method() {
// some processing
//throw exception if HTTP operation is not successful. (use of retry)
}
The value of RETRY_ATTEMPTS and RETRY_DELAY variable come from a separate Constant class, which are int primitive. Both the variable are defined as public static final.
How can I override these values while writing the unit testcases. The actual values increases running time of unit testcases.
I have already tried two approach: Both did not work
Using PowerMock with Whitebox.setInternalState().
Using Reflection as well.
Edit:
As mentioned by #yegor256, that it is not possible, I would like to know, why it is not possible? When these annotations get loaded?
There is no way to change them in runtime. What you should do, in order to make your method() testable is to create a separate "decorator" class:
interface Foo {
void method();
}
class FooWithRetry implements Foo {
private final Foo origin;
#Override
#RetryOnFailure(attempts = Constant.RETRY_ATTEMPTS)
public void method() {
this.origin.method();
}
}
Then, for test purposes, use another implementation of Foo:
class FooWithUnlimitedRetry implements Foo {
private final Foo origin;
#Override
#RetryOnFailure(attempts = 10000)
public void method() {
this.origin.method();
}
}
That's the best you can do. Unfortunately.
So I have small interface
public interface IPlayersStorage
{
// other methods...
public boolean addException(final String nick);
// other methods...
}
and class "PlayersStorage" that implements it: (only used part)
public class PlayersStorage implements IPlayersStorage
{
private static final PlayersStorage inst = new PlayersStorage();
private final Set<String> exceptions = new HashSet<>(50);
#Override
public boolean addException(final String nick)
{
return ! this.exceptions.add(nick);
}
public static PlayersStorage getStorage()
{
return inst;
}
}
And in some place I use that method using that code:
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.getStorage().addException(player);
}
And ProGuard change it to:
for (Iterator localIterator1 = this.cfg.getStringList("Exceptions").iterator(); localIterator1.hasNext();)
{
localIterator1.next();
PlayersStorage.getStorage(); // it's get object, but don't do anything with it...
}
The only possible fix that I found, is add static method to PlayersStorage
public static boolean staticAddException(final String nick)
{
return inst.addException(nick);
}
And then use it (instead of old code)
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.staticAddException(player);
}
Then works... (ProGuard keep method call) but adding static methods for every method from interface isn't good idea.
ProGuard only removes method invocations if they don't have any effect (doesn't seem to be the case here), or if you have specified -assumenosideffects for the methods. You should check your configuration and remove any such option.
Alternatively, your decompiler may be having problems decompiling the code. You should then check the actual bytecode with javap -c.
I would like some help on this matter,
Example:
public class A {
private void foo() {
//Who invoked me?
}
}
public class B extends A {}
public class C extends A {}
public class D {
C.foo();
}
This is basically the scenario. My question is how can method foo() know who is calling it?
EDIT: Basically I am trying to do a database Layer, and in class A I will create a method that will generate SQL statements. Such statements are dynamically generated by getting the values of all the public properties of the calling class.
Easiest way is the following:
String className = new Exception().getStackTrace()[1].getClassName();
But in real there should be no need for this, unless for some logging purposes, because this is a fairly expensive task. What is it, the problem for which you think that this is the solution? We may come up with -much- better suggestions.
Edit: you commented as follows:
basically i'am trying to do a database Layer, and in Class A i will create a method that will generate sql statements, such statements are dynamically generated by getting the values of all the public properties of the calling class.
I then highly recommend to look for an existing ORM library, such as Hibernate, iBatis or any JPA implementation to your taste.
Java 9: Stack Walking API
JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. First off, you should obtain an instance of StackWalker:
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
// other imports
StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
After that you can call the getCallerClass() method:
Class<?> callerClass = walker.getCallerClass();
Regardless of how you configured the StackWalker instance, the getCallerClass method will ignore the reflection frames, hidden frames and those are related to MethodHandles. Also, this method shouldn't be called on the first stack frame.
Perhaps for your use case it would make sense to pass the class of the caller into the method, like:
public class A { public void foo(Class<?> c) { ... } }
And call it something like this:
public class B { new A().foo(getClass() /* or: B.class */ ); }
foo() is private, so the caller will always be in class A.
if you using slf4j as your application logging system.
you can using:
Class<?> source = org.slf4j.helpers.Util.getCallingClass();
I think it's faster than new Exception().getStackTrace(), since getStackTrace() alaways doing clone stacktrace.
I would use StackWalker
private static Class<?> getCallingClass(int skip) {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Optional<? extends Class<?>> caller = walker.walk(frames ->
frames.skip(skip).findFirst().map(StackWalker.StackFrame::getDeclaringClass)
);
return caller.get();
}
If you need the class of the calling method use skip=1.
From a stack trace: http://www.javaworld.com/javaworld/javatips/jw-javatip124.html
A hacky solution is sun.reflect.Reflection.getCallerClass.
public void foo() {
Class<?> caller = sun.reflect.Reflection.getCallerClass();
// ...
}
It is hacky because you have to ensure that the class that calls Reflection.getCallerClass() is loaded on the bootstrap ClassLoader for the annotation #CallerSensitive (which getCallerClass is tagged with) to work. As such, it probably isn't the best solution for a project unless your project happens to use a Java Agent to add your classes to the bootstrap ClassLoader search.
With the following code, you obtain the first class which generated the stack of calls:
public String getInvonkingClassName(boolean fullClassNameNeeded){
StackTraceElement[] stack = new Exception().getStackTrace();
String className = stack[stack.length-1].getClassName();
if(!fullClassNameNeeded){
int idx = className.lastIndexOf('.');
className = className.substring(idx+1);
}
return className;
}
Boolean argument is used to get the full name including package name, or just class name.
StackFrame
The state of one method invocation on a thread's call stack. As a thread executes, stack frames are pushed and popped from its call stack as methods are invoked and then return. A StackFrame mirrors one such frame from a target VM at some point in its thread's execution.
JVM Stack: From Frame 1 get Frame 2 details
| |
| |
| Class2.function1() [FRAME 1] |
| executing the instructions |
|-------------------------------------------|
|Class1.method1() [FRAME 2] |
| called for execution Class2.function1() |
|-------------------------------------------|
Throwable::getStackTrace and Thread::getStackTrace return an array of StackTraceElement objects, which contain the class name and method name of each stack-trace element.
Throwable::getStackTrace contains the Stack with frames as Frame1(Top Frame) Current method, Frame2 calls Frame1 method for execution.
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace();
// Frame1:Log4J.log(), Frame2:CallerClass
Thread::getStackTrace contains the stack with Frames:
Frame1:Thread.getStackTrace(), Frame2:Current Method, Frame3:Caller Method
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); //
sun.misc.SharedSecrets.getJavaLangAccess()
sun.misc.JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
StackTraceElement frame = javaLangAccess.getStackTraceElement((new Throwable()), callerFrame-1 ); // Frame0:Log4J.log(), Frame1:CallerClass
System.out.format("SUN - Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
Throwable throwable = new Throwable();
int depth = javaLangAccess.getStackTraceDepth(new Throwable());
System.out.println("\tsun.misc.SharedSecrets : "+javaLangAccess.getClass() + " - StackTraceDepth : "+ depth);
for (int i = 0; i < depth; i++) {
StackTraceElement frame = javaLangAccess.getStackTraceElement(throwable, i);
System.out.format("Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
}
JDK-internal sun.reflect.Reflection::getCallerClass method. It is deprecated, removed in Java9 JDK-8021946
Any way by using Reflection API we can't find the Line Number of Function which it get called.
System.out.println("Reflection - Called from Clazz : "+ Reflection.getCallerClass( callerFrame )); // Frame1:Log4J.log(), Frame2:CallerClass
Example:
static boolean log = false;
public static void log(String msg) {
int callerFrame = 2; // Frames [Log4J.log(), CallerClass.methodCall()]
StackTraceElement callerFrameStack = null;
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace(); // Frame1:Log4J.log(), Frame2:CallerClass
//StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();// Frame1:Thread.getStackTrace(), Frame2:Log4J.log(), Frame3:CallerClass
int callerMethodFrameDepth = callerFrame; // Caller Class Frame = Throwable:2(callerFrame), Thread.currentThread:2(callerFrame+1)
for (int i = 0; i < stackTraceElements.length; i++) {
StackTraceElement threadFrame = stackTraceElements[i];
if (i+1 == callerMethodFrameDepth) {
callerFrameStack = threadFrame;
System.out.format("Called form Clazz:%s, Method:%s, Line:%d\n", threadFrame.getClassName(), threadFrame.getMethodName(), threadFrame.getLineNumber());
}
}
System.out.println(msg);
if (!log){
Logger logger = Logger.getLogger(callerFrameStack.getClass());
logger.info(msg);
}
}
public static void main(String[] args) {
Log4J.log("Log4J, main");
Clazz1.mc1();
Clazz21.mc12();
Clazz21.mc11();
Clazz21.mc21();
}
}
class Clazz1 {
public static void mc1() {
Log4J.log("Clazz1 - mc1");
}
}
class Clazz11 {
public static void mc11() {
Log4J.log("Clazz11 - mc11");
}
public static void mc12() {
Log4J.log("Clazz11 - mc12");
Clazz1.mc1();
}
}
class Clazz21 extends Clazz11 {
public static void mc21() {
Log4J.log("Clazz21 - mc21");
}
}
For Java 9 use Stack Walking API
I'm just answering this because for some reason the above answers started referring to exception handling - the original question had nothing to do with exceptions.
So, instead of trying to determine the caller of the method in question, and specifically to give more information dealing with the creation of a base class that generates SQL statements for its derived classes, here is an OO solution...
Make the base class abstract and include abstract methods that return the data it needs to build a sql statement.
This would include methods like...
getColumnList()
getFromTable()
getJoinedTables()
getFilterColumns()
The base class then does not care who is calling it because it is going to call up to the derived class for all the details it needs to create the SQL statement.
The base class knows the derived classes are going to provide the implementation of these methods because they are abstract.
Another way to implement this would be to have a SQLGenerator class that receives an interface with the methods described above and operates on the instances passed to it via those methods. For this, you would want to have the abstract methods described above moved into the interface, which all of your SQL related classes would implement.
List item
I tried this and it works well. It is because each Java Object has access to getClass() method which returns the class caller and the method name.
public Logger logger() {
return Logger.getLogger(getClass().toString());
}
example usage:
public DBTable(String tableName) {
this.tableName = tableName;
loadTableField();
this.logger().info("done");
}
sample output log using java.util.logging.Logger
Feb 01, 2017 11:14:50 PM rmg.data.model.DBTable (init) INFO: done
Maybe an answer is
public class CallerMain {
public void foo(){
System.out.println("CallerMain - foo");
System.out.println(this.getClass()); //output- callerMain
}
public static void main(String[] args) {
A a = new A();
CallerMain cm = new CallerMain();
cm.foo();
}
}
class A{
public void foo(){
System.out.println("A - foo");
System.out.println(this.getClass());//output- A
}
}