Seed value in Weld CDI custom scope
Asked Answered
L

1

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);
    }    

}
Length answered 12/7, 2016 at 6:34 Comment(6)
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.Abomination
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.Length
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?Engineer
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.Length
It Looks like, you use JPA and need two different entity manager providers. Please take a look on Deltaspike Jpa module - Multiple EntityManagers. deltaspike.apache.org/documentation/…. So you need presumably qualified producer and not scope.Abomination
No it could even be a constant string or POJOLength
L
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

Length answered 13/2, 2019 at 12:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.