views:

53

answers:

2

For a rich domain driven design I want to use Guice dependency injection on JPA/Hibernate entity beans. I am looking for a similar solution as the Spring @configurable annotation for non-Spring beans.

Does anybody know of a library? Any code examples?

A: 

Since entities are created by the JPA provider, I fail to see when Guice will come in play. Maybe have a look at the approach of the Salve project though.

Pascal Thivent
Thanks, a codeweaving solution like Salve could really do the trick. I tried Salve, but it has limited documentation and I can’t get it to do anything (not even an error message). Just hoped for some simple sample code, for example with AspectJ or even better AOP.
Kdeveloper
@Kdeveloper: I don't have any experience with Salve so I can't recommend it but it might give you some ideas to implement something similar which is why I mentioned it
Pascal Thivent
+2  A: 

You can do this with AspectJ.

Create the @Configurable annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Configurable {
}

Create an AspectJ @Aspect similar to this:

@Aspect
public class ConfigurableInjectionAspect {
    private Logger log = Logger.getLogger(getClass().getName());

    @Pointcut("@within(Configurable) && execution(*.new(..)) && target(instantiated)")
    public void classToBeInjectedOnInstantiation(Object instantiated) {}

    @After(value = "classToBeInjectedOnInstantiation(instantiated)", 
           argNames = "instantiated")
    public void onInstantiation(Object instantiated) {
        Injector injector = InjectorHolder.getInjector();
        if (injector == null) {
            log.log(Level.WARNING, "Injector not available at this time");
        } else {
            injector.injectMembers(instantiated);
        }
    } 
}

Create (and use) a holding class for your injector:

public final class InjectorHolder {

    private static Injector injector;

    static void setInjector(Injector injector) {
        InjectorHolder.injector = injector;
    }

    public static Injector getInjector() {
        return injector;
    }
}

Configure META-INF/aop.xml:

<aspectj>
    <weaver options="-verbose">
        <include within="baz.domain..*"/>
        <include within="foo.bar.*"/>
    </weaver>
    <aspects>
        <aspect name="foo.bar.ConfigurableInjectionAspect"/>
    </aspects>
</aspectj>

Start your VM with aspectjweaver:

-javaagent:lib/aspectjweaver.jar

Annotate your domain classes:

@Entity
@Table(name = "Users")
@Configurable 
public class User {
    private String username;
    private String nickname;
    private String emailAddress;
    @Inject
    private transient UserRepository userRepository

    public User() {}
}
Craig