title: Specify a `DataSource` factory instead of Tomcat's default
body: <h1>tl;dr</h1>
  
  <p>How do I tell Tomcat 9 to use a <a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/common/PGObjectFactory.html" rel="nofollow noreferrer">Postgres-specific</a> <a href="https://docs.oracle.com/javase/8/docs/api/javax/naming/spi/ObjectFactory.html?is-external=true" rel="nofollow noreferrer">object factory</a> for producing <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/DataSource.html" rel="nofollow noreferrer"><code>DataSource</code></a> object in response to <a href="https://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface" rel="nofollow noreferrer">JNDI</a> query?</p>
  
  <h1>Details</h1>
  
  <p>I can easily get a <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/DataSource.html" rel="nofollow noreferrer"><code>DataSource</code></a> object from <a href="https://en.wikipedia.org/wiki/Apache_Tomcat" rel="nofollow noreferrer">Apache Tomcat</a> 9 by defining an XML file named the same as my context. For example, for a web-app named <code>clepsydra</code>, I create this file:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Context&gt;
      &lt;!-- Domain: DEV, TEST, ACPT, ED, PROD  --&gt;
      &lt;Environment name = "work.basil.example.deployment-mode"
                   description = "Signals whether to run this web-app with development, testing, or production settings."
                   value = "DEV"
                   type = "java.lang.String"
                   override = "false"
                   /&gt;
  
      &lt;Resource
                  name="jdbc/postgres"
                  auth="Container"
                  type="javax.sql.DataSource"
                  driverClassName="org.postgresql.Driver"
                  url="jdbc:postgresql://127.0.0.1:5432/mydb"
                  user="myuser"
                  password="mypasswd"
                  /&gt;
  &lt;/Context&gt;
  </code></pre>
  
  <p>I place that file in my Tomcat “base” folder, in <code>conf</code> folder, in folders I created with engine name <code>Catalina</code> and host name <code>localhost</code>. Tomcat feeds settings into a resource factory to return an instance of <code>DataSource</code>. I can access that instance via JNDI:</p>
  
  <pre><code>Context ctxInitial = new InitialContext();
  DataSource dataSource = 
          ( DataSource ) ctxInitial.lookup( "java:comp/env/jdbc/postgres" )
  ;
  </code></pre>
  
  <p>I do realize that <code>postgres</code> in that lookup string could be something more specific to a particular app. But let's go with <code>postgres</code> for the same of demonstration.</p>
  
  <h2>I want <code>org.postgresql.ds.PGSimpleDataSource</code>, not <code>org.apache.tomcat.dbcp.dbcp2.BasicDataSource</code></h2>
  
  <p>This setup is using <a href="http://tomcat.apache.org/tomcat-9.0-doc/jndi-resources-howto.html#JDBC_Data_Sources" rel="nofollow noreferrer">Tomcat’s own resource factory for JDBC DataSource objects</a>. The underlying class of the returned <code>DataSource</code> class is <code>org.apache.tomcat.dbcp.dbcp2.BasicDataSource</code>. Unfortunately, I do not want a <code>DataSource</code> of that class. I want a <code>DataSource</code> of the class provided by the <a href="https://jdbc.postgresql.org" rel="nofollow noreferrer">JDBC driver from <em>The PostgreSQL Global Development Group</em></a>: <a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/PGSimpleDataSource.html" rel="nofollow noreferrer"><code>org.postgresql.ds.PGSimpleDataSource</code></a>.  </p>
  
  <p>By reading the Tomcat documentation pages, <a href="http://tomcat.apache.org/tomcat-9.0-doc/jndi-resources-howto.html" rel="nofollow noreferrer"><em>JNDI Resources How-To</em></a> and <a href="http://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html" rel="nofollow noreferrer"><em>JNDI Datasource How-To</em></a>, I came to realize that Tomcat allows us to use an alternate factory for these <code>DataSource</code> objects in place of the default factory implementation bundled with Tomcat. Sounds like what I need.</p>
  
  <h2><code>PGObjectFactory</code></h2>
  
  <p>I discovered that the Postgres JDBC driver already comes bundled with such implementations:</p>
  
  <ul>
  <li><a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/common/PGObjectFactory.html" rel="nofollow noreferrer"><code>PGObjectFactory</code></a><br />For simple JDBC connections.</li>
  <li><a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/xa/PGXADataSourceFactory.html" rel="nofollow noreferrer"><code>PGXADataSourceFactory</code></a><br />For <a href="https://en.wikipedia.org/wiki/X/Open_XA" rel="nofollow noreferrer">XA</a>-enabled <code>DataSource</code> implementation, for distributed transactions.</li>
  </ul>
  
  <p>By the way, there is a similar factory built into the driver for OSGi apps, <a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/osgi/PGDataSourceFactory.html" rel="nofollow noreferrer"><code>PGDataSourceFactory</code></a>. I assume that is of no use to me with Tomcat.</p>
  
  <p>So, the <code>PGObjectFactory</code> class implements the interface <a href="https://docs.oracle.com/javase/8/docs/api/javax/naming/spi/ObjectFactory.html?is-external=true" rel="nofollow noreferrer"><code>javax.naming.spi.ObjectFactory</code></a> required by JNDI. </p>
  
  <h3>SPI</h3>
  
  <p>I am guessing that the <code>spi</code> in that package name means the object factories load via the <a href="https://en.wikipedia.org/wiki/Service_provider_interface" rel="nofollow noreferrer"><em>Java Service Provider Interface (SPI)</em></a>. </p>
  
  <p><a href="https://i.stack.imgur.com/3H7bL.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3H7bL.png" alt="screenshot of location of SPI mapping file, and its contents"></a></p>
  
  <p>So I presume that need a SPI mapping file, as discussed in the <a href="https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html" rel="nofollow noreferrer">Oracle Tutorial</a> and in the <a href="https://vaadin.com/docs/v14/flow/advanced/tutorial-service-init-listener.html" rel="nofollow noreferrer">Vaadin documentation</a>. added a <code>META-INF</code> folder to my Vaadin <code>resources</code> folder, and created a <code>services</code> folder further nested there. So in <code>/resources/META-INF/services</code> I created a file named <code>javax.naming.spi.ObjectFactory</code> containing a single line of text, the name of my desired object factory: <code>org.postgresql.ds.common.PGObjectFactory</code>. I even checked inside the Postgres JDBC driver to verify physically the existence and the fully-qualified name of this class.</p>
  
  <h1>Question</h1>
  
  <p>➥ My question is: How do I <strong>tell Tomcat to use <code>PGObjectFactory</code> rather than its default object factory</strong> for producing my <code>DataSource</code> objects for producing connections to my Postgres database?</p>
  
  <h3><code>factory</code> attribute on <code>&lt;Resource&gt;</code> element</h3>
  
  <p>I had hoped it would be as simple as adding a <code>factory</code> attribute (<code>factory="org.postgresql.ds.common.PGObjectFactory"</code>) to my <code>&lt;Resource&gt;</code> element seen above. I got this idea from the Tomcat page, <a href="http://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Resource_Definitions" rel="nofollow noreferrer"><em>The Context Container</em></a>. That page is quite confusing as it focuses on global resource, but I do not need or want to define this <code>DataSource</code> globally. I need this <code>DataSource</code> only for my one web app. </p>
  
  <p>Adding that <code>factory</code> attribute:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Context&gt;
      &lt;!-- Domain: DEV, TEST, ACPT, ED, PROD  --&gt;
      &lt;Environment name = "work.basil.example.deployment-mode"
                   description = "Signals whether to run this web-app with development, testing, or production settings."
                   value = "DEV"
                   type = "java.lang.String"
                   override = "false"
                   /&gt;
  
      &lt;Resource
                  name="jdbc/postgres"
                  auth="Container"
                  type="javax.sql.DataSource"
                  driverClassName="org.postgresql.Driver"
                  url="jdbc:postgresql://127.0.0.1:5432/mydb"
                  user="myuser"
                  password="mypasswd"
                  factory="org.postgresql.ds.common.PGObjectFactory"
                  /&gt;
  &lt;/Context&gt;
  </code></pre>
  
  <p>…fails with my <code>DataSource</code> object being null.</p>
  
  <pre><code>ctxInitial = new InitialContext();
  DataSource dataSource = ( DataSource ) ctxInitial.lookup( "java:comp/env/jdbc/postgres" );
  System.out.println( "dataSource = " + dataSource );
  </code></pre>
  
  <blockquote>
    <p>null</p>
  </blockquote>
  
  <p>Removing that <code>factory="org.postgresql.ds.common.PGObjectFactory"</code> attribute resolves the exception. But then I am back to getting a Tomcat <code>BasicDataSource</code> rather than a Postgres <code>PGSimpleDataSource</code>. Thus my Question here.</p>
  
  <p>I know my <code>Context</code> XML is being loaded successfully because I can access that <code>Environment</code> entry’s value.</p>
  
  <h2>2nd experiment</h2>
  
  <p>I tried this from the top, days later. </p>
  
  <p>I created a new "Plain Java Servlet" flavor Vaadin 14.0.9 project named "datasource-object-factory". </p>
  
  <p>Here is my entire Vaadin web app code. The bottom half is the JNDI lookup.</p>
  
  <pre class="lang-java prettyprint-override"><code>package work.basil.example;
  
  import com.vaadin.flow.component.ClickEvent;
  import com.vaadin.flow.component.button.Button;
  import com.vaadin.flow.component.notification.Notification;
  import com.vaadin.flow.component.orderedlayout.VerticalLayout;
  import com.vaadin.flow.router.Route;
  import com.vaadin.flow.server.PWA;
  
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  import javax.sql.DataSource;
  
  /**
   * The main view contains a button and a click listener.
   */
  @Route ( "" )
  @PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
  public class MainView extends VerticalLayout
  {
  
      public MainView ( )
      {
          Button button = new Button( "Click me" ,
                  event -&gt; Notification.show( "Clicked!" ) );
  
  
          Button lookupButton = new Button( "BASIL - Lookup DataSource" );
          lookupButton.addClickListener( ( ClickEvent &lt; Button &gt; buttonClickEvent ) -&gt; {
              Notification.show( "BASIL - Starting lookup." );
              System.out.println( "BASIL - Starting lookup." );
              this.lookupDataSource();
              Notification.show( "BASIL - Completed lookup." );
              System.out.println( "BASIL - Completed lookup." );
          } );
  
          this.add( button );
          this.add( lookupButton );
      }
  
      private void lookupDataSource ( )
      {
          Context ctxInitial = null;
          try
          {
              ctxInitial = new InitialContext();
  
              // Environment entry.
              String deploymentMode = ( String ) ctxInitial.lookup( "java:comp/env/work.basil.example.deployment-mode" );
              Notification.show( "BASIL - deploymentMode: " + deploymentMode );
              System.out.println( "BASIL - deploymentMode = " + deploymentMode );
  
              // DataSource resource entry.
              DataSource dataSource = ( DataSource ) ctxInitial.lookup( "java:comp/env/jdbc/postgres" );
              Notification.show( "BASIL - dataSource: " + dataSource );
              System.out.println( "BASIL - dataSource = " + dataSource );
          }
          catch ( NamingException e )
          {
              Notification.show( "BASIL - NamingException: " + e );
              System.out.println( "BASIL - NamingException: " + e );
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>To keep things simple, I did not designate a Tomcat "base" folder, instead going with defaults. I did not run from IntelliJ, instead moving my web app’s WAR file manually to the <code>webapps</code> folder.</p>
  
  <p>I downloaded a new version of Tomcat, version 9.0.27. I dragged in the Postgres JDBC jar to the <code>/lib</code> folder. I used the BatChmod app to set the permissions of the Tomcat folder. </p>
  
  <p>To the <code>conf</code> folder, I created the <code>Catalina</code> &amp; <code>localhost</code> folders. In there I created a file named <code>datasource-object-factory.xml</code> with the same contents as seen above.</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Context&gt;
      &lt;!-- Domain: DEV, TEST, ACPT, ED, PROD  --&gt;
      &lt;Environment name = "work.basil.example.deployment-mode"
                   description = "Signals whether to run this web-app with development, testing, or production settings."
                   value = "DEV"
                   type = "java.lang.String"
                   override = "false"
                   /&gt;
  
      &lt;Resource
                  factory="org.postgresql.ds.common.PGObjectFactory"
                  name="jdbc/postgres"
                  auth="Container"
                  type="javax.sql.DataSource"
                  driverClassName="org.postgresql.Driver"
                  url="jdbc:postgresql://127.0.0.1:5432/mydb"
                  user="myuser"
                  password="mypasswd"
                  /&gt;
  &lt;/Context&gt;
  </code></pre>
  
  <p>I copied my web app’s <code>datasource-object-factory.war</code> file to <code>webapps</code> in Tomcat. Lastly, I run Tomcat's <code>/bin/startup.sh</code> and watch the WAR file explode into a folder.</p>
  
  <p>With the <code>factory="org.postgresql.ds.common.PGObjectFactory"</code> attribute on my <code>Resource</code> element, the resulting <code>DataSource</code> is <code>null</code>. </p>
  
  <p>As with my first experiment, I can access the value of the <code>&lt;Environment&gt;</code>, so I know my context-name XML file is being found and processes successfully via JNDI.</p>
  
  <p>Here are the logs on a Google Drive:</p>
  
  <ul>
  <li><a href="https://drive.google.com/open?id=1nAekGy4rJNCgjLAP21M9M6Qan0T8EOmI" rel="nofollow noreferrer">catalina.out</a></li>
  <li><a href="https://drive.google.com/open?id=1-5wBpWCsy6SPbMwY8iGWKbH58dfE4x2m" rel="nofollow noreferrer">catalina.2019-10-18.log</a></li>
  </ul>