Creating our own aspects using custom annotations - java

I am new to Annotations and new to StackOverflow and this is my first question. I am trying to write custom annotations which will help me trace and log method executions.
For example:
class A
{
#Logthis
void methodA();
}
Here whenever the method methodA() is executed, I want to log to a file telling "we are entering the methodA in class A" and when methodA is over "we are exiting methodA in class A" something like this. We vil have a number of classes and methods.
I know that this can be done using AspectJ. I have done it by defining pointcuts and joinpoints. But I want to do it using custom annotations.
It will be very helpful if anyone can guide me as to how to go about this.
Thanks in advance.

Using AspectJ you do the following :-
Create an Aspect Class annotated with #Aspect
Annotation a method in the class with #Around and define the value to be execution on classes that you have annotated. You will also need to have enabled proxying of you classes by AspectJ.
#Aspect
public class LoggerAspect {
#Around(value = "execution(#you.custom.Annotation * *(..))")
public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable
{
// DO LOGGING HERE
}
}

You can use Log4J. Here is a tutorial of it:
http://javakane.blogspot.fr/2012/07/automate-log4j-logging-with-aop-and.html

It seems you want to roll your own aop framework. IMHO this is not a very good idea, a lot of work has gone into AspectJ and you would benefit greatly from using it. But I suspect you already know that :) It is strange that you can use NO external jars, that is rather stringent even for commercial software.
But if you really need to do it, you can probably learn from others. AspectJ is open source and there is nothing stopping you from reading through it and adapting it to you needs.
For limited requirements, it is probably not very complex either. You would need a java agent which can look at annotations on classes and methods as they are loaded and modify their bytecode to add logging. Again, there are excellent libraries out there that can aid this but alas you cannot use them.
Another option might be to use jpda. I have no experience with that, but I suspect it will have a significant impact on performance.

Related

Spring and AOP - handling every thrown exception

I have a requirement to intercept every thrown exception and do something with it. I am using this part of code:
#Aspect
#Component
class Advice
{
#AfterThrowing(pointcut = "execution(* mail.service..*.*(..))", throwing = "throwable")
public void sendError(Throwable throwable)
{
System.out.println("exception thrown");
}
}
This somehow does not work as I expected. This pointcut seems to 'affect' only the public methods(which is expected from Spring AOP, I suppose?) but it prints the String only in certain methods, for example, methods that are declared in my Spring configuration class(i guess its because they are initialized before the app starts) and not in the other ones.
I tried to get this aspect working for any exception thrown, but I had no success. Is this somehow connected with the fact that I am using Spring AOP and not full AspectJ?
Also, my project is written in Kotlin(I wrote the aspect in Java so IJ can support it), will this have an impact on using AspectJ? I had a lot of troubles to get it working (because of final classes) and I am wondering if it's going to be a lot harder when I start writing more advanced AspectJ code.
Thanks!
Yes, Spring AOP only works for Spring components and only for public methods (plus protected and package-protected ones for CGLIB proxies). It also does not work for self-invoked methods like this.doSomething() because those do not go through the proxy. Only if your exceptions escalate outside a method called via proxy, Spring AOP will be able to intercept it.
AspectJ with LTW (load-time weaving) or CTW (compile-time weaving) does not have any of those limitations, plus you can also handle exceptions in constructors, not just in methods.
Never having used Kotlin before, I cannot tell you what possible problems might be there, but final classes should not be a problem as such because AspectJ instruments the classes' bytecode directly, not via proxies. Just give it a try.
BTW, just in case you only use Spring because of AOP: You do not need to use Spring at all in order to apply AOP to your classes because AspectJ is 100% independent of Spring. You can use them together or not, your choice. I for example never use Spring, but just Java SE + AspectJ.

How to configure Spring AOP to use AspectJ

