#DeclareParents annotation in Introductions in Aspect Oriented Programming - java

I am doing Spring Aspect Oriented Programming with annotations in Java. I have an Aspect LogAOP:
#Aspect
public class LogAOP {
#DeclareParents(value="beans.service.*+", //Line 1
defaultImpl= EventImpl.class)
public static Event mixin;
#Before("com.beans.business.businessService() &&" +
"this(abc)")
public void usage(Event abc) {
abc.increment();
}
}
I am not able to understand the significance of '+' symbol in Line 1 in value attribute of #DeclareParents annotation.
Beacuse even if I remove this + symbol, the program is running fine. I have also searched in official documentation of Spring AOP (http://docs.spring.io/spring/docs/2.5.4/reference/aop.html) , nothing is mentioned there.

Using + after a class name or interface name is used to match that class or interface, and all it's subclasses. So, the pointcut expression in this case:
#DeclareParents(value="beans.service.*+", //Line 1
defaultImpl= EventImpl.class)
public static Event mixin;
...will match any interfaces or class defined in package beans.service, and also any subclass or implementing class of those classes and interfaces. It may be needed because, the implementing classes might not be in the beans.service package. In your case, you're not seeing the effect because may be all your implementing classes are in the same package. Try implementing an interface in beans.service package, and put the implementing class in a different package. I guess, you'll see the difference then.

Related

Why can't classes that use EJB #Schedule be abstract Classes?

I need to schedule a task and I'm using EJB #Schedule to do so. It's working fine, however I thought I might try to generalize my design so that I can extend from some abstract scheduler, inherit certain functionality, and specify additional functionality in the sub classes extending the abstract class. This way, when I need additional schedulers that perform similar actions, I don't have to rewrite a bunch of code. I wrote it, didn't get any errors, and I thought all was well, and then when I tried to restart my server,
I got:
EJB class com.schedule.SubmissionScheduler must not be defined as abstract : mcftEAR#mcftWeb.war#SubmissionSchedule in the console.
Maybe I don't know enough about how the #Schedule annotation works, but I can't think of any reason abstract classes won't be allowed for this. Any insight would be appreciated
import java.util.List;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
public abstract class SubmissionScheduler {
public abstract SubmissionScheduler getInstance();
#Schedule(hour= "0")
public void every24Hours() {
// Pull all forms and submit every 24 hours
List<Form> forms = getFormsThatAreReadyForSubmission();
// Loop through the list of forms and submit
if (forms != null || !forms.isEmpty()) {
for (Form form : forms) {
form.getFormDao().submit());
}
}
}
...Then I have another class which extends this one.
EDIT: In addition to not being able to make it an abstract class, it won't allow for the class to be final either...Why??
Basically you need an instance of your bean to run any function - in your case scheduled function.
It is impossible to run a function from abstract class cause it's abstract - a container cannot create instance to run your code. So it have to be non abstract to create instance and run a method.

how to apply spring aop for legacy code by taking pointcut as input from user

I have to apply Spring AOP for legacy code without changing anything in the existing code. There is no bean concept and the objects are created using new keyword, so no scope of using applicationContext.getBean("beanName"). Also the pointcuts will be taken as input from end user and there will be a common aspect class.
For eg.
package package1;
public class Demo1 {
public void method1()
{
System.out.println("From method1");
}
public void method2()
{
System.out.println("From method2");
}
}
package package2;
public class Demo2 {
public void method3()
{
System.out.println("From method3");
}
public void method4()
{
System.out.println("From method4");
}
}
package aspects;
public class SpringAspect {
public void beforeAdvice(JoinPoint jointPoint)
{
System.out.println("Before method : "+jointPoint.getSignature());
}
}
Pointcuts taken as input from end user are as follows and their before advisor method is beforeAdvice() from aspects.SpringAspect class :
execution(* package1.Demo1.method1(..))
execution(* package2.Demo2.method4(..))
Also if it is not possible using Spring AOP, how can I use AspectJ during runtime for the same.
First of all, your so-called aspect is missing aspect-related annotations such as #Aspect and #Before, without which it is just a POJO class. It will never be executed or even recognised as an aspect.
Second, Spring AOP is a proxy-based framework which only works in connection with Spring components, not with POJO classes. You need AspectJ in order to solve your problem. (Have you ever read a tutorial or the Spring or AspectJ manual, by the way? I guess you have not.)
Furthermore, why on earth would you want a user to enter pointcuts during runtime? Should you not know where to apply your aspects a bit earlier? Even if I would show you a solution creating aspects on the fly, they would not be very valuable because even load-time weaving needs to instrument your Java code during class-loading. If the target classes are already loaded, there is no way to apply aspects on them post factum.
Maybe you should explain what you want to achieve and not ask how to do something technically which does not make sense and will not work, thus not solve your problem anyway.
If you want a more dynamic way to define your pointcuts other than hard-coding them within your aspects, you can create an abstract base aspect with an abstract pointcut and define the concrete pointcut in an aop.xml file which is used for load-time weaving, as described in the AspectJ documentation.

Java - Using two classes with the same name in an Interface

I need to use two classes with the same name but different namespaces (foo.request.Response and bar.request.Response) in an interface. In classes this can be achieved by using the full name with namespace :
public foo.request.Response method1() { [...]
public bar.request.Response method2() { [...]
But this does not seem to work in Interfaces.
What is the correct way of dealing with this problem ?
Edit 1
Error comes from Eclipse :
foo cannot be resolved to a type
Interface code :
public interface ITestController {
String method1(foo.request.Response response);
}
I found the issue, it was not coming from the interface it was a simple mess-up in the dependencies. Thanks for your help ;)
It works in interfaces, but care should be taken so that the implementing classes fully qualify the names in the same way.
Note that you can not choose which of the two classes when implement the interface. It's the interface that specifies which of the two classes is to be used when implementing the interface.
The code you've posted in your answer is messed up. If the two first methods belong to a class implementing ITestController then that class must also include an implementation for
public String method1(foo.request.Response response) { ... }

Configuration class - best practice with Guice

Background: I'm using Google Guice and so it's easier to pass through the configuration class but I think this is not the best way.
I have a configuration class which stores some paths:
class Configuration{
String getHomePath();
String getUserPath();
}
Also I have a class "a" which needs the "homepath" and a class "b" which needs the "userpath".
Is it better to pass the configuration class through the constructor of class a and b or only pass through the specific path?
If you're really using Guice correctly all your configuration like this should appear in modules' configure method. So:
Remove the configuration class.
Create annotation classes, probably called HomePath and UserPath.
Where class a uses getHomePath() replace that with a String field member named homePath.
Where class b uses getUserPath() replace that with a String field member named userPath.
Modify the class a and b constructors to be #Inject annotated (should already be) and take in a String parameter, respectively annotated with #HomePath and #UserPath and assign the String field member that injected value.
Create bindings in your module's configure method use .annotatedWith() which define correct values; if they're only available at run time, bind a provider.
E.G.
class a {
private String homePath;
#Inject
public a(#HomePath String homePath) {
this.homePath = homePath;
}
public String tellMeAboutHome() {
return "We live in a nice home called " + homePath;
}
}
class customModule extends AbstractModule {
public static final String userPath = "/home/rafael";
public void configure() {
bind(String.class).annotatedWith(HomePath.class).to("/home/");
bind(String.class).annotatedWith(UserPath.class).to(userPath);
}
}
If creating annotations is too much work for you, use the #Named annotation Guice ships with.
There's no single answer to your question, there are only options to choose from, based on your specific situation.
If you know your Configuration class is going to grow AND if it's likely for your A and B classes will use more from it, then pass the whole Configuration object to their constructors. NB: I know this is against the YAGNI principle but sometimes you may know you're gonna need it ;-)
Otherwise, you can consider using #Named injection of your paths so that you reduce A and B classes dependencies to their minimum, which is a good design practice.
The general rule is code to make the dependency graph (which classes know about or depend on other classes/ interfaces) as simple, regular and fixed as possible.
If not passing the Configuration class makes a or b have zero dependencies on on user-written classes, or is necessary to avoid a dependency loop, then use the individual path strings. Otherwise, if it makes more sense to say 'this class has access to configuration info, in a way that may change in the future', pass the class.
I'd avoid the singleton approach, especially if you already have Guice set up.

Java - Register all classes annotated with #MyAnnotation

I have an annotation #MyAnnotation and I can annotate any type (class) with it. Then I have a class called AnnotatedClassRegister and I would like it to register all classes annotated with #MyAnnotation so I can access them later. And I'd like to register these classes automatically upon creation of the AnnotatedClassRegister if possible, and most importantly before the annotated classes are instantiated.
I have AspectJ and Guice at my disposal. The only solution I came up with so far is to use Guice to inject a singleton instance of the AnnotatedClassRegister to an aspect, which searches for all classes annotated with #MyAnnotation and it adds the code needed to register such class in its constructor. The downside of this solution is that I need to instantiate every annotated class in order for the code added by AOP to be actually run, therefore I cannot utilize lazy instantiation of these classes.
Simplified pseudo-code example of my solution:
// This is the class where annotated types are registered
public class AnnotatedClassRegister {
public void registerClass(Class<?> clz) {
...
}
}
// This is the aspect which adds registration code to constructors of annotated
// classes
public aspect AutomaticRegistrationAspect {
#Inject
AnnotatedClassRegister register;
pointcutWhichPicksConstructorsOfAnnotatedClasses(Object annotatedType) :
execution(/* Pointcut definition */) && args(this)
after(Object annotatedType) :
pointcutWhichPicksConstructorsOfAnnotatedClasses(annotatedType) {
// registering the class of object whose constructor was picked
// by the pointcut
register.registerClass(annotatedType.getClass())
}
}
What approach should I use to address this problem? Is there any simple way to get all such annotated classes in classpath via reflection so I wouldn't need to use AOP at all? Or any other solution?
Any ideas are much appreciated, thanks!
It's possible:
Get all paths in a classpath. Parse System.getProperties().getProperty("java.class.path", null) to get all paths.
Use ClassLoader.getResources(path) to get all resources and check for classes: http://snippets.dzone.com/posts/show/4831
It isn't simple that much is sure, but I'd do it in a Pure Java way:
Get your application's Jar location from the classpath
Create a JarFile object with this location, iterate over the entries
for every entry that ends with .class do a Class.forName() to get the Class object
read the annotation by reflection. If it's present, store the class in a List or Set
Aspects won't help you there, because aspects only work on code that's actually executed.
But annotation processing may be an Option, create a Processor that records all annotated classes and creates a class that provides a List of these classes
Well, if your AnnotatedClassRegister.registerClass() doesn't have to be called immediately at AnnotatedClassRegister creation time, but it could wait until a class is first instantiated, then I would consider using a Guice TypeListener, registered with a Matcher that checks if a class is annotated with #MyAnnotation.
That way, you don't need to search for all those classes, they will be registered just before being used. Note that this will work only for classes that get instantiated by Guice.
I would use the staticinitialization() pointcut in AspectJ and amend classes to your register as they are loaded, like so:
after() : staticinitialization(#MyAnnotation *) {
register.registerClass(thisJoinPointStaticPart.getSignature().getDeclaringType());
}
Piece of cake, very simple and elegant.
You can use the ClassGraph package like so:
Java:
try (ScanResult scanResult = new ClassGraph().enableAnnotationInfo().scan()) {
for (ClassInfo classInfo = scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName()) {
System.out.println(String.format("classInfo = %s", classInfo.getName()));
}
}
Scala:
Using(new ClassGraph().enableAnnotationInfo.scan) { scanResult =>
for (classInfo <- scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName).asScala) {
println(s"classInfo = ${classInfo.getName}")
}
}

Categories

Resources