3
votes

I need to configure different @Alternatives, @Decorators and @Injectors for different runtime environments (think testing, staging and production servers).

Right now I use maven to create three wars, and the only difference between those wars are in the beans.xml files. Is there a better way to do this? I do have @Alternative @Stereotypes for the different environments, but even then I need to alter beans.xml, and they don't work for @Decorators (or do they?)

Is it somehow possible to instruct CDI to ignore the values in beans.xml and use a custom configuration source? Because then I could for example read a system property or other environment variable.

The application exclusively runs in containers that use Weld, so a weld-specific solution would be ok.

I already tried to google this but can't seem to find good search terms, and I asked the Weld-Users-Forums, but to no avail. Someone over there suggested to write my own custom extension, but I can't find any API to actually change the container configuration at runtime.

I think it would be possible to have some sort of @ApplicationScoped configuration bean and inject that into all @Decorators which could then decide themselves whether they should be active or not and then in order to configure @Alternatives write @Produces methods for every interface with multiple implementations and inject the config bean there too. But this seems to me like a lot of unnecessary work to essentially duplicate functionality already present in CDI?

edit

Ok, I realized I'm a bit stupid... of course it is possible to add stereotypes and inteceptors at runtime using the CDI extension API:

void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) {
    bbd.addInterceptorBinding(...)
    bbd.addStereotype(...)
}

But what I didn't find was an API to add a decorator. The only thing I found was to activate all @Decorators in the beans.xml, then observe

public <T> void processAnotated(@Observes ProcessAnnotatedType<T> event)

and call

event.veto()

if I don't want a @Decorator to be active.

1
It is very frustrating that we need to write an extension to switch alternatives...Julio Faerman

1 Answers

1
votes

You might want to take a look at JBoss Seam, specifically the Solder sub-project.

It allows dependency driven CDI resolution, so that certain beans are only available if other beans or resources are available. (Class A if "dataSource" is available, Class B if "entityManager" is available)

Since it's open source, you can also take a look at how they wired that together, and use that knowledge as a basis for writing your own extension if needed.

If you're using JSF, I would highly recommend using SEAM-JSF as well, as it gets rid of the clunkiness of having two injection frameworks (JSF DI/CDI) and allows CDI beans in JSF scopes.