Sunday, May 8, 2016

Changing the catalog on a JdbcTemplate (with Spring)

I had a requirement to change the catalog (i.e. database) with JdbcTemplate. I searched around for a while for an answer and, as is often the case, found a solution scattered across several Stack Overflow and other posts. My configuration is:
  • Spring Framework 4.2.5.RELEASE
  • spring-jdbc (for JdbcTemplate)
  • tomcat-jdbc 8.0.18 (for org.apache.tomcat.jdbc.pool.DataSource)

The key to making this all work is to to extend Spring's DelegatingDataSource and override getConnection() to set the catalog you want:

public class CatalogSpecificDataSource extends DelegatingDataSource {

    private final String catalog;

    public CatalogSpecificDataSource(DataSource orig, String catalog) {
        super(orig);
        this.catalog = catalog;
    }

    @Override
    public Connection getConnection() throws SQLException {
        Connection conn = super.getConnection();
        conn.setCatalog(catalog);
        return conn;
    }
}

The next problem is cleanup: how do you ensure that the connection is reset to the default catalog once it's placed into the pool? The answer is in the tomcat connection pool configuration:

    PoolProperties p = new PoolProperties();
    p.setDefaultCatalog("customers");
    /*
     * set your connection properties here - driver, connection string, etc.
     * then, when you're done with that, add the interceptors
     */
    p.setJdbcInterceptors(
        org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.class.getName() + ";" +
        org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer.class.getName());
    DataSource datasource = new DataSource();
    datasource.setPoolProperties(p);

The ConnectionState interceptor remembers if you changed the catalog and will set it back. When you create your JdbcTemplate you can now:

    JdbcTemplate t = new CatalogDataSource(realDataSource, "someOtherCatalog");

or use Spring's idea of assisted injection. To do that:

Step 1. Create a factory interface

public interface CatalogSpecificDataSourceFactory {
    javax.sql.DataSource getDatasource(String catalog);
}

Step 2. Create a spring bean configuration:

    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public CatalogSpecificDataSourceFactory getCatalogSpecificDatasourceFactory() {
        return catalog -> new CatalogSpecificDataSource(getCatalogSpecificDatasource(), catalog);
    }

Step 3. When you want to use it, inject a CatalogSpecificDataSourceFactory then use it to create your Datasource:

    DataSource ds = catalogSpecificDataSoruceFactory.getCatalogSpecificDatasource("booger");
    JdbcTemplate t = new JdbcTemplate(ds);

Or, if you want to get even fancier, set up another assisted factory. In my case, following the assisted injection pattern once again:

    public interface BatchMissionWriterFactory {
        BatchMissionWriter create(String databaseName);
    }

    /* then, in the config: */
    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public BatchWidgetWriterFactory getBatchMissionWriterFactory()
    {
        return catalog -> new BatchWidgetWriterFactory (getCatalogDataSourceFactory().getCatalogSpecificDatasource(catalog));
    }

As usual, hope this is helpful to someone - feedback welcome.

Saturday, January 9, 2016

Reverse engineering a hot tub

I changed the water in my hot tub today and so I had a lot of time on my hands, so I took the controller cover off and tried to figure out how it works. My main purpose was to try to figure out how the control panel interfaces, mainly so that I can contemplate some kind of remote monitoring interface. I know that some models of Balboa controllers have WiFi options, so I figured there must be a communications interface somewhere. There definitely is. The existing (very simple) control panel is connected via an 8-pin RJ-45, and there's a spare one right next to it. There is one removable chip on the board labeled with something looking like a version number. I peeled the sticker off and, surprise it's a PIC18F2420 microcontroller. That's great - I already have programming tools and a C compiler for that. My next step is to try to find a schematic for this board. If I can do that then the feasibility of entirely replacing the control software is high. The hardest part probably would be figuring out how to talk to their existing control panel.

Monday, November 2, 2015

Angular Directives as ES6 Classes part 2 - Scopes

