6

Coming from a Guice background, I know that it is possible to seed an object value from a scope using.

  scope.seed(Key.get(SomeObject.class), someObject);

I suppose one could do this by registering a Bean that gets a value from an AbstractBoundContext, but examples just seeding one value from a Custom Scope seem hard to find. How do I create a custom scope that seeds a value that can be injected elsewhere?

Edit: I am currently using the following workaround, that can be injected in an interceptor to set the Configuration when entering the scope, and can then be injected through its thread local provider. I am still looking for options that feel less hacky / are more integrated with the scope/scope context system in Weld though.

@Singleton
public class ConfigurationProducer {

    private final InheritableThreadLocal<Configuration>  threadLocalConfiguration =
    new InheritableThreadLocal<>();

    @Produces
    @ActiveDataSet
    public ConfigurationConfiguration() {
       return threadLocalConfiguration.get()
    }

    public void setConfiguration(Configuration configuration) {
         threadLocalConfiguration.set(configuration);
    }    

}
  • 1
    Seed function in guice just uses Map to store your objects. In CDI you write an extension and implement Scope interface if you want a custom scope. All your seeded objects will probably placed in context interface implementation in some Map. – temaleva Jul 13 '16 at 09:04
  • Yes I found out about the scope annotation and the extensions. I am however wondering how a javax.enterprise.context.spi.Context should be implemented. And how to get from a Contextual to, what in Guice would be, the Key. – Jan-Willem Gmelig Meyling Jul 13 '16 at 16:08
  • Could you please give more details about the custom scope you need and about what you are trying to achieve? Aren't the built-in scopes enough for you? – cassiomolin Jul 18 '16 at 14:00
  • 1
    I am trying to use this for a multi tenancy environment, where I am creating a `@TenantScoped`, where `@TenantScoped EntityManger` is bound to a provider that uses an `EntityManagerFactory` that is configured for that tenant. So when entering the scope, I need to be able to pass an object reference, that later on can be injected with a specific key/qualifier. – Jan-Willem Gmelig Meyling Jul 18 '16 at 14:04
  • It Looks like, you use JPA and need two different entity manager providers. Please take a look on Deltaspike Jpa module - Multiple EntityManagers. https://deltaspike.apache.org/documentation/jpa.html#ProducingMultipleEntityManagers. So you need presumably qualified producer and not scope. – temaleva Aug 01 '16 at 13:10
  • 1
    No it could even be a constant string or POJO – Jan-Willem Gmelig Meyling Aug 01 '16 at 13:19

1 Answers1

1

The answer is to register a custom bean with the AfterBeanDiscovery event, like so:

    event.addBean()
        .createWith(ctx -> commandContext.getCurrentCommandExecution())
        .addType(CommandExecution.class)
        .addQualifier(Default.Literal.INSTANCE)
        .scope(CommandScoped.class)
        .beanClass(CommandExtension.class);

There is a quite sophisticated example available at https://github.com/weld/command-context-example