Is there a way to add specific condition to method with annotation? - java

I have a method and I want to add some condition to this method.
If condition is true then execute this method, if its not then skip this method. Like;
#SomeConditionAnnotation(check)
public void calculate(){
//some calculations
}
public boolean check(){
//return boolean
}
What I really try to do is;
public void calculate(){
if(check()){
//some calculations
}
}

I think, you should use plain old "if-else", not annotation. So, you write
If condition is true then execute this method, if its not then skip this method.
But it's description of if operator!
Here is purpose of annotations:
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
link

What you describe can be done using an interceptor or decorator. You can use CDI (part of Java EE, but also usable standalone) or aspectj or Spring AOP or ... There exist lots of frameworks which support aspect oriented programming.

Related

Write annotation to guard a method from being called when parameters are invalid

Can I have an annotation for a method that when its parameters are null, just do nothing, effectively as not being invoked?
Probably the easiest way to do this is using interfaces and dynamic proxies. Annotations do nothing other than add metadata. You're going to have to add code to act based on the annotation.
You'd have to do a few things --
Create an interface
public interface IService {
#ValidateNull // Your custom annotation
public void yourMethod(String s1);
}
When using the implementation, instantiate it as a JDK Proxy.
IService myService = (IService)java.lang.Proxy.newInstance(ServiceImpl.class.getClassLoader(),
ServiceImpl.class.getInterfaces(),
new YourProxy(new ServiceImpl());
Now, you can via reflection, capture all invocations of your method in YourProxy class.
public YourProxy implements InvocationHandler {
public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
if (method.isAnnotationPresent(ValidateNull.class)) {
//Check args if they are null and return.
}
}
}
If you dont want to do this, then you're looking at more heavyweight frameworks such as AspectJ / Spring AOP.
Annotations in and of themselves are nothing but data. They don't "do" anything. There are a number of different ways you can have a run time framework that interprets annotations and accomplishes the functionality you're looking for. The most common technique would be what's called Aspect Oriented Programming, where you alter the behaviour of program components based on metadata.
aspectJ is a full featured library that allows you to change the behaviour of just about anything! You wouldn't even technically need an annotation will full aspectJ, there are lots of different ways to 'match' methods that you want to alter the behaviour of.
SpringAOP is a more limited subset of the functionality provided by aspectJ, but it is also easier to use and add to your project as a consequence!

Looking for simple recipe for Java Annotation

I've never written an annotation in Java.
I've got a simple Java class for performance measurement. I call it PerfLog. Here's an example of its use:
public class MyClassToTest {
public String MyMethod() {
PerfLog p = new PerfLog("MyClassToTest", "MyMethod");
try {
// All the code that I want to time.
return whatever;
} finally {
p.stop();
}
}
}
When p.stop() is called, a line will be written to the log file:
2010/10/29T14:30:00.00 MyClassToTest MyMethod elapsed time: 00:00:00.0105
Can PerfLog be rewritten as an Annotation so that I can write this instead?
public class MyClassToTest {
#PerfLog
public String MyMethod() {
// All the code I want to time.
return whatever;
}
}
It would seem to be a good candidate for annotating: It's easy to add or take away the annotation; a production build can leave out PerfLog entirely without having to remove the annotations from the source code; the annotation processor can get the class and method names.
Is this easy to do? Is there a recipe somethere that I can follow?
It has to be Java 5 so I know I have to use apt somewhere.
There is no trivial way to do this using standard Java tools. The path of least resistance would almost certainly be to use an AOP-style library like Google Guice or Spring or AspectJ. Any home-grown attempt to solve this problem will essentially end up doing what AOP libraries would already do for you.
Consider using AOP or Spring - supports Annotations to intercept method invocations and implement custom code
In case that sounds interesting, the Spring AOP docs are here : http://static.springsource.org/spring/docs/2.5.x/reference/aop.html
You can definitely write the annotation parser and its runtime implementation on your own, but reinventing will only be error prone and inefficient when compared to industry solutions.
If you insist on implementing this on your own (without AOP or AOP with Spring), here is what I can suggest (may not be the bestest method) :
Create your beans via a custom FactoryBean always.
In the custom FactoryBean implementation, query the class for methods and check if they are annotated.
If yes, instead of returning the instance of the class itself, return a proxy over the instance.
In the invoke of this proxy, wrap the call to the actual instance's method with new PerfLog() and p.stop()
Its effectively what AOP would (more powerfully) do for you. However, take note that final classes, static methods, classes with no interfaces etc.. will still be a problem in this case (a different ball game).

Is it possible to set a default behaviour for custom (non-native) methods/functions in Java?

