Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-15064

Support i18n and nested template loading in ScriptTemplateView render function

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 5.0 M5
    • Component/s: Web
    • Labels:
    • Last commented by a User:
      true

      Description

      The render function called by ScriptTemplateView has currently 3 parameters provided:

      • String template: the content of the template resource
      • Map<String, Object>: the model to use to render the view
      • String url: the url of the 2 view

      To achieve i18n support for messages and nested template loading, we need to provide these additional informations:

      • a ResourceBundleMessageSource instance (or the ApplicationContext that allows to retrieve it)
      • the view Locale
      • a Function<String, String> that allows the render function to call ScriptTemplateView#getTemplate(String)

      I see mainly 2 ways to support that:

      1) We could be possible leverage setExposeContextBeansAsAttributes() or setExposedContextBeanNames() to access to context beans and expose them via model attributes.

      2) We could transform the 3rd parameter passed to the script function (currently String url) to RenderingContext that would contains String url, Locale locale, ResourceBundleMessageSource messageSource and Function<String, String> templateLoader properties. This would be a breaking change for people using `url` but ScriptTemplateView is a rather feature, and url is not widely used, so I consider this as an option in order to be consistent and provide such flexible mechanism for further needs + it provides these properties in a type-safe way which would be valuable for Kotlin JSR-223 support.

        Issue Links

          Activity

          Hide
          yevhenii-melnyk Yevhenii Melnyk added a comment -

          Not sure if the following stuff is appropriate here but I didn't want to open a new issue without discussion. So, the situation is following:

          I was trying to use two different template view resolvers in my Spring mvc app. For example, kotlin and javascript at the same time. Creation of 2 ViewResolver beans is not the problem. It seems impossible to use two ScriptTemplateConfigurer because ScriptTemplateConfig is being acquired in ScriptTemplateView.autodetectViewConfig by ScriptTemplateConfig.class from Spring context.

          Is there a way to use two scripting engines at the same time or this feature is not supported currently?

          Show
          yevhenii-melnyk Yevhenii Melnyk added a comment - Not sure if the following stuff is appropriate here but I didn't want to open a new issue without discussion. So, the situation is following: I was trying to use two different template view resolvers in my Spring mvc app. For example, kotlin and javascript at the same time. Creation of 2 ViewResolver beans is not the problem. It seems impossible to use two ScriptTemplateConfigurer because ScriptTemplateConfig is being acquired in ScriptTemplateView.autodetectViewConfig by ScriptTemplateConfig.class from Spring context. Is there a way to use two scripting engines at the same time or this feature is not supported currently?
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          Indeed this is currently not supported out of the box, but maybe you could make it works for your use case by extending ScriptTemplateConfig* classes for Kotlin or Javascript with specify dedicated View and ViewConfigurer classes.

          Show
          sdeleuze Sébastien Deleuze added a comment - Indeed this is currently not supported out of the box, but maybe you could make it works for your use case by extending ScriptTemplateConfig* classes for Kotlin or Javascript with specify dedicated View and ViewConfigurer classes.
          Hide
          yevhenii-melnyk Yevhenii Melnyk added a comment -

          I'll leave the stackoverflow post regarding multiple configurers here in case somebody has a same question I've got. The implementation is really easy. Thank you Sébastien Deleuze.

          Show
          yevhenii-melnyk Yevhenii Melnyk added a comment - I'll leave the stackoverflow post regarding multiple configurers here in case somebody has a same question I've got. The implementation is really easy. Thank you Sébastien Deleuze.
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          See also this related pull request for providing i18n support, I will try to provide a solution that fulfill that need too.

          Show
          sdeleuze Sébastien Deleuze added a comment - See also this related pull request for providing i18n support, I will try to provide a solution that fulfill that need too.
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          Juergen Hoeller Could you please have a look to this pull request I have just submitted to say me if you are ok with such approach.

          This change would be breaking (on the script side, not on java side) for people using the third url parameter that we introduced as part of SPR-13453 in 4.2.2, but ScriptTemplateView is a rather young functionality, and this variant with an url parameter is likely to not being used very widely, so I would take the opportunity of our major 5.0 release to define a consistent and future proof render function SPI.

          As you can see here the migration path is trivial.

          I preferred this option over using setExposeContextBeansAsAttributes() or setExposedContextBeanNames() because:

          • It allows to be consistent about the various parameters we pass to the rendering function (url versus others)
          • It is type-safe which matters for Kotlin Script and more discoverable than something based on model attributes
          • It avoids to mix model attributes designed to be rendered in the template, and those informations designed to be used in the rendering function
          • It will allow us to add new rendering properties without breaking the script API

          I also choose to provide the ApplicationContext rather than directly the ResourceBundleMessageSource bean because that avoids to make assumption about how to retrieve it (by type, by name) and allows a wide range of use cases in addition to i18n. See it in action in this Kotlin Script example.

          Show
          sdeleuze Sébastien Deleuze added a comment - Juergen Hoeller Could you please have a look to this pull request I have just submitted to say me if you are ok with such approach. This change would be breaking (on the script side, not on java side) for people using the third url parameter that we introduced as part of SPR-13453 in 4.2.2 , but ScriptTemplateView is a rather young functionality, and this variant with an url parameter is likely to not being used very widely, so I would take the opportunity of our major 5.0 release to define a consistent and future proof render function SPI. As you can see here the migration path is trivial. I preferred this option over using setExposeContextBeansAsAttributes() or setExposedContextBeanNames() because: It allows to be consistent about the various parameters we pass to the rendering function ( url versus others) It is type-safe which matters for Kotlin Script and more discoverable than something based on model attributes It avoids to mix model attributes designed to be rendered in the template, and those informations designed to be used in the rendering function It will allow us to add new rendering properties without breaking the script API I also choose to provide the ApplicationContext rather than directly the ResourceBundleMessageSource bean because that avoids to make assumption about how to retrieve it (by type, by name) and allows a wide range of use cases in addition to i18n. See it in action in this Kotlin Script example .
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          Notice that this improvement allow this kind of Kotlin type-safe templates with i18n and nested template support:

          import org.springframework.web.reactive.result.view.script.*
           
          """${include("header") }
          <p>${i18n("hello")} $foo</p>
          ${include("footer")}"""
          

          Show
          sdeleuze Sébastien Deleuze added a comment - Notice that this improvement allow this kind of Kotlin type-safe templates with i18n and nested template support: import org.springframework.web.reactive.result.view.script.*   """${include("header") } <p>${i18n("hello")} $foo</p> ${include("footer")}"""

            People

            • Assignee:
              sdeleuze Sébastien Deleuze
              Reporter:
              sdeleuze Sébastien Deleuze
              Last updater:
              Stéphane Nicoll
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                8 weeks, 2 days ago