Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support not (!) operator for profile selection [SPR-8728] #13370

Closed
spring-projects-issues opened this issue Sep 28, 2011 · 9 comments
Closed
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Sep 28, 2011

Tobias Mattsson opened SPR-8728 and commented

It would be really helpful if the profile attribute could take names of profiles that all has to be active.

For instance:

<beans profile="production,datacenter_us">
    ...
</beans>
<beans profile="production,datacenter_eu">
    ...
</beans>

As for syntax there would need to be a notation that can express both OR and AND, possibly using | and ,

Like:

<beans profile="staging|production">
    ...
</beans>

Even better would be if the syntax was in line with other expressions such as SpEL.


Affects: 3.1 M2

Issue Links:

7 votes, 12 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Sep 28, 2011

Chris Beams commented

Hi Tobias,

I've been expecting this request :)

For the uninitiated, the semantics of <beans profile="..."/> are such that comma-delimited values signify boolean OR, e.g. for <beans profile="x,y">, individual <bean> elements declared within will be registered if profile x or profile y are currently active.

To re-iterate your request, you would like to introduce additional boolean operations -- particularly AND -- to indicate that individual <bean> elements declared within will be registered only if profile x and profile y are both currently active.

Let me note at this point, that OR logic was selected as the only available operation and mapped to the comma (',') delimiter because it is the most reasonable default, i.e. what most users would expect in most situations, reads well, and also provides the most flexibility. You can effectively achieve boolean AND logic simply by nesting <beans> elements, e.g.:

<beans profile="x">
    <beans profile="y">
        <bean id="beanOnlyRegisteredIfXandYActive" ... />
    </beans>
</beans>

With that said, we understand that this is not an ideal approach if indeed AND logic ends up being commonplace for bean definition profile users. Therefore, we're open to implementing something here, but I would like to see additional votes and concrete use cases before doing so. In the meantime, I hope that the simple alternative above can meet your needs more effectively. Please feel free to rally support for this issue. We'd like to hear from other users.

Also note that any such change must also be reflected in the @Profile annotation. This is somewhat more tricky given that @Profile's value attribute accepts a proper String array rather than a single comma-delimited string. For example, @Profile({"x", "y"}) currently indicates that the annotated component should be registered if profile x or profile y are currently active. Were we to introduce additional boolean operations, this would need to be reflected as an additional attribute to the annotation, e.g.: @Profile(value={"x", "y"}, operation=AND); or optionally this could be supported by parsing individual value strings in the same fashion as the <beans profile="..."> attribute, e.g. @Profile("x&&y"), however this creates some ambiguity about the semantics of the following: @profile({"x&&y", "a||b"}). Does the latter mean either "x and y" or "a or b"? Or does it mean "x and y" and "a or b"? All of this would need to be defined and documented, without losing the initial simplicity of the comma-delimited OR approach.

As you can see, this is a seemingly simple request that can quickly spiral into complexity. For that reason, and as mentioned above, I'd like to get more feedback before heading in any one direction.

Cheers

Chris

@spring-projects-issues
Copy link
Collaborator Author

Erwin Vervaet commented

Next to AND logic, NOT would also be very useful.
I just spend a few days introducing bean definition profiles in a large Spring based application. In quite a few places I had just two variants for a particular set of bean definitions: one that should normally be used, and one that should only be used in special situations. Right now your only option is using two profiles:

<beans profile="normal">...</beans>
<beans profile="special">...</beans>

The downside here is that you need to explicitly activate the 'normal' profile, which can be a bit of a pain. IMHO, it would be more elegant to be able to write something like this:

<beans profile="!special">...</beans>
<beans profile="special">...</beans>

If you find yourself in a special situation it makes sense that you need to activate the 'special' profile.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues
Copy link
Collaborator Author

Erwin Vervaet commented

Hey Chris,

I don't think the default profiles would cover my case. The problem is that we actually have a large number of bean definition profiles (a least 20) and the "just two variants" remark only applies to a few of those. For other cases I need to be explicit and select a particular variant. In other words: I have explicitly activated profiles (Environment.getActiveProfiles()), and as a result the default profiles are no longer considered (AbstractEnvironment.acceptsProfiles()).

@spring-projects-issues
Copy link
Collaborator Author

Peter Wilkinson commented

I'm with Erwin. I have several components that can run with a 'normal' or 'special' profile and I want to be able to switch between modes on each component individually. At the moment this requires me setting all profiles explicitly.

A not operator as Erwin suggested would be very helpful.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

ok -- it certainly does look like there's demand for this change. I'm moving the fixVersion to 3.2 M1 so that I can at least take a stab at a NOT operator. I'll also look at the feasibility of full SpEL expression support, but at this point I would favor as simple as possible a set of changes for the reasons I initially listed above.

One thing that I'd appreciate feedback on:

The current semantics of comma-delimited profile strings is that the comma represents OR logic, e.g.:

<bean profile="p1,p2" ... />

indicates that this bean should be registered if p1 is active OR p2 is active.

Introducing a simple NOT (!) operator,

<bean profile="p1,!p2" ... />

would by extension indicate that this bean should be registered if p1 is active OR p2 is NOT active

This syntax would also allow for strange loopholes like the following:

<bean profile="p1,!p1" ... />

in which case the given bean would always be registered. Harmless perhaps, but worth noting.

Does anyone see issues with the above?

@spring-projects-issues
Copy link
Collaborator Author

Peter Wilkinson commented

@Chris : Looks good to me. =)

@spring-projects-issues
Copy link
Collaborator Author

Erwin Vervaet commented

I like the approach.
Since the NOT operator is well understood it is easy to reason through a profile specification like "p1,!p2" or even "p1,!p1" and understand when a set beans will be activated.
Furthermore, simply introducing the "!" prefix also works elegantly in @Profile.

So +1 from me.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

commit bcd44f3798ed06c0704d2a3564b8a9735e747e87
Author: Chris Beams <cbeams@vmware.com>
Date:   Sun May 27 08:10:40 2012 +0300

    Support not (!) operator for profile selection
    
    The following syntax is now supported
    
      <beans profile="p1,!p2">
    
      @Profile("p1", "!p2")
    
    indicating that the <beans> element or annotated component should
    be processed only if profile 'p1' is active or profile 'p2' is not
    active.
    
    Issue: SPR-8728

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant