deephacks
deephacks

Reputation: 151

Inject cached instances using cdi

I want expose instances managed by an external framework to CDI applications using @Inject. These instances must be provided this other framework since their lifecycle is based on various caching strategies.

Ex: same instance is visible within same thread scope, might live across many request scopes, session scope is not applicable. Seems I need to define a new scope targeting these kind of instances?

What is the best way to do this? An extension, is it possible with producer methods?

I almost got it to work with producer methods using the following:

@Inject
@CustomInject
FwObject obj;

@Produces
@CustomInject
FwObject createConfig(InjectionPoint p) {
  return (FwObject) ctx.get((Class<?>) p.getType());
}

But this force me to be explicit about the type produced which is not possible since there is no common framework interface.

Any help appreciated.

Upvotes: 2

Views: 1273

Answers (2)

deephacks
deephacks

Reputation: 151

I think I solved it by creating a custom scope. The following article was really helpful:

This is a very brief description of how I solved it.

Create custom scope annotation.

import javax.enterprise.context.NormalScope;
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@NormalScope
public @interface CustomScope {
}

Create custom context.

import javax.enterprise.context.spi.Context;
public class CustomContext implements Context {
  private MyFw myFw = .... ;

  @Override
  public Class<? extends Annotation> getScope() {
    return CustomScope.class;
  }
  @Override
  public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext) {
    Bean bean = (Bean) contextual;
    return (T) myFw.get(bean.getBeanClass());
  }
  @Override
  public <T> T get(Contextual<T> contextual) {
    Bean bean = (Bean) contextual;
    return (T) myFw.get(bean.getBeanClass());
  }
  @Override
  public boolean isActive() {
    return true;
  }
}

Create extension and register context.

import javax.enterprise.inject.spi.Extension;
public class CustomContextExtension implements Extension {
  public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager manager) {
    event.addContext(new CustomContext());
  }
}

Register extension.

Add CustomContextExtension to META-INF/javax.enterprise.inject.spi.Extension

Add CustomScope to framework object.

@CustomScope
public class FwObject { ... }

Inject FwObject using @Inject where needed.

public class MyService {
  @Inject
  FwObject obj;
}

Upvotes: 0

LightGuard
LightGuard

Reputation: 5378

Maybe with producer methods, all depends on what you need, but an extension is probably the best way to go. If you need to go with a new scope (if you're using JSF the Conversation scope may work) you will certainly need to create an extension.

Upvotes: 1

Related Questions