I want to use AOP concept to time execution time of some methods that I mark with an annotation that I created. My problem however is that I refer to the annotated method internally, from within the same class. For example:
public void login(params) {
some logic ...
performLogin();
some logic ...
}
#Measured
public void performLogin() {
some logic ...
}
This is a known issue caused by the fact that Spring AOP is using proxy based approach that does not "see" the internal calls within the same class. Apparently I can solve this situation by using AspectJ instead of Spring AOP. If I understand correctly, it can be configured from within Spring itself. From what I found, it looks like I should include #EnableAspectJAutoProxy annotation to configure Spring to use AspectJ instead of its own AOP. Unfortunately, it did not help and after adding the annotation, the interception of the annotated method did not occur.
There is a lot of information on this topic in Spring reference documentation and I got a bit lost. Is there anything else I am supposed to do so that AspectJ will be used?
P.S. Please note that I cannot refactor the whole class and move the calling method outside.
P.P.S. I also verified my pointcut configuration. I annotated the calling method which is invoked externally and it worked fine.
Proxies can only achieve a sub-set of the full capabilities of the actual AspectJ system, basically advice that wraps methods. Due to their nature proxies have following limitations:
interception on external calls only (while breaching proxy boundary)
interception on public members only (private/protected can't be intercepted)
unawareness to local calls (or calls with this or super)
<aop:aspectj-autoproxy /> is not enough - it only wraps methods, you need something like this: <context:load-time-weaver/>
If you want to be able to advise fields for example, you would need to enable the use of Native AspectJ.

JAVA : know when a method is called

thinking of a weird problem in here. Say for example you have code deployed on your server which does the following:
//GET request called when a URL is hit
public void gETCalled(){
MyClass.invoke();
}
Was wondering if its possible to know, from an external test class (which is deployed in the same server environment) on whether invoke() was ever called at all, without modifying MyClass ?
I am trying to write acceptance tests and was wondering if this was ever possible (without touching my MyClass code)
In terms of test cases, PowerMock can intercept static method calls.
http://code.google.com/p/powermock/wiki/MockStatic
However, from server side code, AoP (in particular aspectj) would be your best bet. That way you don't have to actually change any of your code (just code an aspect class), and you can enable it only when you want to adding in the aspectj weaver as a javaagent.
The aspect would look something like this:
#Aspect
public class TrackMyClassInvoke {
#Before("execution(* MyClass.invoke())")
public void beforeInvoke() {
// do something to track it here
}
}
You'd need to make sure to include MyClass in your weaving (i won't get into the full process of weaving, as you can find that all on the aspectj site)
http://www.eclipse.org/aspectj/
I think you may be able to use AoP to do this. I haven't used it myself, but I believe that it will let you create a logging mechanism where you can do something like when you method is called, print out or log some statement.

Dependency Injection With Annotations

I would like to build my own custom DI framework based on Java annotations and I need a little direction to get started. I know it would be much easier to use one of the many wonderful frameworks out there such as guice or spring, but for the sake of my own curiosity, i'd like to build my own.
I'm not very familiar with annotations, so i'm having a bit of trouble finding resources and would really appreciate someone just sort of spelling out a few of the steps i'll need to take to get started.
As fore mentioned, id like to take a factory approach and somehow label my getters with an #Resource or #Injectable type annotation, and then in my business classes be able to set my variable dependencies with an #Inject annotation and have the resource automatically available.
Does anyone have any sort of resource they can pass along to help me understand the process of tagging methods based on annotations and then retrieving values from a separate class based on an annotation. A little direction is all I need, something to get me started. And of course i'll be happy to post a little code sample here once I get going, for the sake of others future reading of course.
EDIT
The resources I am using to put this together:
Java Reflection: Annotations
How to find annotations in a given package: Stack Overflow ?
Scanning Annotations at Runtime
I have not actually finished writing this yet, but the basic task list is going to be as follows (for anyone who might be interested in doing something similar in the future)
At class runtime scan for all #Inject fields and get object type.
Scan all classes (or just a specific package of classes (I haven't
decided yet)) for annotated methods #InjectableResource.
Loop all annotated methods and find the method that returns the
object type I am looking for.
Run the method and get the dependency.
It will also be helpful to note that when scanning all the classes I will be using a library called Javassist. Basically what this does is allows me to read the bytecode information of each class without actually loading the class. So I can read the annotation strings without creating serious memory problems.
Interesting that you want to build your own. I love Google Guice - it makes code so elegant and simple.
I've used this guide before which I found pretty useful for learning about annotations and how you can pull them out of classes and methods.
You will have to define your own Annotations which is done using #interface. Then you will have to define some kind of class for doing bindings e.g. where you see an interface bind in this concrete class. Finally, you will need some logic to pull it altogether e.g. go through each class, find each annotation, and then find a suitable binding.
Give consideration to things like lazy instantiation through Reflections and singletons. Guice, for example, allows you to use a singleton so your only using one instance of the concrete class, or you can bind a new version each time.
Good luck!
Have a look at the following methods:
java/lang/Class.html#getAnnotation(java.lang.Class)
java/lang/Class.html#getAnnotations()
java/lang/Class.html#getDeclaredAnnotations()
Methods of the same name also exist for the java/lang/reflect/Method, java/lang/reflect/Field and java/lang/reflect/Constructor classes.
So in order to use these sorts of methods, you need to know a bit about Java reflection.

