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