Baruch Sadogursky opened SPR-12300 and commented
As suggested by Artem, it makes sense to add @EnableScripting
and @ScriptSource
(refreshDelay = 1000) on the Resource @Bean
method.
Affects: 4.1 GA
Reference URL: http://stackoverflow.com/questions/26208020/using-spring-dynamic-languages-support-from-java-configuration
Issue Links: - #14886 Refreshing annotated Groovy controllers cause ClassCastException - #9888 ScriptFactory for JSR-223 - #12691 Unable to define a scripted bean as an inner bean of another bean - INTEXT-130 Provide support for dynamic scripts (Groovy, JRuby etc.) within the flow definition
8 votes, 12 watchers
Comment From: spring-projects-issues
Artem Bilan commented
The linked issue INTEXT-130 isn't related to the subject, but like a case to gather more info.
Comment From: spring-projects-issues
Juergen Hoeller commented
I'm afraid this might not make it into 4.2 RC1... too much on the plate still, and a rather hard deadline towards the end of May.
Juergen
Comment From: spring-projects-issues
Nick Grealy commented
Hi all, what's required in order to get this delivered (what's been done, what needs to be done)? I'm happy to contribute dev effort to get this into a release. (related? #14886 )
Comment From: spring-projects-issues
Thomas Darimont commented
It would be helpful to have javaconfig support for this - currently you have to write quite a bit of boiler-plate to get this working with Java Config: https://gist.github.com/thomasdarimont/f7f2ef6f4900b9f89d58
Comment From: spring-projects-issues
Thomas Darimont commented
One approach could be to provide an easy to configure FactoryBean
that would create Proxies backed by a AbstractRefreshableTargetSource
which in turn (optionally) perform the reloading after a confgured time interval.
With this in place all the user would have to do to define a refreshable bean backed by a groovy script would be something along the lines of:
@Bean
public GroovyScript myScriptBean() {
return new GroovyScript("classpath:MyScriptBean.groovy", MyScriptInterface.class).refreshEvery(1, SECONDS);
}
A quick API sketch for this can be found here: https://gist.github.com/thomasdarimont/9fe86c61208c340e875a
With respect to the @EnableScripting
idea.
I could imagine the following (with and without spring-boot):
@EnableScripting(lang=GROOVY, sourceSource="scripts", refreshCheckDelay=500, proxyTargetClass=false)
@SpringBootApplication
class App{
...
}
@EnableScripting
could then some kind of "script-scanning" that
automatically picks up (groovy) scripts under the given "source" directory.
It could also automatically turn scripts like the one below into appropriate spring beans.
Note: one could also have special @EnableGroovyScripting
via annotation composition - or even provide a spring-boot-starter-groovy with that enabled.
scripts/MyScript.groovy:
class MyScript implements MyInterface{
def someOperation(){
...
return someResult
}
}
would result in a spring bean named "myScript" of type "MyInterface" with default refresh-settings and default-proxing applied.
For groovy it is easy to derive the expected interface that should be proxied iif the groovy class implements it directly. In other cases (e.g. for other script languages) one needs additional metadata for that, perhaps within the script itself, perhaps in the form of a special marker comment or within a separate file right next to it. I think being able to explicitly define script (factory) beans via an API, similiar to what I sketched above, could be used to explicitly define the interface type to be proxied in a pragmatic way.
Comment From: spring-projects-issues
Artem Bilan commented
Hi Thomas Darimont!
Thank you for digging in this area.
Yes, I definitely agreed that some short FactoryBean
definition is the best way to go. It is Java, it is Spring and it is obvious from the IDE code completion perspective.
My current idea for the @EnableScripting
is around the Groovy ability to use annotations. With that we may get a gain from the same @ComponentScan
which looks for the Groovy scripts as well, loads them as classes and populate appropriate beans with the desired refreshCheckDelay
feature extracting some annotation on the Groovy class.
Looks like we can use annotations with Ruby as well: http://www.weblogism.com/item/342/java-annotations-with-jruby-a-spring-mvc-example. Although it doesn't mean that we will be able to parse its class
All others require further investigation, Although I'm not sure how this feature works with JavaScript... I mean the interface implementation.
So, having the long story for this JIRA, we really may just end up with the FactoryBean
and that's all. Even without involving ScriptFactoryPostProcessor
as it is in your PoC.
Comment From: spring-projects-issues
Juergen Hoeller commented
Let's turn this into a 5.0 feature theme. We have enough on our plate for 4.3, and this one should be done comprehensively... It would also benefit from a milestone phase which 4.3 doesn't have (we're going straight to RC1 in March there).
Juergen