Thursday, December 13, 2007

Composite Annotation

In the creation time of AOP, I realized that java annotation is too weak to use.
Java annotation does not extend or implement, it is irritated me so much
because I see there are much more and more annotation at java programming.


So the idea has come to my thoughts.
We can not extend annotation by annotation, but we can do pretend that
there is composited annotation, offcourse with Lucy.

It is where @Composite is used for:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Composite
@Component
@Singleton
public @interface SingletonComponent {

}



With the example above, @SingletonComponent has two meanings.
1.This is pretend to be @Component
2.This is pretend to be @Singleton

How to pretend?
This is @Composite.

@Composite gives you abbreviate multiple annotation meanings at just one annotaion.
How Lucy do this is when creating annotation meta class, AnnotationDesc,
the annotation which is put @Composite treats as composited annotation that means
there are multiple annotations to make meta class.If so, Lucy analyzes all annotations from
child to parent, and makes multiple annotation meta class.
I mention that Lucy simply does not make annotation meta class for java.lang type annotation and @Composite itself.

So, what gives you if using @Composite are:
-your code are much simpler to see. keep your code clean, baby:)
-it gives you to create so easily one simple annotation from multiple annotaions(isn't that good?)
-you can do customize of framework annotation meanings.

Wednesday, December 12, 2007

The next feature, AOP

Offcource, there are famous AOP framework with IoC.
Spring, JBoss AOP, Seasar2, well I know.



So how about Lucy?Is that any AOP features?
I can say it will be.

Lucy AOP is based on Javassist byte code enhancing.

It will be like this:

@Component
@Singleton
@Aspect(interceptBy = StringReplaceInterceptor.class, pointcut = "replace")
public class Aaa {

public String replace() {
return "aaa";
}
}


It points out Aaa is gonna be enhanced by StringReplaceInterceptor,
and also mentions that if method name is like "replace", by what?
By @Aspect.

@Aspect puts on class and method.
If you do like below:

@Component
@Singleton
@Aspect(interceptBy = StringReplaceInterceptor.class, pointcut = "replace")
public class Aaa {

@Aspect(interceptBy=AppendInterceptor.class)
public String replace() {
return "aaa";
}
}



if "replace" method invoked, StringReplaceInterceptor and AppendInterceptor are
gonna work.

What @Aspect looks like?
@Aspect has two methods, interceptBy and pointcut.
interceptBy() must be declared without any exception,
however, pointcut() is just optional.


@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.TYPE, ElementType.METHOD })
public @interface Aspect {

Class[] interceptBy();

String[] pointcut() default ".*";

}




So with design decision, we are not gonna use aop alliance provided jar.
Why? It is very simple. It is just useless and no one wants to use it.
There are some reasonable reasons to have MethodInvocation,
MethodInterceptor , but others, uhmmm,,,
there is no need to use it. So we simply do not use and make our Interceptor and Invocation.


So, where is StringReplaceInterceptor?
Calm down, here is StringReplaceInterceptor:

@Component
@Singleton
public class StringReplaceInterceptor implements Interceptor {

@Override
public Object intercept(Invocation invocation)
throws InvocationException {
return "bbb";
}

}



Interceptor is very much like AOP alliance Interceptor.
But we can add some good feature and also can consider much better architecure
and add feature when needed because we HAVE this code.


All component is managed by Lucy.
We hope we can provide good and simple AOP feature with Lucy.

Friday, December 7, 2007

multiple injection(single point injection)

Lucy enables multiple injection.

What is multiple injection?
Multiple injection is the way to inject components by one method.
Usually, IoC container supports one component injection by one method.

Look like this:


@Component
@Prototype
public class Client2 {

protected Randomizer randomizer;

public void execute() {
System.out.println(randomizer.getRandom());
}

@Inject
public void setRandomizer(Randomizer randomizer) {
this.randomizer = randomizer;
}
}



This is not bad, but when the situation to inject so many components,
it is not so good to see.


So, I made like this:


@Component
@Prototype
public class Client3 {

protected Add1 a1;

protected Add2 a2;

public int execute() {
return a1.get() + a2.get();
}

@Inject
public void setAll(Add1 a1, Add2 a2) {
this.a1 = a1;
this.a2 = a2;
}
}



This gives you single point injection,
which I prefer to use.

Almost all the IoC container looks like they recommend JavaBeans way,
one component injection per method, but it is skeptical to me it is better way.
If I would see Client2 and Client3 first, I would love to see latter one,
because I can see verrry well where Add1 and Add2 to be injected(are we saying it is visualization?).

Wednesday, December 5, 2007

Lucy - simplest IoC container -

Lucy is a simplest IoC container for Java developers.

There is Spring framework for IoC, I know.
There is Guice for IoC, I know.
There is Seasar2, which is popular in Japan, for IoC, I know.

But none of these is not what I want.
Spring is too comlicated to my brain.
(My brain accepts only easiest one:)

Guice, it sounds better to use, but i see Guice way is not the way i always recommend to use.
(If you are higher skill programmer, recommend to use.)

Seasar2, i don't say about it right now, maybe tommorow.


So I am creating a new one, called Lucy.


Here is a simple sample.


//just a interface
public interface Greeting {

String greet();
}

//Impl class. @Component must set to notify it is component.
//Also @Sinlgeton is singleton notification.(Scopes are singleton, prototype, but you can extend easily)
@Component
@Singleton
public class GreetingImpl implements Greeting {

private String name = "lucy";

public void setName(String name) {
this.name = name;
}

public String greet() {
return "Hello " + name;
}

}

//a client to use
@Component
@Prototype
public class Client {

protected Greeting greeting;

public void execute() {
System.out.println(greeting.greet());
}

//you must specify inject point.
@Inject
public void setGreeting(Greeting greeting) {
this.greeting = greeting;
}

}

//main class
public class Main2 {

public static void main(String[] args) {
Lucy.init();
final Registry registry = Lucy.getRegistry();
try {
registry.register(GreetingImpl.class);
registry.register(Client.class);
Client client = registry.get(Client.class);
client.execute();
} finally {
Lucy.destroy();
}
}
}



Verrrrrrrrrrry simple solution by annotation, as we see.
Our policy is
-small is beautiful

Small code is beautiful.
I know there are situations users want to add new feature.
But I will try to be small as much as I can beacuse small code is always good for developers.
If code is small, you can understand quickly and extend it quickly.
And maintainability is very high compared with large-footprint frameworks.

-no magic

There are no magic. IoC is a just technique, it is not magic.
So I realize auto injection is evil. You must specify injection point for maintainability.

See this code.


public class Hoge {

private Foo foo;

public void setFoo(Foo foo) {
this.foo = foo;
}

}


Ok, guess what Foo is injected to Hoge?
No body knows. There is no other information to know whether inject or not.

Let's see other example.


public class Hoge {

private Foo foo;

@Inject
public void setFoo(Foo foo) {
this.foo = foo;
}

}


Now you know the way:)
You see all the time whether Foo is injected or not.

-less is more

Less is more is always true to me.
Try to be less is so difficult, especially OSS.
But i try.Maybe i will write more detail why i love to pursue "less is more".