Expanding on my previous post about writing directives as ES6 classes, I had a reason today to figure out scope-to-object binding. The situation is as follows. I have an ng-view with a template that includes nvd3:

    <graph tag='tag_identifier'>
        <nvd3 options='hist.options' data='hist.data' api='hist.api' ...>
    </graph>


The 'tag' attribute is an identifier for the thing being graphed (it will be fetched using ngResource) and 'api' is a reference to the nvd3 api. I will need this to call methods, such as refresh(), inside the nvd3 directive, so I have to pass these through. Inside nvd3, the scope is declared like this:
    scope: {
        data: '=',
        options: '=',
        api: '=?',
        events: '=?',
        config: '=?'
    }
but I don't want data, options, and api bound to my scope, I want them bound to my controller. The answer is described pretty well by Pascal Precht in his post Exploring Angular 1.3: Binding to Directive Controllers. This works equally well in Angular 1.4.7. I modified my registration function as follows:

    static register(module) {
        module.directive('graph', [ ()=> {
            return {
                restrict: 'AE',
                transclude: false,
                replace: true,
                controller: GraphDirectiveController,
                controllerAs: 'hist',
                scope: {}, /* true, false, or isolate */
                bindToController: {
                    'tag': '@tag',
                    'api': '=api'
                },
                templateUrl: "views/graph_widget.html",
                link: function (scope, elem, attrs, ctrl) {
                    /* set 'options' and 'data': */
                    ctrl.initGraphOptions();
                }
            };
        }]);
    }
When it comes to the lifecycle, three things are going to happen:
  • Instantiation - first, angular will create an instance of your controller
  • Setters - next, it will bind what used to be a scope to your controller instance
  • link() - this is your chance to do any post-initialization after bindings are set up
Whatever you do, you should definitely not depend on your setters getting called in any particular order. As a directive author, it would not be very nice of you to ask your users to only write attributes in a certain order. That's the main reason to use the link function just to trigger your controller to do any post-binding setup it needs to do. In my case, this means making sure that the api has been initialied before calling initGraphOptions(), which sets this.data and this.options. (Since we're now binding the scope to the controller, that's it!) Just pay attention to the lifecycle and if things get confusing, remember this is ES6 so you can always add explicit setters to your controller and log what's happening:
    set api(_api) {
        console.log("Setting nvd3 API");
        this._api = _api;
    }

Thursday, October 29, 2015

Angular 1.x services as ES6 classes

Following up on my post of an angular 1.x directive implemented as an ES6 class, I worked up a pattern for services.  It's even simpler than the directive, in that the service has no link function to worry about.

I still make an initClass() method that describes the constructor parameters that need to be injected, but note that the factory method only injects an $injector that it uses to create the service.  As with anything, there are many different ways you can do this.  At the end I'll show you a more brief way to do this.

import 'angular';
/*
 * Angular service as a class
 */
export class DataService {
    static initClass() {
        DataService .$inject = ['$resource', '$q'];
    }

    constructor($resource, $q) {
        this.$resoure = $resource;
        this.$q = $q;
        this.latest = $resource('/data/latest/:name');
        this.tables = $resource('/data/config/default_table');
        this.tags = $resource('/data/tags', {},
            {get: {method: 'GET', isArray: true}});
    }

    getLatestValue(key) {
        var deferred = this.$q.defer();

        this.latest.get({"name": key}).$promise.then( (result) => {
            deferred.resolve(angular.fromJson(angular.toJson(result)));
        }, (error) => {
            deferred.reject(error);
        });

        return deferred.promise;
    }

    getTableConfig() {
        var deferred = this.$q.defer();

        this.tables.get().$promise.then((result) => {
            deferred.resolve(angular.fromJson(angular.toJson(result)));
        }, (error) => {
            deferred.reject(error);
        });

        return deferred.promise;
    }

