10

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.

6
  • Probably an overkill: You could create an abstract class or interface, with a default method, which checks for the boolean, and extend the method in your class. Commented Feb 11, 2020 at 12:48
  • 3
    Look into Aspect Oriented Programming (specifically before advice) - stackoverflow.com/questions/31121513/… Commented Feb 11, 2020 at 12:54
  • @NikitaLebed If you actually want to prevent the method executing on a condition as it sounds like OP wants, you'd need an Around advice. Commented Feb 11, 2020 at 12:59
  • Similar questions don't always have the same best answer. What is this Boolean for? Commented Feb 11, 2020 at 13:29
  • @MattTimmermans This boolean is a flag indicating if the soft has received and handled correctly an HTTP request. Commented Feb 11, 2020 at 13:33

4 Answers 4

6

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.

Sign up to request clarification or add additional context in comments.

4 Comments

InvokationHandler is one possibility. Another would be AspectJ.
What is util in method.invoke ?
I overrode invoke in my use case (changed a bit of code to match my needs). It is not called before other methods and I do not understand how it is supposed to be.
@FlorianCastelain can you share how you are calling the code and on which instance ? You now need to call the method on the proxy instance
1

Considering my use case, it was a bit overkill to use AOP or other concepts. So I basically did a check in each functions.

Comments

0

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.

Comments

0

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);
}

2 Comments

For this kind of decorator, I'd say it's enough to use Runnable for the command, and a single wrapper that evaluates the boolean, created by a factory method (static Runnable wrap(Runnable wrapped, Supplier<Boolean> allowed)) { return () -> { if (allowed.get()) wrapped.run(); })
@daniu One could do that, but that's not my preferred way to do it. For me your proposed method loses a lot of "intention" and self documenting properties of the layout of the code flow. But to each their own preferred method. It's heaps better than relying on reflection. Using a native method to steer the code flow forces when changes are made in the future to proper actions. "Magic" reflection methods may be forgotten, resulting in long behavior hunts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.