Uploaded image for project: 'Velocity'
  1. Velocity
  2. VELOCITY-176

DataSourceResourceLoader throws null pointer exception

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.3.1
    • 1.5
    • Engine
    • None
    • Operating System: All
      Platform: PC
    • 19440

    Description

      Hi,

      I am trying to use DB (Oracle) as a storage for my templates, but using
      org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader class I am
      getting consistently null pointer exception.

      I was able to debug it and it seems that this could be the fix for this problem:
      change getResourceStream function to return StringBufferInputStream(strField),
      where strField is: String strField = rs.getString(templateColumn);
      (not BufferedInputStream(rs.getAsciiStream(templateColumn)) )

      Note: this also will require import java.io.*;

      Please see the modified class below.

      Please let me know if this change make sense or is there something else I
      should do to avoid this problem.

      Thanks.

      package org.apache.velocity.runtime.resource.loader;
      import java.io.*;

      /*

      • The Apache Software License, Version 1.1
        *
      • Copyright (c) 2001-2002 The Apache Software Foundation. All rights
      • reserved.
        *
      • Redistribution and use in source and binary forms, with or without
      • modification, are permitted provided that the following conditions
      • are met:
        *
      • 1. Redistributions of source code must retain the above copyright
      • notice, this list of conditions and the following disclaimer.
        *
      • 2. Redistributions in binary form must reproduce the above copyright
      • notice, this list of conditions and the following disclaimer in
      • the documentation and/or other materials provided with the
      • distribution.
        *
      • 3. The end-user documentation included with the redistribution, if
      • any, must include the following acknowlegement:
      • "This product includes software developed by the
      • Apache Software Foundation (http://www.apache.org/)."
      • Alternately, this acknowlegement may appear in the software itself,
      • if and wherever such third-party acknowlegements normally appear.
        *
      • 4. The names "The Jakarta Project", "Velocity", and "Apache Software
      • Foundation" must not be used to endorse or promote products derived
      • from this software without prior written permission. For written
      • permission, please contact apache@apache.org.
        *
      • 5. Products derived from this software may not be called "Apache"
      • nor may "Apache" appear in their names without prior written
      • permission of the Apache Group.
        *
      • THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
      • WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      • OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      • DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
      • ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      • SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      • LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
      • USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      • ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      • OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
      • OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      • SUCH DAMAGE.
      • ====================================================================
        *
      • This software consists of voluntary contributions made by many
      • individuals on behalf of the Apache Software Foundation. For more
      • information on the Apache Software Foundation, please see
      • <http://www.apache.org/>.
        */

      import java.io.InputStream;
      import java.io.BufferedInputStream;
      import java.util.Hashtable;

      import javax.sql.DataSource;
      import javax.naming.InitialContext;

      import org.apache.velocity.runtime.Runtime;
      import org.apache.velocity.runtime.resource.Resource;

      import org.apache.velocity.exception.ResourceNotFoundException;

      import org.apache.commons.collections.ExtendedProperties;
      import java.sql.Connection;
      import java.sql.ResultSet;
      import java.sql.Statement;
      import java.sql.SQLException;

      /**

      • This is a simple template file loader that loads templates
      • from a DataSource instead of plain files.
        *
      • It can be configured with a datasource name, a table name,
      • id column (name), content column (the template body) and a
      • datetime column (for last modification info).
      • <br>
      • <br>
      • Example configuration snippet for velocity.properties:
      • <br>
      • <br>
      • resource.loader = file, ds <br>
      • <br>
      • ds.resource.loader.public.name = DataSource <br>
      • ds.resource.loader.description = Velocity DataSource Resource Loader <br>
      • ds.resource.loader.class =
        org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader <br>
      • ds.resource.loader.resource.datasource = java:comp/env/jdbc/Velocity <br>
      • ds.resource.loader.resource.table = tb_velocity_template <br>
      • ds.resource.loader.resource.keycolumn = id_template <br>
      • ds.resource.loader.resource.templatecolumn = template_definition <br>
      • ds.resource.loader.resource.timestampcolumn = template_timestamp <br>
      • ds.resource.loader.cache = false <br>
      • ds.resource.loader.modificationCheckInterval = 60 <br>
      • <br>
      • Example WEB-INF/web.xml: <br>
      • <br>
      • <resource-ref> <br>
      • <description>Velocity template DataSource</description> <br>
      • <res-ref-name>jdbc/Velocity</res-ref-name> <br>
      • <res-type>javax.sql.DataSource</res-type> <br>
      • <res-auth>Container</res-auth> <br>
      • </resource-ref> <br>
      • <br>
      • <br>
      • and Tomcat 4 server.xml file: <br>
      • [...] <br>
      • <Context path="/exampleVelocity" docBase="exampleVelocity" debug="0"> <br>
      • [...] <br>
      • <ResourceParams name="jdbc/Velocity"> <br>
      • <parameter> <br>
      • <name>driverClassName</name> <br>
      • <value>org.hsql.jdbcDriver</value> <br>
      • </parameter> <br>
      • <parameter> <br>
      • <name>driverName</name> <br>
      • <value>jdbc:HypersonicSQL:database</value> <br>
      • </parameter> <br>
      • <parameter> <br>
      • <name>user</name> <br>
      • <value>database_username</value> <br>
      • </parameter> <br>
      • <parameter> <br>
      • <name>password</name> <br>
      • <value>database_password</value> <br>
      • </parameter> <br>
      • </ResourceParams> <br>
      • [...] <br>
      • </Context> <br>
      • [...] <br>
      • <br>
      • Example sql script:<br>
      • CREATE TABLE tb_velocity_template ( <br>
      • id_template varchar (40) NOT NULL , <br>
      • template_definition text (16) NOT NULL , <br>
      • template_timestamp datetime NOT NULL <br>
      • ) <br>
        *
      • @author <a href="mailto:david.kinnvall@alertir.com">David Kinnvall</a>
      • @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
      • @author <a href="mailto:lachiewicz@plusnet.pl">Sylwester Lachiewicz</a>
      • @version $Id: DataSourceResourceLoader.java,v 1.8 2002/02/10 18:46:58 geirm
        Exp $
        */
        public class DataSourceResourceLoader extends ResourceLoader
        {
        private String dataSourceName;
        private String tableName;
        private String keyColumn;
        private String templateColumn;
        private String timestampColumn;
        private InitialContext ctx;
        private DataSource dataSource;

      public void init( ExtendedProperties configuration)

      { dataSourceName = configuration.getString("resource.datasource"); tableName = configuration.getString("resource.table"); keyColumn = configuration.getString("resource.keycolumn"); templateColumn = configuration.getString("resource.templatecolumn"); timestampColumn = configuration.getString("resource.timestampcolumn"); Runtime.info("Resources Loaded From: " + dataSourceName + "/" + tableName); Runtime.info( "Resource Loader using columns: " + keyColumn + ", " + templateColumn + " and " + timestampColumn); Runtime.info("Resource Loader Initalized."); }

      public boolean isSourceModified(Resource resource)

      { return (resource.getLastModified() != readLastModified(resource, "checking timestamp")); }

      public long getLastModified(Resource resource)

      { return readLastModified(resource, "getting timestamp"); }

      /**

      • Get an InputStream so that the Runtime can build a
      • template with it.
        *
      • @param name name of template
      • @return InputStream containing template
        */
        public synchronized InputStream getResourceStream( String name )
        throws ResourceNotFoundException
        {
        if (name == null || name.length() == 0) { throw new ResourceNotFoundException ("Need to specify a template name!"); }

      try
      {
      Connection conn = openDbConnection();

      try
      {
      ResultSet rs = readData(conn, templateColumn, name);

      try {
      if (rs.next())

      { String strField = rs.getString(templateColumn); return new StringBufferInputStream(strField); //return new // BufferedInputStream(rs.getAsciiStream (templateColumn)); }

      else

      { String msg = "DataSourceResourceLoader Error: cannot find resource " + name; Runtime.error(msg ); throw new ResourceNotFoundException (msg); }

      }
      finally

      { rs.close(); }
      }
      finally
      { closeDbConnection(conn); }
      }
      catch(Exception e)
      { String msg = "DataSourceResourceLoader Error: database problem trying to load resource " + name + ": " + e.toString(); Runtime.error( msg ); throw new ResourceNotFoundException (msg); }

      }

      /**
      * Fetches the last modification time of the resource
      *
      * @param resource Resource object we are finding timestamp of
      * @param i_operation string for logging, indicating caller's intention
      *
      * @return timestamp as long
      */
      private long readLastModified(Resource resource, String i_operation)
      {
      /*
      * get the template name from the resource
      */

      String name = resource.getName();
      try
      {
      Connection conn = openDbConnection();

      try
      {
      ResultSet rs = readData(conn, timestampColumn, name);
      try
      {
      if (rs.next())
      { return rs.getTimestamp(timestampColumn).getTime(); }
      else
      { Runtime.error("DataSourceResourceLoader Error: while " + i_operation + " could not find resource " + name); }
      }
      finally
      { rs.close(); }

      }
      finally

      { closeDbConnection(conn); }

      }
      catch(Exception e)

      { Runtime.error( "DataSourceResourceLoader Error: error while " + i_operation + " when trying to load resource " + name + ": " + e.toString() ); }

      return 0;
      }

      /**

      • gets connection to the datasource specified through the configuration
      • parameters.
        *
      • @return connection
        */
        private Connection openDbConnection()
        throws Exception
        {
        if(ctx == null) { ctx = new InitialContext(); }

      if(dataSource == null)

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

      return dataSource.getConnection();
      }

      /**

      • Closes connection to the datasource
        */
        private void closeDbConnection(Connection conn)
        Unknown macro: { try { conn.close(); } catch (Exception e) { Runtime.info( "DataSourceResourceLoader Quirk: problem when closing connection: " + e.toString()); } }

      /**

      • Reads the data from the datasource. It simply does the following
        query :
      • <br>
      • SELECT <i>columnNames</i> FROM <i>tableName</i> WHERE <i>keyColumn</i>
      • = '<i>templateName</i>'
      • <br>
      • where <i>keyColumn</i> is a class member set in init()
        *
      • @param conn connection to datasource
      • @param columnNames columns to fetch from datasource
      • @param templateName name of template to fetch
      • @return result set from query
        */
        private ResultSet readData(Connection conn, String columnNames, String
        templateName)
        throws SQLException { Statement stmt = conn.createStatement(); String sql = "SELECT " + columnNames + " FROM " + tableName + " WHERE " + keyColumn + " = '" + templateName + "'"; return stmt.executeQuery(sql); }

        }

      Attachments

        Activity

          People

            Unassigned Unassigned
            mangvlad@yahoo.com Vlad Mangeym
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: