-
Notifications
You must be signed in to change notification settings - Fork 53
DSL deferred execution #482
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
Conversation
| * Marker interface so the evaluator can tell apart objects which are {@link DeferredSupplier} | ||
| * but which expect DSL methods called on them instead of the value they supply. | ||
| */ | ||
| public interface DslCallable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm considering changing this to an annotation. When applied on:
- A class will work as now - let the DSL evaluator know to use the object as is, stop evaluation
- On a method - white-list the method for DSL calls. Deprecate non-annotated method calls. This will make it very easy to inspect what is executable by the DSL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea. Do you want to make it part of this PR or do it subsequently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one. Don't want to introduce APIs that will go away in master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After spiking the changes decided to keep DslCallable interface for first case and introduce a DslAccessible annotation for second. They have different use-cases, better not to mix them in the same annotation.
Will send an email to dev@brooklyn.apache.org discussing the DslAccessible change and implement it in a separate PR.
a0f3749 to
e634760
Compare
Lets us call methods on DslCallable methods and at the same time resolve the object if it's the last of the chain.
Fixes tests which expect the DSL evaluated objects to be in the correct package. Adds tests to verify that objects outside of the package scope are inaccessible to DSL.
e634760 to
6607ccb
Compare
Gives more control over what method gets executed.
| if (object instanceof DslCallable || object == null) { | ||
| return Maybe.of(object); | ||
| } | ||
| Maybe<?> resultMaybe = Tasks.resolving(object, Object.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this code reachable? This class is only constructed when object is DslCallable in which case the above branch applies, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm - missed the !
|
makes sense although something niggles... quick things:
my gut says a cleaner solution would be methods of the form |
Allows us to call custom DSL methods on any object we are interested in without the object knowing about DSL.
|
Good idea about stopping once the function is available, will think about it. Re |
|
Did the removal of |
|
nice. and good spot re errors. probably is worth keeping, not just for errors, but also so that we have some hope of being able to propose autocompletions / populate graphical editor. fine by me either way. |
| assertEquals(getConfigEventually(app, DEST), "myvalue"); | ||
| } | ||
|
|
||
| @Test(groups="WIP") // config accepts strings only, no suppliers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cut-n-paste - think this comment should be attributeWhenReady accepts strings only, no suppliers, also on next method
| Task<T> result = ((EntityInternal)entity).getExecutionContext().submit(new Callable<T>() { | ||
| @Override | ||
| public T call() throws Exception { | ||
| // TODO Move the getNonBlocking call out of the task after #280 is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean #480?
Addresses review comments.
Applying the DslAccessible annotation on any method allows it to be called by DSL
|
Decided to stick with |
| clazz.getPackage().getName().startsWith(whiteListPackage.getName())); | ||
| if (isPackageAllowed) { | ||
| if (DEPRECATED_ACCESS_WARNINGS.add(m)) { | ||
| log.warn("Deprecated since 0.11.0. The method '" + m.toString() + "' called by DSL should be white listed using the " + DslAccessible.class.getSimpleName() + " annotation. Support for DSL callable methods under the " + whiteListPackage + " will be fremoved in a future release."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo "fremoved". Would be nice to break this line up over several (currently 297 characters wide!)
|
|
||
| @Retention(RUNTIME) | ||
| @Target(METHOD) | ||
| public @interface DslAccessible { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to add some javadoc around this to explain what it's for.
| } | ||
| } | ||
|
|
||
| @DslAccessible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it that attributeWhenReady() and config() are able to be @DslAccessible when a few commits ago they did not return a value that implemented DslCallable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(i.e. I thought the difference was that e.g. attributeWhenReady() and config() couldn't be invoked within BrooklynDslInterpreter.evaluateOn() using DslDeferredFunctionCall.invoke() and so for them a DslDeferredFunctionCall object gets created, whereas general DslComponents get evaluated with an immediate DslDeferredFunctionCall.invoke(). Now, however, both general DslComponents like parent() and also e.g. attributeWhenReady()/config() are marked as @DslAccessible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(does the comment on the PR header, "DslComponent is a special case where it will not be resolved before evaluating the DSL as that's the expected behaviour.", still apply?)
|
LGTM, once @geomacy 's comments addressed |
|
Actually I think my comments above are not worth holding this up for, and I answered my question above myself with a bit of further inspection and running tests, so happy to merge. LGTM. |
Allows DSL to be applied on the return value of
attributeWhenReadyandconfigcalls. Before the change the DSL calls are made on theAttributeWhenReadyandDslConfigSupplierobjects correspondingly. After the changes the value will first be resolved and then the DSL evaluated on result.DslComponentis a special case where it will not be resolved before evaluating the DSL as that's the expected behaviour.Allows us to call custom DSL methods on any object we are interested in without the object knowing about DSL. Also lets us do chaining.
For example:
Builds on #482
Introduces
DslAccessibleannotation used to white-list methods which are allowed to be called by DSL, replacing the current approach of expecting them to be under theorg.apache.brooklyn.camp.brooklyn.spi.dsl.methodspackage.