    getAllTags() {
        var defer = this.$q.defer();
        /* This is an example of how to cache the result */
        if (angular.isDefined(this.tag_cache)) {
            /* Resolve from the cache */
            defer.resolve(tag_cache);
        } else {
            /* Not cached, so resolve from the backend server */
            tags.get().$promise.then( (allTags) => {
                this.tag_cache = {};
                alltags = angular.fromJson(angular.toJson(allTags));
                angular.forEach(allTags, function (t) {
                    tag_cache[t.name] = t;
                });
                defer.resolve(tag_cache);
            }, (error) => {
                defer.reject(error);
            });
        }

        return defer.promise;
    }


    static register(module) {
        module.factory('dataservice', [ '$injector', function($injector) {
            return $injector.instantiate(DataService);
        }]);
    }
}

If you're not like me (and you don't care about having the injectables defined in the source close to the constructor) you can skip initClass() and setting up DataService.$inject and just set them when you call instantiate():

    static register(module) {
        module.factory('dataservice', [ '$injector', function($injector) {
            return $injector.instantiate(DataService, [ '$q', '$resource' ] );
        }]);
    }


Back in app.js you do just as before:

import { DataService } from 'services/dataservice';
...
DataService.register(mainModule);
...

I'm doing all of this with System.js but it's on my short list to try it all with webpack.  I will let you know when that works.

By the way .. if you're wondering what all this fromJson(toJson()) stuff is: the object that comes back from $resource has some extra items in it (beyond what the server returns).  That's the recommend trick for stripping them out.  It's not really necessary to strip them out - in particular, if you use ngResource to POST them back it strips things like $promise out before POSTing.  Again, though, I'm a little OCD about this, especially if I display the raw result using the angular json $filter, so I take the trouble to clean up the object.  It's an optional step.


Wednesday, October 28, 2015

Angular Directives as ES6 Classes

I have been working on having my angular 1.x directive's controllers exist as classes, just like I already do with pure controllers and with services.  I'm honing in on a pattern for directives that I like.

This accomplishes is a few things:
  • Consolidating the directive into a single class reduces global namespace and scope pollution.
  • When you use an ES6 loader (like System.js or webpack) there's just one thing to export/import: the class itself
  • app.js still has to call a registration function, but it's now simpler.  It calls a static class method with one parameter, the module to which to attach the directive.  No longer does app.js have to know what parameters to inject into some directive that's off in a separate file.
  • Writing your controllers as classes encourages you to write directive logic in more testable ways.  Hiding the call to angular's own directive registration keep's the class's business private.  I have found that doing this helps me clarify what's done in the controller vs. the link function, and thinking about that has made my link functions very short (as I think they should be).
  • I still provided a way to hook in to the directive lifecycle to do things like cancel timers, in-process requests to ngResource, etc.

So for the pattern looks like this:

/*
 * A directive called "Reformer", in a Class
 */
export class Reformer{

   static inject() {  Reformer.$inject = [ '$interval', '$q' ];  }
   constructor($interval, $q) {
      this.$interval = $interval;
      this.$q = $q;
   }
   
   tick() {
      console.write("Ping!");
   }

   initialize() {
      this.timer = this.$interval( () => { this.tick() }, 1000);
   }

   destroy() {
      this.$interval.cancel( this.timer );
   }


   static register(module) {
      module.directive('reformer', function () {
         return {
            restrict: 'E',
            templateUrl: 'reformerTemplate.html',
            transclude: false,
            replace: true,
            scope: false,
            controller: Reformer,
            link: function (scope, elem, attrs, ctrl) {
               ctrl.initialize();

               scope.$on('destroy', function () {
                  ctrl.destroy();
                });
             }
          };
      });
   }
}
Reformer.inject();  /* set up injection */

Now, from app.js you just call the static registration method:

import { Reformer } from 'reformer';
Reformer.register(mainModule);


If you're wondering why I did the $inject spec that way, it's because it drives me nuts to have the constructor at one end and the $inject spec at the other end of the file.

This same basic technique works with services, but since they are a little simpler I did not document them here.