views:

90

answers:

4

In the service layer I have a classes that look something like:

class MyService {
    public doSomething() {
        TelnetSession session = new TelnetSession();
        session.open("username", "password");
        session.execute("blah");
        session.close();
    }
}

In many classes I have to declare and open session and then at the end close it. I'd rather do something with annotations but I've got no idea where to start. How do other people do something like this:

class MyService {
    @TelnetTransaction
    public doSomething() {
        session.execute("blah");
    }
}

where a method annotated with @TelnetTransaction instantiates, opens and passes in the TelnetSession object.

Thanks,

James

+8  A: 

Before and after is what aspect oriented programming is for.

Spring handles transactions with aspects. Give Spring AOP or AspectJ a look.

duffymo
And, if you want to homegrow it yourself, lookup the Proxy Pattern.
BalusC
+1  A: 

Unless you are doing something ropey, you want to end up with an object that delegates to a service object, with the execute around. There is no reason for both types to implement exactly the same interface, and good reasons why they should not. There are a number of ways of ending up with this:

  • Just do it by hand. I suggest always starting off like this before hitting code generation.
  • Use a dynamic proxy. Unfortunately java.lang.reflect.Proxy requires you to add an interface.
  • Use APT (or at least the annotation processing facilities in 1.6 javac) to generate the code. Java source is easier than bytecode, but I don't know of any good libraries for Java source code generation.
  • Use the Execute Around idiom by hand - verbose and clumsy.
Tom Hawtin - tackline
Java source code generation with APT is a very advanced topic, especially if you want to modify existing classes (I know, I did it recently and it gave me quite a struggle, you need to struggle with tons of undocumented internal javac calls). I'd suggest proxy or AOP (proxy is AOP of sorts also)
seanizer
@seanizer Modifying existing classes with apt is, well, wrong.
Tom Hawtin - tackline
I know that's the official wording, but it's what makes great technologies like Project Lombok possible. But you suggested it here yourself. How should he implement this functionality using APT without modifying existing classes?
seanizer
@seanizer To be clear, Project Lombok is a complete and utter hack, IMO. The idea is to always create a new class that delegates to the original. Client code will use the generated class (which will be the API), the generated class then uses the implementation class (the SPI).
Tom Hawtin - tackline
@Tom a) that approach makes sense, I guess. b) I know Lombok is a hack but it's a great hack c) in my recent case that wouldn't have been an option because I was extending wicket components and there is a rigid hierarchy that prevents such delegation. Read here for info if you want: http://stackoverflow.com/questions/3652463/aop-or-apt-for-overriding-methods-from-super-classes
seanizer
+1  A: 

As duffymo says, AOP is the way to go. I'd suggest you to get a copy of

AspectJ in Action

It is written by Ramnivas Laddad, a Spring Committer, and it covers both Spring AOP and "real" AspectJ thoroughly and understandably.

For developing you should use the AspectJ Developer Tools for Eclipse or better yet, the SpringSource Tool Suite (it contains AJDT).

seanizer
A: 

Spring AOP will be your best bet if you are already using that. If you need runtime injection, you would need to use AspectJ. I remember reading Spring does not support that kind of injection

mezzie
You don't need byte code manipulation to do before and after AOP calls.
duffymo
@duffymo Exactly. Spring AOP matches method executions on spring beans as the only supported pointcuts (AspectJ supports many more). But these pointcuts can be targeted by `before`, `after` (several kinds) and `around` advices. Restricting to this kind of pointcut gives spring the option to use either JDK proxies or dynamic subclassing using CGLib. And if you want additional pointcuts, you need static AspectJ compilation or load time weaving.
seanizer