Arguments Against Annotations

My team is moving to Spring 3.0 and there are some people who want to start moving everything into Annotations. I just get a really bad feeling in my gut (code smell?) when I see a class that has methods like this: (just an example - not all real annotations)
#Transaction
#Method("GET")
#PathElement("time")
#PathElement("date")
#Autowired
#Secure("ROLE_ADMIN")
public void manage(#Qualifier('time')int time) {
...
}
Am I just behind the times, or does this all seem like a horrible idea to anyone else? Rather then using OO concepts like inheritance and polymorphism everything is now by convention or through annotations. I just don't like it. Having to recompile all the code to change things that IMO are configuration seems wrong. But it seems to be the way everything (especially Spring) is going. Should I just "get over it" or should I push back and try to keep our code as annotation free as possible?
Actually I think that the bad feeling in your gut against has more to do with Annotations like this mixing configuration with code.
Personally I feel the same way as you do, I would prefer to leave configuration (such as transaction definitions, path elements, URLs that a controller should be mapped to, etc.) outside of the code base itself and in external Spring XML context files.
I think though that the correct approach here comes down to opinion and which method you prefer - I would predict that half the community would agree with the annotations approach and the other half would agree with the external configuration approach.
Maybe you have a problem with redundant annotations that are all over the code. With meta-annotations redundant annotations can be replaced and your annotations are at least DRY.
From the Spring Blog:
#Service
#Scope("request")
#Transactional(rollbackFor=Exception.class)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyService {
}
#MyService
public class RewardsService {
…
}
Because Java evolves so slowly people are putting more features that are missing in the language into annotations. This is a good thing Java can be extended in some form and this is a bad thing as most of the annotations are some workaround and add complexity.
I was also initially skeptical about annotations, but seeing them in use, they can be a great thing. They can also be over used.
The main thing to remember about annotations is that they are static. They cannot change at runtime. Any other configuration method (xml, self-description in code, whatever) does not suffer from this. I have seen people here on SO have issues with Spring in terms of having a test environment on injecting test configurations, and having to drop down to XML to get it done.
XML isn't polymorphic, inherited or anything else either, so it is not a step backwards in that sense.
The advantage of annotations is that it can give you more static checking on your configuration and can avoid a lot of verbosity and coordination difficulties in the XML configurations (basically keeping things DRY).
Just like XML was, Annotations can be over used. The main point is to balance the needs and advantages of each. Annotations, to the degree that they give you less verbose and DRYer code, are a tool to be leveraged.
EDIT: Regarding the comment about an annotation replacing an interface or abstract class, I think that can be reasonable at the framework boundary. In a framework intended to be used by hundreds, if not thousands of projects, having an interface or base class can really crimp things (especially a base class, although if you can do it with annotations, there is no reason you couldn't do it with a regular interface.
Consider JUnit4. Before, you had to extends a base class that had a setup and tear down method. For my point, it doesn't really matter if those had been on an interface or in a base class. Now I have a completely separate project with its own inheritance hierarchy, and they all have to honor this method. First of all, they can't have their own conflicting method names (not a big deal in a testing framework, but you get my point). Second of all you have have the chain of calling super all the way down, because all methods must be coupled.
Now with JUnit4, you can have different #Before methods in different classes in the hierarchy and they can be independent of each other. There is no equally DRY way to accomplish this without annotations.
From the point of view of the developers of JUnit, it is a disaster. Much better to have a defined type that you can call setUp and teardown on. But a framework doesn't exist for the convenience of the framework developer, it exists for the convenience of the framework user.
All of this applies if your code doesn't need to care about the type (that is, in your example, nothing would every really use a Controller type anyway). Then you could even say that implementing the framework's interface is more leaky than putting on an annotation.
If, however, you are going to be writing code to read that annotation in your own project, run far away.
It's 2018 and this point is still relevant.
My biggest problem with annotations is that you don't have an idea what the annotations are doing. You're cutting some caller code off and hiding it somewhere disconnected from the callee.
Annotations were introduced to make the language more declarative and less programmatic. But if you're moving the majority of the functionality to annotations, you are effectively switching your code to a different language (and not a very good one at that). There's very little compile-time checking. This article makes the same point: https://blog.softwaremill.com/the-case-against-annotations-4b2fb170ed67
The whole heuristic of "move everything to configuration so that people don't have to learn how to code" has gotten out of control. Engineering managers aren't thinking.
Exceptions:
JUnit
JAX-RS
I personally feel that annotations have taken over too much and have blown up from their original and super useful purpose (e.g., minor things like indicating overridden method) into this crazy metaprogramming tool. I don't feel the JAva mechanism is robust enough to handle these clusters of annotations preceding each method.
For instance, I'm fighting with JUnit annotations these days because they restrict me in ways that I don't like
That being said, in my experience the XML based configuration isn't pretty either. So to quote South Park, you're choosing between a giant douche and a t*rd sandwich.
I think that the main decision you have to make is whether you are more comfortable with having a delocalization of the spring configuration (i.e., maintain two files instead of one), and whether you use tools or IDE plugins that benefit from the annotations. Another important question is whether the developers who will use or maintain your code truly understand annotations.
Like many things, there are pros and cons. In my opinion, some annotations are fine, though sometimes it feels like there is a tendency to overuse annotations when a plain old function calling approach might be superior, and taken as a whole, this can unintentionally increase cognitive load because they increase the number of ways to "do stuff."
Let me explain. For example, I'm glad you mentioned the #Transactional annotation. Most Spring developers probably are going to know about and use #Transactional. But how many of those developers know how #Transactional actually works? And would they know off the top of their head how to create and manage a transaction without using the #Transactional annotation? Using #Transactional makes it easier for me to use transactions in a majority of cases, but in particular cases when I need more fine-grained control over a transaction, it hides those details from me. So in a way it is a double edged sword.
Another example is #Profile in Spring config classes. In the general case, it makes it easier to specify which profiles you want a Spring component loaded in. However, it if you need more powerful logic than just specifying a list of profiles for which you want the component loaded, you would have to get the Environment object yourself and write a function to do this. Again, most Spring developers would probably be familiar with #Profile, but the side effect of that is they become less familiar with the details of how it works, like the Environment.acceptsProfiles(String... profiles) function, for instance.
Finally, when annotations don't work, it can be harder to understand why and you can't just put a breakpoint on the annotation. (For instance, if you forgot the #EnableTransactionManagement on your config, what would happen?) You have to find the annotation processor and debug that. With a function calling approach, you can of course just put a breakpoint in the function.
Annotations have to be used sparingly. They are good for some but not for all. At least the xml configuration approach keeps the config in one file (or multiple) instead of spread all over the place. That would introduce (as I like to call it) crappy code organization. You will never see the full picture of the configuration if it is spread across hundreds of files.
Annotations often introduce dependencies where such dependencies do not belong.
I have a class which happens by coincidence to have properties which resemble the attributes from a table in an RDBMS schema. The class was created with this mapping in mind. There is clearly a relationship between the class and the table but I am happy to keep the class free from any metadata declaring that relationship. Is it right that this class makes a reference to a table and its columns in a completely different system? I certainly don't object to external metadata that associates the two and leaves each free of an understanding of the other. What did I gain? It is not as if metadata in the source code provides type safety or mapping conformance. Any verification tool that could analyze JPA annotations could equally well analyze hibernate mapping files. Annotations did not help.
At one contract, I had created a maven module with a package of implementations of interfaces from an existing package. It is unfortunate that this new package was one of many directories within a monolithic build; I saw it as something separate from the other code. Nonetheless, the team was using classpath scanning so I had to use annotations in order to get my component wired into the system. Here I did not desire centralized configuration; I simply wanted external configuration. XML configuration was not perfect because it conflated dependency wiring with component instantiation. Given that Rod Johnson didn't believe in component based development, this was fair. Nonetheless, I felt once again that annotations did not help me.
Let's contrast this with something that doesn't bother me: TestNG and JUnit tests. I use annotations here because I write this test knowing that I am using either TestNG or JUnit. If I replace one for the other, I understand that I will have to perform a costly transition that will stray close to a rewrite of the tests.
For whatever reason, I accept that TestNG, JUnit, QUnit, unittest, and NUnit owns my test classes. Under no circumstances does either JPA or Hibernate own those domain classes which happen to get mapped to tables. Under no circumstances does Spring own my services. I control my logical and physical packaging in order to isolate units which depend upon either. I want to ensure that a move away from one doesn't leave me crippled because of all the dependencies it left behind. Saying goodbye is always easier than leaving. At some point, leaving is necessary.
Check these answers to similar questions
What are the Pros/Cons of Annotations (non-compiler) compared to xml config files
Xml configuration versus Annotation based configuration
Basically it boils down to: Use both. Both of them have there usecases. Don't use annotations for things which should remain configurable without recompiling everything (especially things which maybe your user should be able to configure without needing you to recompile all)
I think it depends to some extent on when you started programming. Personally, I think they are horrid. Primarily because they have some quasi-'meaning' which you will not understand unless you happen to be aware of the annotation in question. As such they form a new programming language all by themselves and move you further away from POJOs. Compared to (say) plain old OO code. Second reason - they can prevent the compiler doing your work for you. If I have a large code base and want to refactor something or rename something I'd ideally like the compiler to throw up everything that needs to be changed, or as much as possible. An annotation should just be that. An annotation. Not central to the behaviour of your code. They were designed originally to be optionally omitted upon compilation which tells you all you need to know.
And yes, I am aware that XML config suffers in the same way. That doesn't make it worse, just equally bad. At least I can pretend to ignore that though - it doesn't stare me in the face in every single method or parameter declaration.
Given the choice I'd actually prefer the horrible old J2EE remote/home interfaces etc (so criticised by the Spring folks originally) as at least that gives me an idea of whats happening without having to research #CoolAidFrameworkThingy and its foibles.
One of the problems with the framework folks is that they need to tie you to their framework in order to make the whole enterprise financially viable. This is at odds with designing a framework well (i.e. for it to be as independant and removeable from your code as possible).
Unfortunately, though, annotations are trendy. So you will have a hard time preventing your team using them unless you are into code reviews/standards and the like (also, out of fashion!)
I read that Stroustup left annotations out of C++ as he feared they would be mis-used. Sometimes things go in the wrong direction for decades, but you can hope things will come full circle in time..
I think annotations are good if they are used with measure. Annotations like #WebService do a lot of work at deployment and run time, but they don't interfere in the class. #Cachexxx or #Transactional clearly interfere by creating proxies and a lot of artifacts, but I think they are under control.
Thing begin to mess when using Hibernate or JPA with annotations and CDI. Annotations grow a lot.
IMO #Service and #Repository are interferences of Spring in your application code. They make your application Spring dependant and only for Spring use.
The case of Spring Data Graph is another story. #NodeEntity, for instance, add methods to the class at build time to save the domain object. Unless you have Eclipse and Spring plugin you will errors because those methods don't exist in source code.
Configuration near the object has its benefits, but also a single configuration point. Annotations are good with measure, but they aren't good for everything, and definitively bad when there are as much annotation lines as source code lines.
I think the path Spring is going is wrong; mainly because in some cases there is no other way to do such funny things. It's is as if Spring wants to do xtreme coding, and at the same time they lock developers into Spring framework. Probably Java language needs another way to do some things.
Annotations are plain bad in my experience:
Inability to enforce type safety in annotations
Serialization issues
Cross compiling (to for instance javascript) can be an issue.
Libraries/frameworks requiring annotations exclude non-annotated classes from external libraries.
not overridable or interchangeable
your projects eventually becomes strongly dependant on the system that requires the annotations
If Java would have something like "method literals" you could annotate a class in a corresponding annotation class.
Something like as following:
Take for instance javax.persistence, and the following annotated class:
#Entity
class Person
{
#Column
private String firstname;
public String getFirstname() { return firstname; }
public void setFirstname(String value) { firstname = value; }
#Column
private String surname;
public String getSurname() { return surname; }
public void setSurname(String value) { surname = value; }
}
Instead of the annotations, I'd suggest a mapping class like:
class PersonEntity extends Entity<Person> {
#Override
public Class<Person> getEntityClass() { return Person.class;}
#Override
public Collection<PersistentProperty> getPersistentProperties() {
LinkedList<PersistentProperty> result = new LinkedList<>();
result.add(new PersistentProperty<Person>(Person#getFirstname, Person#setFirstname);
result.add(new PersistentProperty<Person>(Person#getSurname, Person#setSurname);
return result;
}
}
The fictional "#" sign in this pseudo java code represents a method literal, which, when invoked on an instance of the given class, invokes the corresponding delegate (signed with "::" since java 8) of that instance.
The "PersistentProperty" class should be able to enforce the method literals to be referring to the given generic argument, in this case the class Person.
This way, you have more benefits than annotations can deliver (like subclassing your 'annotate'-class) and you have none of the aforementioned cons.
You can have more domain-specific approaches too.
The only pre annotations have over this, is that with annotations you can quickly see whether you have forgotten to include a property/method. But this too can be handled more concise and more correct with better metadata support in Java (think for instance of something like required/optional like in Protocolbuffers)

Categories