Is it possible to set a default behaviour for custom (non-native) methods/functions in Java?
For example, I would like to change the default "Function" to do a System.out.println("message") whenever called.
So, when a custom method/function is being created:
public String testMethod()
{
//custom code
}
it should execute the newly added default behaviour (in this case the system output), before the custom code is run.
Even if this would be a bad excercise, is it possible? Maybe by extending the function class or something?
One way is using Aspect-oriented programming (AOP) for Java: Aspect/J. For what you want, AOP would let you inject code in your program at specific points, e.g. having specified methods execute some println code upon entering or exiting the method. [AOP has a much larger purpose than this simple use for printing debug statements, but I'm trying to stay on target for answering the question.]
This article (possibly somewhat dated) shows an example similar to what you want:
http://www.developer.com/java/other/article.php/3109831/Simplify-your-logging-with-AspectJ.htm
It sounds like you want either aspect-oriented programming (e.g., AspectJ) or byte-code weaving (e.g., ASM or cglib).
Maybe, you should look at java.reflect.Proxy.But it requires that you create one proxy per class for which you want to monitor method calls.
An example :
#SuppressWarnings("unchecked")
public static <T> List<T> traceList(final List<T> list) {
return (List<T>)Proxy.newProxyInstance(
ProxyTest.class.getClassLoader(),
new Class<?>[]{List.class},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("enter "+method);
try {
return method.invoke(list,args);
} finally {
System.out.println("exit "+method);
}
}
});
}
If you only need to do this for your own classes and not for classes from the Java library or that you get from someone else, then this is what Object-Oriented Programming is all about. Create your top level class, put this function in it, and then derive any other classes from there.

How can I run a function before current function using annotations?

Is there any way for using an annotation for running a function before currently called function, something like this:
public void doSomethingEarlier() {
}
#DoSomethingEarlier
public void doSomething() {
}
So I want to call doSomethin() function, and before executing this function I want to automatically run doSomethingEarlier() function.
You have a number of ways, which are a bit difficult to implement:
use Proxy where you can parse the annotation on the target method and invoke a method with the same name
use AOP
The first approach is more straightforward. It would probably be better to have the annotation look something like:
#BeforeMethod("methodName")
In general, this is how AOP works on the low level.
See Spring Aspect Oriented Programming.
Java won't do this for you. Someone else: you or some library: has to see the annotation and adjust the call process.
Yes, you can use annotations for that. You have to create your own #DoSomethingEarlier annotation (with run-time retention), and you have to code your own annotation processor processor. It is not an easy proposition, and you might want to look for other alternatives like AOP or dynamic proxies (which might not be easy either.)
This is easier...
public void doSomethingEarlier() {
}
public void doSomething() {
doSomethingEarlier();
}

How do I intercept a method invocation with standard java features (no AspectJ etc)?

I want to intercept all method invocations to some class MyClass to be able to react on some setter-invocations.
I tried to use dynamic proxies, but as far as I know, this only works for classes implementing some interface. But MyClass does not have such an interface.
Is there any other way, besides implementing a wrapper class, that delegates all invocations to a member, which is an instance of the MyClass or besided using AOP?
As you note, you cannot use JDK dynamic proxies (no interface), but using Spring and CGLIB (JAR included with Spring), you can do the following:
public class Foo
{
public void setBar()
{
throw new UnsupportedOperationException("should not go here");
}
public void redirected()
{
System.out.println("Yiha");
}
}
Foo foo = new Foo();
ProxyFactory pf = new ProxyFactory(foo);
pf.addAdvice(new MethodInterceptor()
{
public Object invoke(MethodInvocation mi) throws Throwable
{
if (mi.getMethod().getName().startsWith("set"))
{
Method redirect = mi.getThis().getClass().getMethod("redirected");
redirect.invoke(mi.getThis());
}
return null;
}
});
Foo proxy = (Foo) pf.getProxy();
proxy.setBar(); // prints "Yiha"
If you are prepared to do something really ugly, have a look at:
http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/
Basically the debugger interface ought to allow you to attach like a debugger, and hence intercept calls. Bear in mind I think this is a really bad idea, but you asked if it was possible.
Java doesn't have any actual language features for method interception (not sure any static language does)
I kinda like Nick's idea of using the debugger interface, that's just mean.
I think the short answer you need is: No there isn't a way of intercepting a method call in Java without actually replacing the class using a proxy or wrapper.
Note: The AOP libraries just make this happen automatically.
Some of the Java gurus might frown upon this but I've had some good success with avoiding primitive types and setters altogether. My class looks like this:
class Employee extends SmartPojo {
public SmartString name;
public SmartInt age;
}
You'll notice two things: 1. everything is public. 2. No constructor.
The magic happens in SmartPojo which searches for any field which implements the "Smart" interface and initializes it. Since this is no primitive (and no final class), I can add set() and get() methods for all fields anywhere in my model in a single place. So no setter/getter wastes anymore, it's stunningly simple to add notification (also in a single place), etc.
True, this is no POJO anymore and it's not a Bean in most ways but I've found that these old ideas limit me more than they help. YMMV.
I just developed a small framework for this purpose.
You can check it out at: http://code.google.com/p/java-interceptor/ (use svn to check out).
There isn't a lot of magic in AspectJ. You can write your own agent. http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html seems to be good starting point.
Why cannot your class implement an interface? You could just extract some interface from it containing all the methods that you want to intercept and use the dynamic proxies mechanism easily. It's also a good programming practice to code with interfaces and not classes.
You could use Spring framework with Spring AOP capabilities (which are using dynamic proxies inside) to do it. You will just have to define your class as a Spring bean in the configuration file and clients of your class will have to either get its instance from the Spring application context or as a dependency automatically (by defining the setMyClass(MyClass mc) method for instance). From there you can easily go to defining an aspect that intercepts all the method calls to this class.

Categories

Resources