Velocity
  1. Velocity
  2. VELOCITY-267

Create a DataSourceResourceLoader that can be wired to the datasource with IoC

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 1.5
    • Fix Version/s: 1.5
    • Component/s: Engine
    • Labels:
      None
    • Environment:
      Operating System: other
      Platform: Other

      Description

      I'd like to create a ResourceLoader similar to DataSourceResourceLoader, except that I'd like to set
      the DataSource via IoC (in Spring). The main reason for this is so my database-loading of templates
      does not depend on a JNDI connection.

      The main problem is how to manage a ResourceLoader with Spring and then set it declaratively on its
      VelocityEngine - rather than via properties.

      <suggested patch from Will Glass-Husain>
      Does this mean that you'd need to pass in an instance of a resource manager
      (initialized with the datasource) to VelocityEngine, rather than just set
      the class name as a property? (MR - Yes)

      As I understand the source code, this doesn't seem possible. But I think a
      patch wouldn't be difficult. (a change to
      RuntimeInstance.initializeResourceManager) to look for an instance of the
      class as well as the class name. Something similar to
      LogManager.createLogSystem which accepts as a property the class name of a
      class that implements LogSystem, or an instance of the class itself.
      </suggested patch>

        Activity

        Matt Raible created issue -
        Hide
        Will Glass-Husain added a comment -

        Matt,

        I'm not a Spring user (not yet), so you'll have to advise me on this... how
        should the new DataSourceResourceLoader be configurable in order to be
        compatible with Spring.

        options...
        (a) pass in the datasource name and other params in a constructor
        (b) use standard javabean setters and getters (setDatasourceName, etc)
        (c) pass in a properties object with the various params.

        Alternately, if you've already built a custom resource loader that does that,
        perhaps you could just attach it.

        WILL

        Show
        Will Glass-Husain added a comment - Matt, I'm not a Spring user (not yet), so you'll have to advise me on this... how should the new DataSourceResourceLoader be configurable in order to be compatible with Spring. options... (a) pass in the datasource name and other params in a constructor (b) use standard javabean setters and getters (setDatasourceName, etc) (c) pass in a properties object with the various params. Alternately, if you've already built a custom resource loader that does that, perhaps you could just attach it. WILL
        Hide
        Matt Raible added a comment -

        Created an attachment (id=11361)
        DatabaseResourceLoader: an IoC-ready DataSourceResourceLoader

        Show
        Matt Raible added a comment - Created an attachment (id=11361) DatabaseResourceLoader: an IoC-ready DataSourceResourceLoader
        Hide
        Matt Raible added a comment -

        I've attached the resourceLoader that I wrote in hopes of using it, but then discovered that there was no
        way to pass it to the velocity engine. I think the best way is to continue to allow a properties file to be
        passed, but also coding the defaults from DataSourceResourceLoader (so you don't have to set them).
        For IoC, I simply added a setter for setDataSource() - which can be easily done in Spring. The hard part
        is passing this initialized loader to the VelocityEngine.

        Show
        Matt Raible added a comment - I've attached the resourceLoader that I wrote in hopes of using it, but then discovered that there was no way to pass it to the velocity engine. I think the best way is to continue to allow a properties file to be passed, but also coding the defaults from DataSourceResourceLoader (so you don't have to set them). For IoC, I simply added a setter for setDataSource() - which can be easily done in Spring. The hard part is passing this initialized loader to the VelocityEngine.
        Hide
        Will Glass-Husain added a comment -

        Well, no comments from the crowd, but it was simple to implement. Patch
        following. Fully backwards compatible. Ant test works fine, of course.

        I modified the existing DataSourceResourceLoader as it seemed silly to create
        a new one. So, something similar to the following should work:

        velocity.properties:
        resource.loader = ds
        ds.resource.loader.resource.table = tb_velocity_template
        ds.resource.loader.resource.keycolumn = id_template
        ds.resource.loader.resource.templatecolumn = template_definition
        ds.resource.loader.resource.timestampcolumn = template_timestamp

        Code:
        DataSourceResourceLoader ds = new DataSourceResourceLoader();
        ds.setDataSource(DATASOURCE);
        Velocity.setProperty("ds.resource.loader.instance",ds);
        Velocity.init();

        Give it a spin, see how it works.

        Show
        Will Glass-Husain added a comment - Well, no comments from the crowd, but it was simple to implement. Patch following. Fully backwards compatible. Ant test works fine, of course. I modified the existing DataSourceResourceLoader as it seemed silly to create a new one. So, something similar to the following should work: velocity.properties: resource.loader = ds ds.resource.loader.resource.table = tb_velocity_template ds.resource.loader.resource.keycolumn = id_template ds.resource.loader.resource.templatecolumn = template_definition ds.resource.loader.resource.timestampcolumn = template_timestamp Code: DataSourceResourceLoader ds = new DataSourceResourceLoader(); ds.setDataSource(DATASOURCE); Velocity.setProperty("ds.resource.loader.instance",ds); Velocity.init(); Give it a spin, see how it works.
        Hide
        Will Glass-Husain added a comment -

        Created an attachment (id=11362)
        patch to implement enhancement request

        Show
        Will Glass-Husain added a comment - Created an attachment (id=11362) patch to implement enhancement request
        Hide
        Will Glass-Husain added a comment -

        Created an attachment (id=11363)
        zip of test case files

        Show
        Will Glass-Husain added a comment - Created an attachment (id=11363) zip of test case files
        Hide
        Matt Raible added a comment -

        Thanks Will. I can't it to work yet, but I've posted a question to the Spring
        mailing list in hopes of figuring it out.

        http://thread.gmane.org/gmane.comp.java.springframework.devel/4121

        Show
        Matt Raible added a comment - Thanks Will. I can't it to work yet, but I've posted a question to the Spring mailing list in hopes of figuring it out. http://thread.gmane.org/gmane.comp.java.springframework.devel/4121
        Hide
        Matt Raible added a comment -

        Thanks will - your patched DataSourceResourceLoader works great:

        http://jroller.com/page/raible?anchor=loading_velocity_templates_from_the

        Show
        Matt Raible added a comment - Thanks will - your patched DataSourceResourceLoader works great: http://jroller.com/page/raible?anchor=loading_velocity_templates_from_the
        Hide
        Will Glass-Husain added a comment -

        Patched - Revision# 124381. Matt, thanks again for the patch and the testing.

        Show
        Will Glass-Husain added a comment - Patched - Revision# 124381. Matt, thanks again for the patch and the testing.
        Jeff Turner made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 28611 12315137
        Hide
        Will Glass-Husain added a comment -

        I'm not sure i understand the proposed patch - can anyone suggest a specific edit? WGH

        I'm copying the following from Vladimir Terzic <vterzic@intgas.com> 's recent entry on Bugzilla.

        To make this patch truly work with spring you need to change method below.
        If method is left unchanged Velocity will look for JNDI context which may not be
        available and spring with throw an error. Since we provided dataSource via
        spring IOC context call is not necessary.

        private Connection openDbConnection() throws Exception {
        if (dataSource != null)
        return dataSource.getConnection();

        if (ctx == null)

        { ctx = new InitialContext(); }

        if (dataSource == null)

        { dataSource = (DataSource)ctx.lookup(dataSourceName); }

        return dataSource.getConnection();
        }

        Show
        Will Glass-Husain added a comment - I'm not sure i understand the proposed patch - can anyone suggest a specific edit? WGH I'm copying the following from Vladimir Terzic <vterzic@intgas.com> 's recent entry on Bugzilla. To make this patch truly work with spring you need to change method below. If method is left unchanged Velocity will look for JNDI context which may not be available and spring with throw an error. Since we provided dataSource via spring IOC context call is not necessary. private Connection openDbConnection() throws Exception { if (dataSource != null) return dataSource.getConnection(); if (ctx == null) { ctx = new InitialContext(); } if (dataSource == null) { dataSource = (DataSource)ctx.lookup(dataSourceName); } return dataSource.getConnection(); }
        Will Glass-Husain made changes -
        Assignee Velocity-Dev List [ velocity-dev@jakarta.apache.org ]
        Status Resolved [ 5 ] Reopened [ 4 ]
        Resolution Fixed [ 1 ]
        Hide
        Vladimir Terzic added a comment -

        Velocity requires JNDI context to get DataSource (note check for ctx).
        Above enhancement requsted by Matt Raible enables Spring configuration of Velocity JDBC DataSourceLoader which means that now you can pass JDBC DataSource to Velocity using spring config file(via IOC setter injection).

        If you are using Spring framework to pass in the DataSource, Velocity does not need to check for the dataSource (and more importantly for context) since it already has reference to it . My suggested enhancement will allow you to run this configuration of Velocity outside of the J2EE environment.

        I know...clear as mud

        current code:
        --------------------------------------------------------------
        private Connection openDbConnection() throws Exception {
        if (ctx == null)

        { ctx = new InitialContext(); }

        if (dataSource == null) { dataSource = (DataSource)ctx.lookup(dataSourceName); }

        return dataSource.getConnection();
        }

        proposed code:
        --------------------------------------------------------------
        private Connection openDbConnection() throws Exception {
        if (dataSource != null)
        return dataSource.getConnection();

        if (ctx == null) { ctx = new InitialContext(); }

        if (dataSource == null)

        { dataSource = (DataSource)ctx.lookup(dataSourceName); }

        return dataSource.getConnection();
        }

        Show
        Vladimir Terzic added a comment - Velocity requires JNDI context to get DataSource (note check for ctx). Above enhancement requsted by Matt Raible enables Spring configuration of Velocity JDBC DataSourceLoader which means that now you can pass JDBC DataSource to Velocity using spring config file(via IOC setter injection). If you are using Spring framework to pass in the DataSource, Velocity does not need to check for the dataSource (and more importantly for context) since it already has reference to it . My suggested enhancement will allow you to run this configuration of Velocity outside of the J2EE environment. I know...clear as mud current code: -------------------------------------------------------------- private Connection openDbConnection() throws Exception { if (ctx == null) { ctx = new InitialContext(); } if (dataSource == null) { dataSource = (DataSource)ctx.lookup(dataSourceName); } return dataSource.getConnection(); } proposed code: -------------------------------------------------------------- private Connection openDbConnection() throws Exception { if (dataSource != null) return dataSource.getConnection(); if (ctx == null) { ctx = new InitialContext(); } if (dataSource == null) { dataSource = (DataSource)ctx.lookup(dataSourceName); } return dataSource.getConnection(); }
        Will Glass-Husain made changes -
        Bugzilla Id 28611
        Fix Version/s 1.5 [ 12310253 ]
        Environment Operating System: other
        Platform: Other
        Operating System: other
        Platform: Other
        Description I'd like to create a ResourceLoader similar to DataSourceResourceLoader, except that I'd like to set
        the DataSource via IoC (in Spring). The main reason for this is so my database-loading of templates
        does not depend on a JNDI connection.

        The main problem is how to manage a ResourceLoader with Spring and then set it declaratively on its
        VelocityEngine - rather than via properties.

        <suggested patch from Will Glass-Husain>
        Does this mean that you'd need to pass in an instance of a resource manager
        (initialized with the datasource) to VelocityEngine, rather than just set
        the class name as a property? (MR - Yes)

        As I understand the source code, this doesn't seem possible. But I think a
        patch wouldn't be difficult. (a change to
        RuntimeInstance.initializeResourceManager) to look for an instance of the
        class as well as the class name. Something similar to
        LogManager.createLogSystem which accepts as a property the class name of a
        class that implements LogSystem, or an instance of the class itself.
        </suggested patch>
        I'd like to create a ResourceLoader similar to DataSourceResourceLoader, except that I'd like to set
        the DataSource via IoC (in Spring). The main reason for this is so my database-loading of templates
        does not depend on a JNDI connection.

        The main problem is how to manage a ResourceLoader with Spring and then set it declaratively on its
        VelocityEngine - rather than via properties.

        <suggested patch from Will Glass-Husain>
        Does this mean that you'd need to pass in an instance of a resource manager
        (initialized with the datasource) to VelocityEngine, rather than just set
        the class name as a property? (MR - Yes)

        As I understand the source code, this doesn't seem possible. But I think a
        patch wouldn't be difficult. (a change to
        RuntimeInstance.initializeResourceManager) to look for an instance of the
        class as well as the class name. Something similar to
        LogManager.createLogSystem which accepts as a property the class name of a
        class that implements LogSystem, or an instance of the class itself.
        </suggested patch>
        Hide
        Will Glass-Husain added a comment -

        Patch applied - thanks!

        Show
        Will Glass-Husain added a comment - Patch applied - thanks!
        Will Glass-Husain made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Hide
        Henning Schmiedehausen added a comment -

        Close all resolved issues for Engine 1.5 release.

        Show
        Henning Schmiedehausen added a comment - Close all resolved issues for Engine 1.5 release.
        Henning Schmiedehausen made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Mark Thomas made changes -
        Workflow jira [ 12325142 ] Default workflow, editable Closed status [ 12551266 ]
        Mark Thomas made changes -
        Workflow Default workflow, editable Closed status [ 12551266 ] jira [ 12552184 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            Matt Raible
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development