Friday, March 30, 2018

multi-profiles in one minute

2012 spring added bean-profiles which is similar to project-stages added in myfaces-codi 2010. deltaspike improved and unified the project-stage concept. for the average case it's (imo) easier to handle than bean-profiles. however, from time to time users come up with some very special edge-cases which can be done with (custom) expressions supported by @Exclude. per definition such cases can get quite complex and usually there is an easier approach with deltaspike. in all the years (on the mailing-lists and in projects) i just saw one case which would really benefit a bit from the (imo) more complex bean-profiles approach. even in that case the result wasn't just "bad luck" and a questionable workaround as a result. instead it is possible to implements bean-profiles as a deltaspike-addon with less than 30 lines of code.


public class MultiProfileExtension implements Extension {
private Set<String> activeProfileNames = new HashSet<>();
protected void determineActiveProfiles(@Observes BeforeBeanDiscovery beforeBeanDiscovery) {
String activeProfileString =
ConfigResolver.getPropertyValue("active-profiles", "Production");
Collections.addAll(activeProfileNames, activeProfileString.split(","));
}
protected void matchActiveProfiles(@Observes ProcessAnnotatedType pat, BeanManager bm) {
Set<Annotation> annotations = pat.getAnnotatedType().getAnnotations();
Profile profile = AnnotationUtils.findAnnotation(
bm, annotations.toArray(new Annotation[annotations.size()]), Profile.class);
if (profile == null) {
return;
}
for (String supportedProfile : profile.value()) {
if (activeProfileNames.contains(supportedProfile)) {
return;
}
}
pat.veto();
}
}
the usage is quite simple.
@Profile("X")
//further cdi annotation/s
public class BeanProfileX {
}

a type-safe approach based on cdi-stereotypes is supported as well. the usage of the type-safe approach is also straightforward:
@ProfileA
//further cdi-annotation/s
public class BeanProfileA {
}
//...
@Stereotype
@Profile("A")
public @interface ProfileA {
}
view raw ProfileA.java hosted with ❤ by GitHub
enabling 1-n profiles can be done with any active config-source.
the implementation including tests are available at ds-multi-profile-addon.