How to manually inject dependencies into a bean in a AfterBeanDiscovery event listener (CDI)
up vote
0
down vote
favorite
I am using CDI 1.2 (Weld 2.3.5) and want to manually instantiate a bean and inject its dependencies during an AfterBeanDiscovery
event listener. I'm expecting that this would allow me to ensure that its Initialization would precede the @PostConstruct
initialization of other beans in the deployment container.
However, I am looking to use a bean declared via @Produces
as a dependency for the bean I am trying to create. According to the BeanManager API doc, I am not allowed to call a BeanManager.getReference()
method during the AfterBeanDiscovery
event. So I find myself a little stuck; I'm not sure if/how I can retrieve/use a dependency declared in the container as a parameter when constructing my bean in my ABD listener.
So far, I have the following:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
I'm still learning how to best leverage the JEE/CDI events and listeners, so perhaps this is not the right approach. Is there anyway to legally do what I am hoping to do? Is there any way to use/access a CDI controlled bean instance from within the ABD event listener?
I'm looking to support multiple @Produces CustomConfig
beans, and generate a CDICustomConfig
for each instance of a CustomConfig bean found in the context. How should I approach this?
java java-ee cdi weld bean-manager
add a comment |
up vote
0
down vote
favorite
I am using CDI 1.2 (Weld 2.3.5) and want to manually instantiate a bean and inject its dependencies during an AfterBeanDiscovery
event listener. I'm expecting that this would allow me to ensure that its Initialization would precede the @PostConstruct
initialization of other beans in the deployment container.
However, I am looking to use a bean declared via @Produces
as a dependency for the bean I am trying to create. According to the BeanManager API doc, I am not allowed to call a BeanManager.getReference()
method during the AfterBeanDiscovery
event. So I find myself a little stuck; I'm not sure if/how I can retrieve/use a dependency declared in the container as a parameter when constructing my bean in my ABD listener.
So far, I have the following:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
I'm still learning how to best leverage the JEE/CDI events and listeners, so perhaps this is not the right approach. Is there anyway to legally do what I am hoping to do? Is there any way to use/access a CDI controlled bean instance from within the ABD event listener?
I'm looking to support multiple @Produces CustomConfig
beans, and generate a CDICustomConfig
for each instance of a CustomConfig bean found in the context. How should I approach this?
java java-ee cdi weld bean-manager
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during anAfterBeanDiscovery
event listener." What goal you are trying to achieve?
– Illya Kysil
Nov 21 at 21:46
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that isAfterDeploymentValidation
.
– Siliarus
Nov 26 at 10:06
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which@Observes @Initialized(ApplicationScoped.class)
instead
– Eric B.
Nov 27 at 23:36
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I am using CDI 1.2 (Weld 2.3.5) and want to manually instantiate a bean and inject its dependencies during an AfterBeanDiscovery
event listener. I'm expecting that this would allow me to ensure that its Initialization would precede the @PostConstruct
initialization of other beans in the deployment container.
However, I am looking to use a bean declared via @Produces
as a dependency for the bean I am trying to create. According to the BeanManager API doc, I am not allowed to call a BeanManager.getReference()
method during the AfterBeanDiscovery
event. So I find myself a little stuck; I'm not sure if/how I can retrieve/use a dependency declared in the container as a parameter when constructing my bean in my ABD listener.
So far, I have the following:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
I'm still learning how to best leverage the JEE/CDI events and listeners, so perhaps this is not the right approach. Is there anyway to legally do what I am hoping to do? Is there any way to use/access a CDI controlled bean instance from within the ABD event listener?
I'm looking to support multiple @Produces CustomConfig
beans, and generate a CDICustomConfig
for each instance of a CustomConfig bean found in the context. How should I approach this?
java java-ee cdi weld bean-manager
I am using CDI 1.2 (Weld 2.3.5) and want to manually instantiate a bean and inject its dependencies during an AfterBeanDiscovery
event listener. I'm expecting that this would allow me to ensure that its Initialization would precede the @PostConstruct
initialization of other beans in the deployment container.
However, I am looking to use a bean declared via @Produces
as a dependency for the bean I am trying to create. According to the BeanManager API doc, I am not allowed to call a BeanManager.getReference()
method during the AfterBeanDiscovery
event. So I find myself a little stuck; I'm not sure if/how I can retrieve/use a dependency declared in the container as a parameter when constructing my bean in my ABD listener.
So far, I have the following:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
I'm still learning how to best leverage the JEE/CDI events and listeners, so perhaps this is not the right approach. Is there anyway to legally do what I am hoping to do? Is there any way to use/access a CDI controlled bean instance from within the ABD event listener?
I'm looking to support multiple @Produces CustomConfig
beans, and generate a CDICustomConfig
for each instance of a CustomConfig bean found in the context. How should I approach this?
java java-ee cdi weld bean-manager
java java-ee cdi weld bean-manager
asked Nov 11 at 20:50
Eric B.
10.2k28105206
10.2k28105206
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during anAfterBeanDiscovery
event listener." What goal you are trying to achieve?
– Illya Kysil
Nov 21 at 21:46
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that isAfterDeploymentValidation
.
– Siliarus
Nov 26 at 10:06
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which@Observes @Initialized(ApplicationScoped.class)
instead
– Eric B.
Nov 27 at 23:36
add a comment |
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during anAfterBeanDiscovery
event listener." What goal you are trying to achieve?
– Illya Kysil
Nov 21 at 21:46
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that isAfterDeploymentValidation
.
– Siliarus
Nov 26 at 10:06
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which@Observes @Initialized(ApplicationScoped.class)
instead
– Eric B.
Nov 27 at 23:36
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during an
AfterBeanDiscovery
event listener." What goal you are trying to achieve?– Illya Kysil
Nov 21 at 21:46
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during an
AfterBeanDiscovery
event listener." What goal you are trying to achieve?– Illya Kysil
Nov 21 at 21:46
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,
AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that is AfterDeploymentValidation
.– Siliarus
Nov 26 at 10:06
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,
AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that is AfterDeploymentValidation
.– Siliarus
Nov 26 at 10:06
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as
@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which @Observes @Initialized(ApplicationScoped.class)
instead– Eric B.
Nov 27 at 23:36
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as
@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which @Observes @Initialized(ApplicationScoped.class)
instead– Eric B.
Nov 27 at 23:36
add a comment |
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253104%2fhow-to-manually-inject-dependencies-into-a-bean-in-a-afterbeandiscovery-event-li%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253104%2fhow-to-manually-inject-dependencies-into-a-bean-in-a-afterbeandiscovery-event-li%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Would you be so kind to describe why it is required to "to manually instantiate a bean and inject its dependencies during an
AfterBeanDiscovery
event listener." What goal you are trying to achieve?– Illya Kysil
Nov 21 at 21:46
You need to rethink your approach, why do you want that? What you are trying to do is not meant to work,
AfterBeanDiscovery
is too early for beans to exist. Soonest you can do that isAfterDeploymentValidation
.– Siliarus
Nov 26 at 10:06
@IllyaKysil What I'm trying to achieve was modeled on the liquibase-cdi module. My goal was to manually create/instantiate a bean during the ABD event that would automatically get injected with all its dependencies. But as
@Siliarus
pointed out, I'm at at the right point in the lifecycle. In the end, I moved my bean to a method which@Observes @Initialized(ApplicationScoped.class)
instead– Eric B.
Nov 27 at 23:36