I'm trying to figure out the best practice for dealing with the following situation:
public class AppModule extends Module {
#Override
protected void configure() {
install(new JpaPersistModule("myJpaUnit").addFinder(Dao.class));
bind(MyJpaInitializer.class).asEagerSingleton();
}
#Provides
#IndicatesSomeConstantMap
#Singleton
Map<String, String> getMappings(Dao dao) {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
// Build map from Dao
return builder.build();
}
}
I need to inject #IndicatesSomeConstantMap in other classes. It seem the only way that getMappings can get the Dao is if I bind MyJpaInitializer as an EagerSingleton - which feels wrong. What's the preferred way of dealing with these hierarchical dependencies?
EDIT:
Based on the answer from #jeffcrowe I came up with something like:
public class Module1 extends PrivateModule {
#BindingAnnotation #Target({ FIELD, PARAMETER, METHOD }) #Retention(RUNTIME)
public #interface Jpa1{}
#Singleton
public static class JpaInitializer1 {
#Inject
public JpaInitializer1(#Jpa1 PersistService service) {
service.start();
}
}
public interface Finder1 {
#Finder(query="FROM Foo", returnAs = ArrayList.class)
List<Foo> getAll();
}
#Override
protected void configure() {
install(new JpaPersistModule("firstJpaUnit").addFinder(Finder1.class));
bind(JpaInitializer1.class);
}
#Provides
#Exposed
#Jpa1
PersistService getPersistService(Provider<PersistService> provider) {
return provider.get();
}
#Provides
#Exposed
#Jpa1
Finder1 getFinder(Finder1 finder, JpaInitializer1 init) {
return finder;
}
}
This handles the the dependency by wrapping it behind the provider and feels cleaner to me than using the eagerSingleton approach. This also hides the JpaModule behind a private module making it useful in a situation where multiple persistence modules are bound. The new problem is that since the Finder is already bound by the JpaPersistModule we have to add the #Jpa1 annotation to every injection of Finder1. Is there a way around that?
This is an interesting case. Normally in a scenario like this you could bind the initializer in normal Singleton scope and inject it into the Dao implementation, and this would ensure that it was done before the Dao was used. Due to the way the Jpa persistence modules are set up, there doesn't seem to be an easy way to add this dependency.
As the OP pointed out to me, JpaPersistModule is final, so we can't work around this by subclassing it. We can, however wrap the binder used to install the JpaPersistModule.
First wrap the binder in a proxy with an overridden the bind() method to intercept the EntityManager.class binding. (BinderProxy implements Binder and passes every call to the Binder given in it's constructor. Source available here)
new BinderProxy(binder()) {
#Override
public <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
if (clazz == EntityManager.class) {
return (AnnotatedBindingBuilder<T>) super.bind(clazz).annotatedWith(DefaultEntityManager.class);
} else {
return super.bind(clazz);
}
}
}.install(new JpaPersistModule("myJpaUnit"));
Then add a provides method to your module which ensures Jpa init before an EntityManager is used
#Provides EntityManager provideEm(MyJpaInitializer init, #DefaultEntityManager EntityManager em){
return em;
}
Related
I need to access to an instance provided via Guice #Provides, so i'm testing a way to access the #Provides Method via a Interceptor...but no way, the interceptor never distpaches.
Also i can't change Provider Method Signature , cause inherits from another class ....
public class MyModule extends AbstractModule{
public static class MyInterceptor implements MethodInterceptor{
#Override
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
System.out.println("MyModule ::: Intercepted#invoke! : "+ methodInvocation.getMethod().getName());
return methodInvocation.proceed();
}
}
#Provides
StampInterface getStamp(){
StampExampleImpl se = new StampExampleImpl();
se.setId("theID");
se.setTst(System.currentTimeMillis());
return se;
}
#Override
protected void configure() {
bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Provides.class),
new MyInterceptor());
}
public static void main(String... args) {
StampInterface s = Guice.createInjector(new MyModule()).getInstance(StampInterface.class);
System.out.println( s.getTst());
System.out.println("---------------------------");
}
}
Please check the limitations of guice aop as described here: https://github.com/google/guice/wiki/AOP#limitations
Instances must be created by Guice by an #Inject-annotated or no-argument constructor It is not possible to use method interception on instances that aren't constructed by Guice.
You are creating the StampExampleImpl yourself via "new" (doesn't matter that you do so inside a produces method). Thus guice does not know about it in regard to interception.
Quick fix: let guice create the impl instance for you:
#Provides
StampInterface getStamp(StampExampleImpl se){
se.setId("theID");
se.setTst(System.currentTimeMillis());
return se;
}
2nd Problem: why matching on "annotatedWith(Provides)"? You want to intercept the getTsd() method of your StampInterface, and that is not annotated. The annotation is on the producer method of your module, which is a different thing.
I am wondering what the difference is between using #provides on a method and using bind() in my guice modules.
I usually override AbstractModule.configure() and bind all my implementations to my interfaces like this:
public class MyModule extends AbstractModule
{
#Override
protected void configure()
{
this.bind(myIface.class).to(myIfaceImpl.class);
this.bind(myOtherIface.class).to(myOtherIfaceImpl.class).asEagerSingleton();
}
...
}
However, I have noticed a pattern in the codebase I'm currently working with where implementations aren't bound explicitly they are being returned from providers like this:
public class MyModule extends AbstractModule
{
#Provides
#Singleton
myIface iFaceProvider()
{
return new myIfaceImpl();
}
...
}
Is there a reason to prefer one over the other? Are there cases that force a particular method?
If you do
bind(MyInterface.class).to(MyImplementation.class)
Guice creates the instance for you. This enables certiain things like AOP. If you do
#Provides
MyInterface provideMyInterface() {
return new MyImplementation();
}
then Guice didn't create the instance so AOP won't work. Also, it requires an accessible constructor for MyImplementation. Generally, this form is only used when you can't edit MyImplementation to make it Guice-compatible.
There's a third form:
#Provides
MyInterface provideMyInterface(MyImplementation impl) {
return impl;
}
which is almost totally equivalent to the bind(...).to(...) form. It is commonly used in frameworks like Dagger that do not have the bind syntax.
I would like to create a class whose objects can be injected using the #Context annotation (or better yet a custom annotation for cases where I need to pass an argument to the annotation) into resource methods. In Jersey 1.* I would have used InjectableProvider (in my case together with AbstractHttpContextInjectable). What I'm trying to achieve is something like #Auth [1] from dropwizard (which uses Jersey 1.7).
The injection capabilities of Jersey were replaced by HK2 as far as I know and I could not find any example of what I'm describing.
Edit: See this question for further problems I have encountered while trying to follow Michal's guide.
You need to implement InjectionResolver<T> interface from HK2. Take a look at existing implementations that are present in Jersey workspace:
ContextInjectionResolver handling #Context
ParamInjectionResolver handling #PathParam, #QueryParam, ... (via it's subclasses)
AutowiredInjectResolver handling #Autowired
Once you have this, you need to extend AbstractBinder from HK2 and bind your InjectionResolver via it's #configure() method:
public class MyResolverBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<MyAnnotation>>() {})
.in(Singleton.class);
}
}
... and register an instance of this binder in your application class (or via feature):
Feature:
public class MyFeature implements Feature {
#Override
public boolean configure(final FeatureContext context) {
context.register(new MyResolverBinder());
return true;
}
}
register MyFeature into Application:
public class JaxRsApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(MyFeature.class);
// Register other providers or resources.
return classes;
}
}
register MyResolverBinder or Feature in the ResourceConfig
new ResourceConfig()
// Register either MyFeature
.register(MyFeature.class)
// or MyResolverBinder
.register(new MyResolverBinder())
// Register other providers or resources
.packages("my.package");
Providing an implementation of InjectionResolver only helps with injection, not when resolving values for the parameters of a resource method.
At least with Jersey 2.11, you need to define a ValueFactoryProvider annotated with #Provider.
#Provider
public class MyValueFactoryProvider implements ValueFactoryProvider {
#Inject
private MyFactory factory;
#Override
public Factory<?> getValueFactory(Parameter parameter) {
if (parameter.getAnnotation(MyAnnotationParam.class) != null) {
return factory;
}
return null;
}
#Override
public PriorityType getPriority() {
return Priority.NORMAL;
}
}
If you also want to get the value injected in, e.g., members and constructor parameters, then InjectionResolver works well.
I stumbled upon a case where the AOP proxy created by using #Cacheable breaks the dependency injection in Spring 3.1.1. Here is my scenario:
I have an interface and a class implementing this interface using #Cacheable at the implemented method.
Example interface:
public interface ImgService {
public byte[] getImage(String name);
}
Example implementation:
public class ImgServiceImpl implements ImgService {
#Cacheable(cacheName = "someCache")
public byte[] getImage(String name){//TODO};
protected String someOtherMethod(){//};
}
I also have to JUnit test classes - one which injects the interface and one the implementation:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" })
public class ImgServiceTest {
#Inject
private ImgService;
}
and
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" })
public class ImgServiceImplTest {
#Inject
private ImgServiceImpl;
}
Dependency injection for the interface works fine. However, when I get to injecting the implementation in the second test class I get an "Injection of autowired dependencies failed". I was able to debug it and it appears that ClassUtils.isAssignableValue() wrongly compares the desired type to the proxy class. It is called by DefaultListableBeanFactory. What is even stranger is that if I remove the #Cacheable annotation from the implemented method and add it to some other protected/private method, dependency injection works fine again. Is this a bug and what would be the correct approach to handle this situation?
It's not a bug, it's an expected side-effect of using JDK dynamic proxies for AOP implementation.
Since all calls to the cacheable method of ImgServiceImpl should go through the dynamic proxy of type ImgService, there is no way to inject this dependency into a field of type ImgServiceImpl.
When you move #Cacheable to private or protected method, injection works because #Cacheable doesn't take effect in this case - only public methods can be adviced using proxy-based AOP.
So, you should either declare fields to be injected as ImgService, or configure Spring to use target class-based proxies instead using proxy-target-class = "true".
Yet another option is to configure Spring to use AspectJ-based AOP implementation (requires compile-time or load-time weaving).
It's applicable to all AOP-based features provided by Spring (transactions, security, async execution, cache, custom aspects, etc).
See also:
7.6 Proxying mechanisms
OK, so here is the solution I came up finally. I implemented a simple method that attempts to extract the target object from the proxy based on its implementation of the org.springframework.aop.framework.Advised class:
#SuppressWarnings({"unchecked"})
public static <T> T getTargetObject(Object proxy, Class<T> targetClass) {
if (AopUtils.isJdkDynamicProxy(proxy)) {
try {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} catch (Exception e) {
return null;
}
} else {
return (T) proxy;
}
}
My implementation test class now looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" })
public class ImgServiceImplTest {
#Inject
private ImgService imgService;
private ImgServiceImpl imgServiceImpl;
#PostConstruct
public void setUp() {
imgServiceImpl = getTargetObject(imgService, ImgServiceImpl.class);
}
}
Is it possible to wrap generic injections in some way?
Given the interface:
interface IFoo<T>
In my guice module:
bind((Key<IFoo<SomeType>) Key.get(Types.newParameterizedType(IFoo.class, SomeType.class))).to(Foo.class);
But before I return the Foo instance I want to wrap it with this:
class FooWrapper<T> implements IFoo<T> { public FooWrapper(Foo<T> foo) { ... } }
Somewhere like this:
return new FooWrapper<T>(foo);
Here's one way you can do this:
public class FooModule extends PrivateModule {
#Retention(RUNTIME) #BindingAnnotation
private #interface Internal {}
#Override protected void configure() {
bind(new TypeLiteral<IFoo<SomeType>>(){}).annotatedWith(Internal.class)
.to(new TypeLiteral<Foo<SomeType>>(){});
}
#Provides #Exposed IFoo<SomeType> provideFoo(#Internal IFoo<SomeType> foo) {
return new FooWrapper<SomeType>(foo);
}
}
Another thing that might work well would be to add a general annotation like #Wrapped and then to declare FooWrapper's constructor like this:
#Inject public FooWrapper(#Wrapped IFoo<T> foo) { ... }
Then in your private module you could bind Foo annotated with #Wrapped and bind and expose FooWrapper normally, without needing to use an #Provides method.
There may well be better ways of doing this I haven't thought of yet. Do also keep in mind that method interception is often a good way of decorating interface implementations with other behavior as well.