I have some code I want to run every time any method is invoked in a specific Java class, but don't want to touch the actual method bodies. This is because there are a lot of methods that change frequently, and the people programming these methods shouldn't have to worry about adding my code to every method.. even if it is just a single line that calls another method.
I can't think of a way to achieve this with inheritance, so I was wondering if it is possible with reflection? Or even at all?
It's possible to get a list of methods in a class, inspect their properties and even invoke them. But I'm not seeing anything that lets you attach extra code, such as an event handler for example. Maybe Java is the wrong language for something like this..
This is very common behavior, where Aspect Oriented Programming is definitely the right thing to use.
But I also get impressed with how the famous CMS does it.
For each class which contains the concrete method around, you can have a property (List of methods) which contains the code you want to execute before the method call.
You can write a registerBeforeCall(Method m) method which takes a method and adds to teh list.
Your method should contain a for loop at the first line(which goes through the list of methods) and invoke each of the method one by one.
Do not forget to put a try and catch and ignore the exception if there is any in the invocations.
For e.g. :
public void myActualMethod(){
for(Method m : registeredMethodsToCallBeforeActualCode){
m.invoke();
}
//my actual code
// here you can also write a for loop to execute all the methods which you want to call after your actual code is executed.
}
This approach is not very special, but is widely use, when you do not choose AOP.
one way to implement it by inheritance is:
public SuperClass {
public void doSomething() {
doBefore();
doSpecific();
doAfter();
}
protected abstract void doSpecific();
}
public SubClass extends SuperClass {
protected void doSpecific() {
System.out.println("Do specific implementation....");
}
}
public static void main(String[] args) {
SuperClass clazz = new SubClass();
clazz.doSomething();
}
Related
Minimal working example:
static void foo(boolean bar){
some code A
if(bar){
some code B
}
else{
some code C
}
some code D
}
Here we use the parameter bar to determine the method's behavior, not to actually do something with its value. As a result we redundantly check the value of bar. The method that calls foo() knows the value of bar, since it actually passed it as a parameter. A simple alternative would be:
static void foo1(){
A;B;D;
}
static void foo2(){
A;C;D
}
The result is, that we have redundant code. Now we could put A and D into methods, but what if they manipulate several variables? Java doesn't have methods with multiple return types. Even assuming we could put them into methods, we would still have foo1 looking like a();b();d(), and foo2 looking like a();c();d(). My current solution to this issue is create a functional interface for c(), b() , then to define foo as
static void foo(BCinterface baz){ A; baz.do() ;D;}
The issue is that every time I want to write a method with slightly different behaviors, I have to define an interface for the methods where they differ. I know in other languages there are function pointers. Is there any way to achieve something similar in java without having to define an interface every time? Or is there some practice to avoid having these kinds of situations come up in the first place?
In fact, I think your very first code snippet is the best and most readable solution.
bar is used to determine what the method will do, so what? Why try to move this logic to the caller of foo? There is no point. If I were trying to read the caller of foo, do I need to know how foo works (given it's well named)? No. Because I'm only interested in what happens in the caller of foo. Abstraction is a good thing, not a bad thing. So my advice is, leave it as that.
If you really want to extract the logic, you don't need a new functional interface every time. The java.util.function package and java.lang package already provides you with some functional interfaces. Just use them. For example, in your specific case, BCInterface can be replaced by Runnable.
Your way of solving duplicated invocations seems over complicated.
To provide a distinct behavior at a specific step of an processing/algorithm, you can simply use the template method pattern that relies on abstract method(s)s and polymorphism :
In software engineering, the template method pattern is a behavioral
design pattern that defines the program skeleton of an algorithm in an
operation, deferring some steps to subclasses.1 It lets one redefine
certain steps of an algorithm without changing the algorithm's
structure.[2]
Of course you will have to remove all these static modifiers that don't allow to take advantage of OOP features.
The boolean parameter is not required either any longer.
Define in a base class Foo, foo() that defines the general behavior that relies on an abstract method and let the subclass to define the abstract method implementation.
public abstract class Foo{
public abstract void specificBehavior();
public void foo(){
a();
specificBehavior();
d();
}
public void a(){
...
}
public void d(){
...
}
}
Now subclasses :
public class FooOne extends Foo {
public void specificBehavior(){
...
}
}
public class FooTwo extends Foo {
public void specificBehavior(){
...
}
}
Below I am trying to explain the problem with an example.
We have a Caller.java
Caller.java : which calls the series of Actors to perform certain steps in sequence.
Actor.java : Abstract class containing action() method
ActorOne.java : Implements the action() method
ActorTwo.java : Implements the action() method
ActorThree.java : Implements the action() method
At runtime, based on a task to accomplish, a collection of classes is prepared inside Caller.java and instantiated using the Reflection.
Actor.java: callActions(){
Class[] classes = [ActorOne.class, ActorTwo.class]
for(Class clazz : classes){
Actor actor = (Actor) clazz.newInstance();
actor.action();
}
}
In certain situation, which I know runtime inside the callActions.java, I need to inform the ActorTwo to peform the action method differently.
My solution is to pass that flag to the ActorTwo object using Reflection API and inside the action() method put if/else to perform the flag specific action.
Is there a better way to design the solution, so that I can avoid the if/else within the ActorTwo.action() method?
Best Regards
Another option is to make the action() method take an array of arguments (like main(...) does). That way ActorTwo could check the arguments to see if its in the special case, whereas the other Actors could just ignore the input.
public abstract class Actor{
public abstract void action(String[] args);
}
public class Actor2 extends Actor{
public void action(String[] args){
if(args != null && args.length > 0 && args[0].equals("SPECIAL_CASE"){
//Do special case things
} else {
//Do regular case things
}
}
}
This formation gives you the most flexibility going forward with adding extra cases to any actors.
You could have two methods on your interface. ActorOne and ActorThree would delegate the implementation of one method to the other (maybe an abstract super class would do that). ActorTwo would do something different.
You could have another interface with the different method, and have ActorTwo implement it, and at runtime check if your object supports it
if(inSpecialCase && actor instanceof Actor2) {
((Actor2)actor).specialMethod()
Eclipse works like the second suggestion a lot, to preserve extensibility and compatibility (new interfaces are created over time and the behavior adapts depending on what level the code supports).
Use polymorphism. Define one more method in your ActorTwo.java called action(flag), and then implement the new behavior in this method. When you do not want to pass flag, normal action() should be called. When you want to pass flag, on runtime, you should call action(flag).
A word of advise, try to avoid reflection if possible. It slows down the execution. If it is not possible for your code to avoid reflection, that is fine.
My Java is rusty-as-hell, and this threw me completely. I'm sure the answer is simple, but here's a simple example method that switches one Thingy off (if there's one already on) and another on:
private Thingy store;
public void switchiton(final Thingy pThingy) {
if (store != null)
store.endit();
pThingy.startit();
store = pThingy;
}
Problem: pThingy may be a subclass (e.g. CleverThingy) and not the superclass (Thingy), and CleverThingy overrides the endit method.
That code will always run the endit method in Thingy though - not the overridden one in CleverThingy (as it's declared as a Thingy and not a CleverThingy).
Obviously the method has no idea (and should not need one) about subclasses.
What am I missing that is staring at me in the face?
Update:
The subclass in this case is created "on the fly" (not sure of the correct term) rather than formally extended - e.g. in my Game class I have:
startthingy = new Thingy();
gamethingy = new Thingy() {
#Override
public void endit() {
// override things in here
super.endit();
}
}
switchiton(gamethingy); // DOES call gamethingy's overridden startit
switchiton(startthingy); // << gamethingy's overridden endit is NOT called!?
Simplest way to close this off is to answer it myself I think...
The commenters confirmed that how I thought it SHOULD work is how it actually should - this means the error is clearly elsewhere in the code...
I'm going to re-write all the anonymous classes to make them easier to debug and change a few of it's more dubious behaviours in the hope that tracks the error down
The core problem I asked - isn't really a problem tho, so...
Thanks for that!
I don't know if this is exactly the answer you are looking for (because it changes the Thingy class instead of the switchItOn() method), but I think I found a fairly easy and safe solution to your problem. If you are worried about someone extending Thingy and not properly doing whatever the endit() method needs to do, you could make it final. This will make it so that whatever is required to do in the endit() method will always be done and that method can't be overridden.
If you still want subclasses to be able to have flexability with that class, you could try something like this:
public class Thingy {
public void storeIt() {
//do stuff
}
public final void callEndIt() {
//do whatever stuff needs to be done every time in order for your program to work
endIt();
}
public void endIt() {
//this can be extended by subclasses safely
}
}
Then, you can just always call callEndIt() instead of endIt() so that whatever safety precautions you need to have done get fulfilled.
I've been attempting to resolve my problem for about a day now, but can't seem to get anywhere. The problem:
I have a java class, ExternalClass which has 30 methods in it.
I also have an interface ExternalClassFacade.
public class ExternalClass {
public method1() {...}
public method2() {...}
...
...
public metod30(...) {...}
}
This class is an external library and I cannot modify it's code.
The class works well but I have a situation where I need to group up multiple calls on an undefined timespan to all 30 methods, delay the execution, and execute all at once (serial or parallel I don't care) at some moment.
For example, over 10 minutes, methods 1 to 30 will be called randomly 500 times, I want them to do nothing at the moment of being invoked, but after 10 minutes I want to invoke all 500 calls as they were originally called.
most of the methods require parameters which I need to remember for the moment in which i will call the methods.
I'm looking for a way to extend/wrap/composite this class, so that when someone calls any of these methods, or, a special method that will bridge the calls to the original methods so that they will be delayed till the right moment comes.
I was thinking about extending the class and overriding all methods, and managing 30 Struct-Like classes to hold the info about the calls, but that would require :
30 overrides
30 lists
30 classes
Lots of code, not very smart.
I'm looking for a better way to do this, I was thinking about catching the calls and keeping the pointer to the original method call, but this is java, so it's not possible.
Very interesting problem indeed. First question: does ExternalClass implement some interface? If it does, it simplifies stuff a lot, however if it doesn't, you can create one:
interface ExternalClassFacade {
method1();
method2();
//...
method30();
}
Don't worry, you don't have to implement it! Just copy all the method signatures from the ExternalClass. Do you know java.lang.Proxy? Wonderful tool in such problems like yours:
ExternalClass ext = //obtain target ExternalClass somehow
ExternalClassFacade extFacade = (ExternalClassFacade) Proxy.newProxyInstance(
ExternalClass.class.getClassLoader(),
new Class<?>[]{ExternalClassFacade.class},
new BatchInvocationHandler(ext));
extFacade.method1();
As you can see this magic and obscure code created something that implements ExternalClassFacade and allows you to run the same methods as ExternalClass. Here is the missing puzzle:
public class BatchInvocationHandler implements InvocationHandler {
private final ExternalClass ext;
public BatchInvocationHandler(ExternalClass ext) {
this.ext = ext;
}
#Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
return MethodUtils.invokeMethod(ext, method.getName(), args);
}
}
This code itself is not doing anything useful - when you call a method on the ExternalClassFacade it forwards the call to the same named method on ExternalClass with the same arguments. So we haven't achieved anything yet. BTW I am using MethodUtils from Apache Commons Lang to simplify the reflection code a bit. Chances are you already have this library on the CLASSPATH, if not, it is just few lines of extra code.
Now look at this improved version:
private static class BatchInvocationHandler implements InvocationHandler {
private final ExternalClass ext;
private Queue<Callable<Object>> delayedInvocations = new ConcurrentLinkedQueue<Callable<Object>>();
public BatchInvocationHandler(ExternalClass ext) {
this.ext = ext;
}
#Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
delayedInvocations.add(new Callable<Object>() {
#Override
public Object call() throws Exception {
return MethodUtils.invokeMethod(ext, method.getName(), args);
}
});
return null;
}
}
Now we are getting somewhere: instead of calling the method we are wrapping the call inside Callable and adding it to a delayedInvocations queue. Of course since we are no longer calling the actual method, the return value is just a placeholder. If ExternalClass methods have return types different than void, you must be very careful.
I think you see the light now. Everything you need is to create a thread that will take all the Callables collected in the queue and run them in batch. You can do it in various ways, but the basic building blocks are there. Also you might choose data structure like map or set rather than a queue. I can for instance imagine grouping methods by name for some reason.
Of course if you can use AspectJ/Spring AOP you will avoid the whole proxy infrastructure code. But the basic idea will be the same only that the API will be more pleasent.
Using AspectJ, you could introduce an interface to the class, then code to the interface. After that, you're free to add whatever behavior behind the interface that you want. Alternately, just use AspectJ to weave in the collecting/executing behavior you're looking for.
Cglib or Javassist would also let you do it more cleanly by letting you basically proxy the class by dynamic subclassing (assuming it's not final).
There are plenty of options. Those are three third-party ones that occurred to me. An advantage of some of these approaches is that they'll give you some representation of a method invocation in object form, which you can easily collect and run at a later time.
You could use an aspect to intercept all calls to execute external lib methods and to pause the Thread, writing the Thread's ID to a synchronized Set. That Set is in a singleton being watched by another Thread.
When your business rule to execute is fired, have the singleton watcher iterate the Set and notify each thread to continue processing. The aspect will continue on and execute each originally requested external method.
I have an existing class into which I want to add a method. But I want the method to be called only from a specific method from a specific class. Is there any way that I can prevent that call from other classes/methods?
For example, I have an existing class A
public final class A
{
//other stuff available for all classes/methods
//I want to add a method that does its job only if called from a specific method of a class, for example:
public void method()
{
//proceed if called from Class B.anotherMethod() else throw Exception
}
}
One way of doing this is getting the StackTrace inside the method() and then confirming the parent method?
What I am looking for is a solution that is more clean and advisable solution like a pattern or something.
To be honest, you have painted yourself into a corner here.
If classes A and B are not related and not members of the same package, then visibility won't solve the problem. (And even if it did, reflection can be used to subvert the visibility rules.)
Static code analysis won't solve the problem if the code can use reflection to call the method.
Passing and checking B.this as an extra parameter to A.method(...) doesn't help because some other class C could pass a B instance.
This leaves only the stacktrace approach1... or giving up and relying on the good sense of the programmer2 not to call methods that they shouldn't.
The ideal solution is to revisit the design and/or coding decisions that got you into this mess.
1 - See other answers for examples that use annotations, a security manager, etc to conceal the stacktrace stuff from the application programmer. But note that under the hood you are adding probably hundreds, possibly thousands of instructions overhead per method call.
2 - Do not underestimate the programmer's good sense. Most programmers, when they see advice not to call some method, are likely to follow that advice.
The right way to do this would be a SecurityManager.
Define a permission which all code which wants to call A.method() has to have, and then make sure only B and A have that permission (this also means that no class has AllPermission).
In A, you check this with System.getSecurityManager().checkPermission(new BMethodPermission()), and in B you call the method inside of AccessController.doPrivileged(...).
Of course, this requires that a security manager is installed (and it uses suitable policies) - if it isn't, all code is trusted and everyone can call everything (if necessary, with Reflection).
You might consider using an interface. If you're passing in the calling class, you can confirm that the class is of the appropriate type.
Alternatively, if you're using Java, you can use "default" or "package" level access (e.g. void method() vs. public void method()). This will allow your method to be called by any class inside the package and does not require that you pass the class to the method.
The only way to check for sure at run time is to take a stack trace. Even if its private you can access the method via reflections.
A simpler way to do this would be to check usages in your IDE. (provided its not called via reflections)
As others have mentioned, using the stack trace is one way to implement the functionality that you are looking for. Generally, if one needs to "block" callers from a public method, it could be a sign of poor design. As a rule of thumb, use access modifiers that restrict the scope as much as possible. However, making a method package-private or protected is not always an option. Sometimes, one may want to group some classes in a separate package. In that case, the default (package-private) access is too restrictive, and it usually does not make sense to subclass, so protected is not helpful either.
If restricting calling to certain classes is desired, you can create a method like:
public static void checkPermission(Class... expectedCallerClasses) {
StackTraceElement callerTrace = Thread.currentThread().getStackTrace()[3];
for (Class expectedClass : expectedCallerClasses) {
if (callerTrace.getClassName().equals(expectedClass.getName())) {
return;
}
}
throw new RuntimeException("Bad caller.");
}
Using it is very simple: just specify what class(es) can call the method. For example,
public void stop() {
checkPermission(ShutdownHandler.class);
running = false;
}
So, if the stop method gets called by a class other than ShutdownHandler, checkPermission will throw an IllegalStateException.
You may wonder why checkPermission is hard-coded to use the fourth element of the stack trace. This is because Thread#getStackTrace() makes the most recently called method the first element. So,
getStackTrace()[0] would be the call to getStackTrace itself.
getStackTrace()[1] would be the call to checkPermission.
getStackTrace()[2] would be the call to stop.
getStackTrace()[3] would be the method that called stop. This is what we are interested in.
You mentioned that you want methods to be called from a specific class and method, but checkPermission only checks for class names. Adding the functionality to check for method names requires only a few modifications, so I'm going to leave that as an exercise.
Make proper use of protected
The standard way to do this in java is to put Class B and Class A in the same package (maybe a subpackage of your current application) and use the default visibility.
The default java visibility is "package-private" which means everything in that package can see your method, but nothing outside that package can access it.
See Also:
Is there a way to simulate the C++ 'friend' concept in Java?
Assuming that you only need to apply this restriction to classes within your project, static analysis could work for you - for example an ArchUnit test:
package net.openid.conformance.archunit;
import com.google.gson.JsonElement;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.AccessTarget;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import net.openid.conformance.testmodule.OIDFJSON;
import org.junit.Test;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.*;
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class PreventGetAs {
#Test
public void doNotCallJsonElementGetAs() {
JavaClasses importedClasses = new ClassFileImporter().importPackages("net.openid.conformance");
JavaClasses allExceptOIDFJSON = importedClasses.that(DescribedPredicate.not(nameContaining("OIDFJSON")));
ArchRule rule = noClasses().should().callMethodWhere(
target(nameMatching("getAs[^J].*")) // ignores getAsJsonObject/getAsJsonPrimitive/etc which are fine
.and(target(owner(assignableTo(JsonElement.class)))
)).because("the getAs methods perform implicit conversions that might not be desirable - use OIDFJSON wrapper instead");
rule.check(allExceptOIDFJSON);
}
}
You can do it by using annotations and reflection. I will report a similar case, i.e. the case where you can let the method being called only by specific methods from extenal classes. Suppose that the class that must be "protected" by a whatsoever invocation of the its public methods is Invoked, while Invoker is the class tha has a method enabled to invoke one or more methods from Invoked. Then, you can do something like reported in the following.
public class Invoked{
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public static #interface CanInvoke{}
public void methodToBeInvoked() {
boolean canExecute=false;
try {
//get the caller class
StackTraceElement element = (new Throwable()).getStackTrace()[1];
String className = element.getClassName();
Class<?> callerClass = Class.forName(className);
//check if caller method is annotated
for (Method m : callerClass.getDeclaredMethods()) {
if (m.getName().equals(methodName)) {
if(Objects.nonNull(m.getAnnotation(EnabledToMakeOperationRemoved.class))){
canExecute = true;
break;
}
}
}
} catch (SecurityException | ClassNotFoundException ex e) {
//In my case does nothing
}
if(canExecute){
//do something
}
else{
//throw exception
}
}
}
and the Invoker class is
public class Invoker{
private Invoked i;
#Invoked.CanInvoke
public void methodInvoker(){
i.methodToBeInvoked();
}
}
Note that the method that is enabled to invoke is annotated with the CanInvoke annotation.
The case that you requested is similar. You annotate the classes/method that cannot call the public method and then you set to true the canExecute variable only if the method/class is not annotated.
You can use a tool like Macker and add it to your build process to check some rules are respected, like
<?xml version="1.0"?>
<macker>
<ruleset name="Simple example">
<access-rule>
<deny>
<from class="**Print*" />
<to class="java.**" />
</deny>
</access-rule>
</ruleset>
</macker>
It will NOT prevent you from writing wrong code but if you use Maven or another build system it can raise an error during your build process.
This tools work at a "class" level not at a "method" level but I do not see the point of preventing the call of only one method from a certain class ...
I realise your use case states 'specific method in specific class', but I don't think you can reliably solve this at design time (and I can't think of a use case where this would have to be enforced anyway).
The following example creates an easy design time solution for restricting the access of a class' method to a particular class. It can, however, be easily extended to multiple allowed classes.
It is achieved by defining a public inner class with a private constructor that acts as a key to the method at hand. In the following example the class Bar has a method that should only be called from an instance of the Foo class.
Class Foo:
public class Foo
{
public Foo()
{
Bar bar = new Bar();
bar.method(new FooPrivateKey());
}
public class FooPrivateKey
{
private FooPrivateKey()
{ }
}
}
Class Bar:
public class Bar
{
public Bar()
{
}
public void method(FooPrivateKey fooPrivateKey)
{
if(fooPrivateKey == null)
{ throw new IllegalArgumentException("This method should only be called from the Foo class.");}
//Do originally intended work.
}
}
I don't think this is by any means safe for things like reflection or even things like FooPrivateKey.class.newInstance(), but this will at least warn the programmer a little more obtrusively than a simple comment or documentation, while you don't have to look in to more complicated things like what was suggested by people like Roberto Trunfio and Ronan Quillevere (which are perfectly viable answers as well, just too complicated for most situations in my opinion).
I hope this is sufficient for your use case.