AfterAdvice for all constructors of classes statically implementing an interface - java

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).

Related

AspectJ: intercept constructor when method reference is used

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?

Design suggestion: Changing the class behaviour

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.

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.

Java: Alternative to passing "this" as constructor argument in order to reference creating object

I've spent a while thinking about different solutions that the one I went for as I've read around (I am not really experienced with Java yet) that using this for a constructor argument isn't usually a good practice.
What I am trying to do is to instantiate several objects of class JobGroupMod and for every JobGroupMod I have to create a certain number of JobMod objects that must be able to reference back the JobGroupMod objects in which they've been spawned from.
In order to accomplish that I am passing "this" to the JobMod constructor but, even if working, it didn't feel like proper designing.
public class JobGroupMod implements JobGroup {
public JobGroupMod(Node n,Set<Job> clusterJobs){
JobMod j=new JobMod(n,this);
}
}
And now the JobMod class:
public class JobMod implements Job {
public JobMod(Node n, JobGroup jg){
setJobGroup(jg);
}
}
My question is, is there a better way of solving this, or is my solution the suggested way?
You should try using a static factory method (Effective Java link).
This way you avoid passing this in a constructor call, which is highly ill-advised to say the least.
example code:
public class JobGroupMod implements JobGroup {
public static JobGroupMod createModeMod(Node n, Set<Job> clusterJobs) {
JobGroup jg = new JobGroupMod();
JobMod j = new JobMod(n, jg);
return jg;
}
}
As long as it remains the only thing you do in the JobGroupMod constructor is is fairly safe as long as you understand the ramifications. There's a lot of Java code in the real world that does this. It's still not something you really want to do, especially when you start talking about multithreading and concurrency.
The danger is passing this to something else before an object is fully constructed. If the constructor were to throw an exception after you did this and not fully construct, you could have a nasty problem. If another thread were to access the object you passed this to before it was fully constructed, you'd have a nasty problem.
What you'll often find in Java is people using a factory pattern to avoid this, an "init" type method, or dependency injection.
Generally there is no magic. You can either pass parameter via constructor or initalize it later using setter/init method etc.
If your class JobMod needs reference to JobGroupMod and has nothing to do without it pass it using constructor. If sometimes it can stand without it create init() method or setter that can initialize this reference.
BTW sometimes you have to create both parameterized and default constructor: first for regular programmatic usage, second if you are using XML, JSON or other serialization that is going easier for bean-like classes. In this case at least create javadoc that explains that default constructor should not be used directly.

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.

Categories