How to check if class has methods added by aspect? - java

Suppose I have a simple class:
public class TestClass {
/*...*/
}
I created an aspect which injects new method to this class:
public aspect TestAspect {
public void TestClass.aspectMethod() {
/*...*/
}
}
Now, how can I check if TestClass has method added by TestAspect in runtime?

The simplest way would be to simply reflect on the class:
TestClass.class.getDeclaredMethod("aspectMethod")
which will throw NoSuchMethodException if it isn't there. Or if you have the bytes you could use a byte code visitor to check what methods exist in the byte code - but the reflective route would be less messing around.

Andy's answer is the correct one, I just want to answer your follow-up question from the comment:
Duck typing is not a Java feature, but if you use ITD in order to make the class implement an interface and then have an instance of your aspect-extended class you can use instanceof MyInterface in order to determine what you need to know. Other ways (also using reflection) are also available:
Interface with the method you want to add later via ITD:
package de.scrum_master.app;
public interface MyInterface {
void myMethod();
}
Sample driver application:
package de.scrum_master.app;
import java.lang.reflect.Type;
public class Application {
public static void main(String[] args) {
Application application = new Application();
// Use an instance
System.out.println(application instanceof MyInterface);
System.out.println(MyInterface.class.isInstance(application));
// Use the class
for (Type type : Application.class.getGenericInterfaces())
System.out.println(type);
for (Class<?> clazz : Application.class.getInterfaces())
System.out.println(clazz);
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.Application;
import de.scrum_master.app.MyInterface;
public aspect MyAspect {
declare parents : Application implements MyInterface;
public void Application.myMethod() {}
}
Application output:
true
true
interface de.scrum_master.app.MyInterface
interface de.scrum_master.app.MyInterface

Related

User defined class import at run time

I'm trying to figure out how to resolve the following use case:
A user can define a Java class, say MyFoo like this (the code is generated automatically and the guid is set to avoid name collisions)
import com.bar.entities.BaseEntity;
package com.bar.entities.defined.79B35635_DEDF_A344_9621_0477A6E71725;
public class MyFoo extends BaseEntity {
public String getFoo() { ... }
public Integer getBar() { ... }
#Override
public byte[] serialize() {...}
}
A user can import that Java class in other class like this:
package com.bar.business;
import com.bar.entities.defined.79B35635_DEDF_A344_9621_0477A6E71725.MyFoo;
public class Business extends Minion {
#Override
public void execute(EntityProvider ep) {
MyFoo myFoo = ep.get("myFoo", MyFoo.class);
if (myFoo.getBar() < 10) {
notifyMaster();
}
}
}
Additionaly I have a Java application (actually a Grizzly HTTP Server with a Jersey API Rest) that must be able to compile both classes.
¿How can I compile both classes? The first one can be compiled. The second one can't because the compiler says that the method getBar() is not known (it does not fail at the import line, surpringsly)
I want to send both Class<?> instances over the network and use them elsewhere via reflection with getDeclaredConstructor()
Kind regards.

AspectJ: track new object initialization

I'm trying to understand AspectJ. I want to try to count all object initializations (which are initialized from the classes I've specified, not some Java-internal ones) in a project and I'm really not sure how to do this.
Let's say I have classes called A and B, where A has subclasses Aa and Ab, B has the subclasses Ba and Bb, and Bb has the subclass Bba. I'd like my aspect to track every single initialization of the objects created with those classes as a base, but I don't really understand how to properly do this (even though this should be somewhat simple). So far, I have something similar to this:
public aspect AspectCounter {
private int objects = 0;
pointcut countObjects() : initialization(A.new(..)) || initialization(B.new(..));
pointcut printObjects() : call(* Test.printCounter(..));
after() : countObjects() {
objects++;
}
after() : printObjects() {
System.out.println(objects);
}
}
Which does, at least, print the right amount of A's and B's I've created (I didn't go with B*.new(..) since it would, the way I understand it, track any initialization of Bba three times which I don't want in this case).
The way it works right now is that I have a Test class which, well, does test stuff, and after I'm done with the testing, I'm just calling an empty printCounter method that doesn't really do anything. It seems to work and does actually give me the right number of objects, but I'm sure there's a better way to do this. I really don't like having an empty method.
You cannot do this with initialization, preinitialization or execution pointcuts on *.new(..) because of the order in which they are executed. They are not nested as you might think but executed rather sequentially due to the way the JVM works. I have explained this in detail here including sample code and log output. So you are only left with the option to use a call pointcut. Here is an example:
package de.scrum_master.app;
public class A {}
package de.scrum_master.app;
public class Aa extends A {}
package de.scrum_master.app;
public class Ab extends A {}
package de.scrum_master.app;
public class B {}
package de.scrum_master.app;
public class Ba extends B {}
package de.scrum_master.app;
public class Bb extends B {}
package de.scrum_master.app;
public class Bba extends Bb {}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new A();
new Aa();
new Ab();
new B();
new Ba();
new Bb();
new Bba();
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.A;
import de.scrum_master.app.B;
public aspect InstanceCreationCounter {
private static int count;
after() : call(A+.new(..)) || call(B+.new(..)) {
System.out.printf("%4d %s%n", ++count, thisJoinPoint);
}
}
Console log:
1 call(de.scrum_master.app.A())
2 call(de.scrum_master.app.Aa())
3 call(de.scrum_master.app.Ab())
4 call(de.scrum_master.app.B())
5 call(de.scrum_master.app.Ba())
6 call(de.scrum_master.app.Bb())
7 call(de.scrum_master.app.Bba())
I guess this is what you want.
Caveat: You need to have control over all the calling code and weave the aspect into it in order for this to work.

Java: How to get the object of a subclass by calling it's parent class

import java.util.*;
import java.lang.*;
import java.io.*;
class mainA {
private mainA obj;
public mainA(int type) {
System.out.println("accessing mainA");
switch(type) {
case 1:
obj = new mysql();
break;
case 2:
obj = new mssql();
break;
default:
break;
}
}
}
class mysql extends mainA {
public void printme() {
System.out.println("accessing mysql");
}
}
class mssql extends mainA {
public void printme() {
System.out.println("accessing mssql");
}
}
class C2 extends mainA {
public C2() {
super();
}
public static void main(String args[]){
Object b = new C2();
b.printme();
}
}
I need to achieve the following scenario. It would be great if someone can help me out.
I'm trying to create a common API library set which can be scaled to as many backend databases as possible.
The idea is to create an object of C2, which in turn would return the value of either mysql/mssql based on the dbtype. The type parameter can be obtained from any where in the code. mainA is the super class which consists of config params. Type can be obtained here as well. The problem here is that I'm stuck with not being able to get the object of mysql/mssql from C2. The ideal situation would be to create an object of C2 which refers to mainA that gets the type and inits either mssql/mysql. C2.printme must call the db class which was specified in the type.
Would generic classes be of any help here?
you can have an instanceof test to cast the object but it is lame as you would have to change your code if you are adding a new type of DB object.
You can have a good interface and make the subclasses implement it so that you can call through your interface without caring about the actual implementation object.
Coding to Interface is what you should be doing.
You've got some work ahead of you. You'll want to read up on interfaces. In your example, you can do something like the following (it's a bit silly in the real world).
Let's call our interface Printable.java (by convention, starts with either the capital letter "I" or ends in "-ible", "able," etc). I wouldn't really call it Printable, but for the purpose of this example:
public interface Printable {
public void logDatabaseType();
}
Your parent class (we can make it abstract so that it cannot be created directly without an underlying implementation):
public abstract class Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("logDatabaseType()");
}
}
Your subclasses:
public class MySQL extends Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("Accessing MySQL");
}
}
public class MicrosoftSQL extends Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("Accessing MSSQL");
}
}
In your test class (you should try to get your feet wet with JUnit as early as possible):
public class DatabaseLogTest {
#Test
public void printDatabaseType() {
//programming by interface
Printable printable = new MySql();
printable.logDatabaseType();
printable = new MicrosoftSQL();
printable.logDatabaseType();
//then later you can do
//someMethod(printable);
//and the printable object will retain whatever was instantiated
//and someMethod will be blissfully ignorant of the actual implementation
}
}
#Override is important because it tells your IDE and the developer that you're overriding an implementation and the IDE will spit out errors if the implied contract is not met. You should have this whenever you're overriding.
You'd also want to use a logger (e.g., SLF4j over Log4J or logback) rather than System.out.println() method calls.

Strange behaviour on method annotations and default access level

Here's my problem...
I have an annotation in package pkg3:
package pkg3;
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface TestAnno {
}
Also I have two classes in package pkg1, one with public access and one with default access
package pkg1;
import pkg3.TestAnno;
class Class1 {
#TestAnno
public void test1() { }
public void test2() { }
}
and
package pkg1;
import pkg3.TestAnno;
public class Class2 extends Class1 {
#TestAnno
public void test3() { }
public void test4() { }
}
Finnally I've got a main class in package pkg2
package pkg2;
import java.lang.reflect.Method;
import pkg1.Class2;
import pkg3.TestAnno;
public class MainClass {
public static void main(String[] args) {
Class2 cls = new Class2();
for(Method m: cls.getClass().getMethods()) {
System.out.println(m);
if (m.getAnnotation(TestAnno.class) != null) {
System.out.println(" > hass anno");
}
}
}
}
Running this example I expect to see the info, that two methods have #TestAnno present - test1 and test3, but I only see one test3, and... what is strange, the methods test1 and test2 are listed as they were be declared in class Class2.
public void pkg1.Class2.test3()
> hass anno
public void pkg1.Class2.test4()
public void pkg1.Class2.test1()
public void pkg1.Class2.test2()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
... rest methods from java.lang.Object
I know, that getMethods returns only public methods from given glass (and it's all super classes) but... this is strange for me.
I'm using this in order to separate generated classes (which have default access) from implementation classes (which are public and they're extending generated classes).
Have I to use public access in generated classes (I wanted them not to be visible to rest of the world) or is there any way to get annotated public methods from Class1 ?
This answer is just a "one big maybe" made by a man at 3 a.m. so it will require JLS confrontation, better terminology and more informations. I was planning to post it as comment but unfortunately it is too long :/
Lets take a look at this classes
class SomeClass {
#TestAnno
public void test(){}
}
class SomeDefaultClass extends SomeClass {
}
public class SomePublicClass extends SomeClass {
}
now take a look at this code and its result
Method m1 = SomePublicClass.class.getMethod("test");
Method m2 = SomeDefaultClass.class.getMethod("test");
System.out.println(m1 + "\t> " + m1.getAnnotation(TestAnno.class));
System.out.println(m2 + "\t\t> " + m2.getAnnotation(TestAnno.class));
output
public void SomePublicClass.test() > null
public void SomeClass.test() > #TestAnno()
As you see public class that extends class with package modifier doesn't inherit annotations, but class with package modifier does.
Why is that?
Both SomeDefaultClass and SomePublicClass "inherited" test() method but not in the same way.
If you take a look at result of javap SomeDefaultClass.class you will see
class SomeDefaultClass extends SomeClass {
SomeDefaultClass();
}
so it doesn't have test() method in its binaries, so it will use it from SomeClass which have TestAnno annotation.
On the other hand if you take a look at result of javap SomePublicClass you will see
public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}
which means that code of test() method has been overridden in SomePublicClass so this method has been declared again in SomePublicClass but unfortunately without previous annotations and since overridden method doesn't have annotations you wont see them in your code. (Why annotations are not added when compiler is overriding method? Honestly, I don't know :/)
Why is overriding happening? I suspect that since SomePublicClass is public and test is also public it should be accessible from all packages, but since SomeClass has default/package visibility this method couldn't be accessible via SomeClass from outside of its package.
To prevent moving/copying test method from one class to another you can make both classes public or default/package.

Use Aspectj to find List of classes implementing a certain interface

Is it possible using AspectJ to find a list of all Classes which implement a certain interface. For e.g I have an interface MatchRule. Then I can have classes DefaultMatchRule and CustomMatchRule concrete clases which implement MatchRule interface.
Now at runtime I want to get a list which will have 2 classes DefaultMatchRule and CustomMatchRule
public interface MatchRule {
}
public class DefaultMatchRule implements MatchRule {
}
public class CustomMatchRule implements MatchRule {
}
public aspect FindSubClasses {
// some thing to find list of classes implementing MatchRule interface
}
AspectJ is not designed to finding classes. Your best option is to scan the classpath and use reflection.
If you can live with compile-time information, the Eclipse AJDT plugin offers good graphical information for all AspectJ advises.
But if you can live with some limitations, you can find the classes for all objects that is advised by AspectJ.
A solution that prints out the class names for all objects of classes that implements MatchRule:
#Aspect
public class FindSubClassesAspect {
#Pointcut("execution(demo.MatchRule+.new(..))")
public void demoPointcut() {
}
#After("demoPointcut()")
public void afterDemoPointcut(
JoinPoint joinPoint) {
FindSubClasses.addMatchRuleImplememtation(
joinPoint.getTarget().getClass().getSimpleName());
}
}
A class that contain the information about all the MatchRule implementations:
public enum FindSubClasses {
;
private static Set<String> matchRuleImplementations =
new HashSet<String>();
public static void addMatchRuleImplememtation(String className) {
matchRuleImplementations.add(className);
}
public static Collection<String> getMatchRuleImplementations() {
return matchRuleImplementations;
}
}
A simple driver that demonstrate that the aspect works:
public class Driver {
public static void main(String[] args) {
new DefaultMatchRule();
new CustomMatchRule();
Collection<String> matchRuleImplementations =
FindSubClasses.getMatchRuleImplementations();
System.out.print("Clases that implements MatchRule: ");
for (String className : matchRuleImplementations) {
System.out.print(className + ", ");
}
}
}
The output of executing this driver:
Clases that implements MatchRule: DefaultMatchRule, CustomMatchRule,
I hope this helps!
The only possible way to do this at runtime is probably scanning all your packages and checking to see whether your classes implement that interface.
I can't think of any other way this is possible. In fact, Eclipse has a context menu option that shows the "Implementors" of an interface but they achieve that by scanning the packages.

Categories