AspectJ: intercept constructor when method reference is used - java

For normal contructor calls with new I use
pointcut replaceableNew() : call((#Replaceable *).new(..));
Object around() : replaceableNew() {
Constructor<?> constructor = ((ConstructorSignature) thisJoinPointStaticPart.getSignature()).getConstructor ;
Class<?> declaringClass = constructor.getDeclaringClass();
if (!Registry.getInstance().isReplaced(declaringClass)) {
return proceed() ;
}
Class<?>[] parameterTypes = constructor.getParameterTypes();
Object[] args = thisJoinPoint.getArgs();
return Registry.getInstance().create(declaringClass, parameterTypes, args); // creates some sub-class of declaring class
}
but this does not work when contructor is passed as method references.
Stream.of(1,2).map(SomeReplaceable::new) ...
Workaround for instance method references (with "*lambda*" ) does not work.
execution((#Replaceable *).new(..)) pointcut does not allow to replace the returned object.
Maybe some combination of call(* *(..)) and execution(... above could work, but this way we will advice too much calls and also will create and discard unneccessary replaceable instances. Looks ugly.
Any other ideas?

Maybe some combination of call(* *(..)) and execution(..) above could work
No, it will not, because there simply is no call() joinpoint to intercept for AspectJ when using method references. The same is true for reflective constructor calls.
Thus, your idea will only work for simple cases, i.e. when there is a normal constructor call you can intercept. As you already noticed, you cannot directly replace the instance generated by a constructor, not even with low level byte code engineering frameworks such as ASM or BCEL or higher level ones like Javassist or ByteBuddy - simply because the JVM does not allow it. The best you can do with such frameworks is to transform the constructor code such that it skips object initialisation and directly calls the super constructor with dummy arguments (all super constructors also have to be instrumented in order to skip initialisation, BTW).
Besides, your aspect, even if it was possible to replace objects returned by execution(*.new(..)), would have to take care of excluding this() and super() calls, make sure to do the right thing if a subclass of the annotated class is being instantiated etc.
The whole idea just does not work. Sorry to destroy your dream (I also used to have this idea many years ago), but these are the facts.
Coming back to the XY problem: I am asking you again to rather describe what you want to achieve, not to describe how you think this ought to be done technically. What is your use case? Which problem are you trying to solve?

Related

Calling a function that does not exist via reflection/javassist

i need to call a function - (getters and setters of a property), but my problem is, the name of the property is generated at runtime (name of some variable + number).
Is it possible to manipulate the bytecode via javassist or gclib so that the function calls are directed to some proxy object/function, and there the real method name and the number extracted from the called function name, so that i can call the function afterwards (with the number as parameter)?
I tried the following, but it didnt work:
MethodHandler handler = new MethodHandler() {
#Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) {
String realMethodName=thisMethod.substring(0,5);
Integer param=Integer.parseInt(thisMethod.substring(5));
Method m = self.getClass().getMethod(realMethodName);
m.invoke(self,param);
return null;
}
};
I think this might be one of the few scenarios where using Java reflection Proxy objects might come in handy.
You could define some interface, but delegate the method to the (dynamic) invocation handler which would then call those "getter/setter" methods.
Side note: when implementing such an invocation handler you have to understand that ANY method call on the corresponding object will trigger its "invoke" method; event when you call toString or equals or whatever else is inherited from Object.
EDIT: and one more (different) thought: are you sure you need to create dynamic method names at all? If you have some numeric (or string based) key - what not using a Map for example?
Like
Map<WhateverKeyType,YourPropertyClass>
that would be much more "normal java" way of handling your problem (instead of thinking about reflection or byte code manipulation).
If you wanted to implement something similar but could think of using another library than javassist, consider using Byte Buddy (which I wrote, for disclosure).
Considering, you have an interface
interface Foo { Object getProperty() }
that you wanted to implement to access a property of the bean
class Bar { Object getAbc123() { ... } }
Then using Byte Buddy, you could implement a class
Foo accessor = new ByteBuddy()
.subclass(Foo.class)
.method(named("getProperty"))
.intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("getAbc123"))
.on(new Bar()))
.make()
.load(Foo.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.newInstance();
of the interface that redirects the invocation of getProperty to the method of your choosing. With a little bit of customization, you can surely create a more generic solution.

Testing a method which calls private void method inside using mockito

I want to test a method which internally calls a void method.
Below is the code
public String process(MKSConnectionParams mksConnectionParam, IProgressMonitor progressMonitor) throws Exception {
if (null != progressMonitor) {
progressMonitor.beginTask("Starting the creation of report", 100);
}
if (null == mksConnectionParam) {
initialize(MksLibFactory.getDefault());
}
else {
initialize(mksConnectionParam, MksLibFactory.getDefault());
}
--------------
}
public void initialize(MKSConnectionParams mksConnectionParam, IMksLibrary mksLibDefault) throws Exception {
paramMKSConnectionParams = mksConnectionParam;
GlobalConstants.hostName = paramMKSConnectionParams.hostname;
GlobalConstants.port = String.valueOf(paramMKSConnectionParams.port);
try {
localISi = mksLibDefault.getSi(paramMKSConnectionParams);
localIIm = mksLibDefault.getIm(paramMKSConnectionParams);
}
catch (MksLibException | AuthenticationError e) {
throw e;
}
ProjectInfo prjInfo = localISi.getProjectInfo(pathToPj);
projRevCmd = prjInfo.getConfigPath().getConfigPath() + "#b=" + projectRevision;
}
I am writing mockito test case for process() method. Testing is getting failed when initialize(mksConnectionParam, MksLibFactory.getDefault()) is called. It is because in the process we are calling real mks connection and I am passing dummy user name and password.
We aren't able to mock this initialize method. Is there any way to do this?
Small pseudocode would be of great help.
Earlier I had initialize method as private. Would changing it to public make any difference?
There are several ways to test this scenario, and different people would advocate different approaches, mostly based on personal preference.
Notice that testing this, will require changes in the code of the class you're testing (I believe you neglected to mention its name). There is one exception, and that's if you're using PowerMock. I won't go into the details here, but you find out more on how to incorporate it into your mockito code here.
Back to regular testing methods, the problem is that you're using the real IMksLibrary instead of a mock, and that's because you obtain a reference to it inside the process method. Here are a few method that you might want to consider:
Change the signature of the process method to receive the reference to the IMksLibrary instance, so that the test code can supply a mock of it
Instead of creating the reference inside the process method inject a reference to the class, either by using some DI framework (e.g. Spring, Guice, CDI, etc.), or as a constructor parameter
Create a protected method called something like getIMjsLibraryInstance() in the class, that will return MksLibFactory.getDefault(), and use it instead of the explicit code (this is the Extract Method refactoring that can be automatically done by most IDEs for Java nowadays). In the test code, you need to create a subclass (this is why it's my least favorite method) which overrides this method and returns a mock, and test the subclass instead of the real class. Notice that this is the ONLY method that you should subclass
You might feel deterred from using the third method, since in effect, you're not really testing the class that you meant to test (but rather a subclass of it). I tend to agree that this has a bed smell to it. However, keep in mind, that unlike the other two methods, this will not require any changes to the clients of the class (this is a pretty strong argument in favor of it).
There are other methods that you can use, but they are pretty similar in nature to the first two methods, and they also require some changes in the code.
If you feel that any "regular" method of testing is not good enough (due to code changes or whatever other reason), you are welcomed to take a look at PowerMock, which will enable you to intercept the static method call that returns the IMksLibrary instance, and return a mock instead. A word of caution though. There are some serious coupling that happens when these type of solutions are used, so it is usually not highly recommended, unless you are really in a dire need.

Constructors: get type list from argument list

I'm currently working on a program where I will be dynamically loading classes at runtime and am building a library of functions to support it. One of these functions is a method to easily search a given jar file for a given class name and create a new instance from the given set of initialization arguments.
The issue is arguments. I know how to find a constructor for a class for a set of class types, however, trying to find a constructor that accepts a list of arguments is harder. My first thought was to iterate through the arguments and call getClass() on each, but what about null arguments which may well be a valid thing for some constructors?
Is there any sensible way to find the correct constructor for a given set of arguments?
NOTE: standard Java only, this is a joint project so Java derived languages and 3rd party libraries are not available.
Did you go through Reflection API tutorial?? It has the implementation for exactly what you want..
After you pass the Reflection API Tutorial, you can use single method for your problem
private final boolean checkConstructor(Class<?> type, Class<?>... parameterTypes) {
try {
forName.getConstructor(parameterTypes);
return true;
}catch(NoSuchMethodException e) {
}
return false;
}
What you have to remember that order of the paraemterTypes is important.
You should not allo to sytiation where you call for a constructor not knowing the parametersTypes. Same rule apply to code style that you should not use null in the constructors.
getClass() is a right approach. You have to iterate over all accessible constructors and choose most specific one acting according to the spirit of Choosing the Constructor and its Arguments, including throwing exeptions if 0 or >1 constructors found, and boxing/unboxing as in Determine Method Signature. You cannot implement that algorithms literally because of nulls, but should keep as close as possible.

How to override instance/concrete class's method runtime? (e.g. reflection, cglib)

What I wanna do is a method that can
generate instance of Class X (a class variable passed in arg) and
override some of it's method
More specifically, the parent class X I want to override contains
Contains no default constructor (e.g. all constructors with args)
Constructors calling non-private method within the same class
Originally I thought it's quite simple to use reflection or something similar,
Then I found there's limitation on implementing my requirement.
For refection: Can only override "interface" via java.lang.reflect.Proxy
http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
for cglib: it cannot create instance of no default constructor and constructor calling non-private member methods
http://insufficientinformation.blogspot.com/2007/12/spring-dynamic-proxies-vs-cglib-proxies.html
I think this is achievable, since Mockito can do all kinds of method injection runtime.
Please anyone give some advise, Thanks.
The pseudo-code I image is like this:
createAndOverride(Class X) {
X newObj = X.newInstance(args) {
#override
methodOfX(args2) {
...
}
}
return newObj;
}
Original problem scenario
I was intended to test a Class which has several methods calling X1.get(), X2.get(), X3.get()
In some test case, I need to make Xn.get() to return something I can control for test (e.g. null)
Due to below constraint:
But due to mock tool restriction to JMock 1.0 (I have no control :( ), so I cannot just simply mock Xn.get() to returns "someSpecifiedObjects"
Xn has no null constructors and constructors calling non-private member
My workaround is self made Xn Class and pass them to test case to let Cn.get() to be expected
code example:
ClassToTest.SomeMethod(new X1() {
#override
get() {
return someSpecifiedObjects;
}
});
And this kind of thing is spread-ed over the Test Case.
Therefore, In order to reduce duplicate code, I would like to build a method to generate Xn instance with specified overrided method for test. e.g.
X1 x1 = createAndOverride(X1);
Then, the problem of this post comes
are you looking for something like javassist? You can instrument code and inject your methods at runtime. I personally try to avoid byte code manipulation as much as possible. Can you not have these overrides in your code base rather than doing on the fly? May be something like wrappers?
So what I think you need is a similar functionality to C#'s Reflection.Emit:
Using Reflection.Emit to create a class implementing an interface
Java Equivalent of Reflection.Emit
Dynamically Create Java Classes With JavaClassCreator
While I haven't done this myself, I think you should be able to use reflection/emission and dynamic type creation in order to achieve what you're looking for. However, I would still like to mention that if you're trying to test "functionality" that's not int he code path of the function you're testing, then you probably shouldn't be testing it at all. For example:
SomeObjectInterface get()
{
if(_someObjectStateIsSet)
{
// Return a concrete implementation A
return new ConcreteImplA();
}
else
{
// Return a concrete implementation B
return new ConcreteImplB();
}
}
In this case get has no code path that would return null, so you shouldn't need to test for null. I'm not sure if I understood your question 100% correctly, especially why you're testing for null, but consider the above advice and see what works for you.

AfterAdvice for all constructors of classes statically implementing an interface

I want to do some authorization-checks for domain objects. This includes checks if someone is allowed to instantiate an object (depending of it's type - this check is done externally so no need to solve this).
All our domain objects implement one specific interface (directly or indirectly)
What I need is an advice which runs after the instantiation of a domain object and is able to use the created instance (needed for the determination of the permission). (Additionally the advice may not execute when the constructor is called out of hibernate)
I want to implement this using AspectJ (which is working yet for methods) ideally using only static analysis as there are no a runtime dependent changes
Now I am trying to create an #AfterReturning adivce which intercepts constructor calls. But I do not get the pointcut working.
What I tried:
#Pointcut("within(a.b.c.DomainObject+) && execution(*.new(..))")
#Pointcut("execution(a.b.c.DomainObject+.new(..))")
But both does not work.
Does anyone know how I can achieve this?
Regards Michael
Here are some examples that helped me figure out how to do something similar. http://www.eclipse.org/aspectj/sample-code.html
Also, here is something that I have in my project--for testing purposes--to add a listener after an object is created:
pointcut init(JComponent j):
this(j) &&
initialization(*.new());
after(JComponent j) returning: init(j) {
if(j instanceof JButton && !(j instanceof AccessibleButton))
System.out.println(j.toString() + thisJoinPointStaticPart.getSourceLocation());
j.addFocusListener(new VisualFocusListener());
}
EDIT:
The above will execute every time a constructor is called, whether it is the one called or called by this() or super()--probably not what you want. I have just figured out another way to get at the object returned from the constructor.
after() returning(JComponent j): call(*.new(..)) {
//do something with j
}
That reads in English almost like it does in code: "after returning a JComponent from a constructor, do something". I have *.new(..) because I don't care which constructor is called or what parameters it takes as long as it gives me a JComponent. You can further limit that by saying Foo.new(..) or Foo.new(int).

Categories