Author: avin

  • Install Oracle XE 11g R2 on Ubuntu 12.04

    I’ve recently had a task of enabling Oracle database support for a JRuby on Rails application. To set up an Oracle database for use on a development environment, there were two preferred options – using Oracle DB on a virtual machine or installing Oracle XE locally.

    1. Oracle DB on a virtual machine
    Oracle kindly provide several VirtualBox images for download – I used the Database App Development VM, which comes with Enterprise Edition and SQL Developer, and it’s straightforward to get this running. The only catch is to enable a second network adapter (either Bridged or Host-only) in the VirtualBox settings so the VM is externally addressable. From there, keep in mind the the instance name is orcl, and sys and system passwords are oracle.

    2. Installing Oracle XE locally
    Oracle XE is officially supported on Windows and Red Hat Linux-based systems (the Developer Days VMs are Oracle Linux). Debian Linux-based systems don’t seem to be officially supported, but there have been efforts on installing Oracle XE on Ubuntu (my particular interest). I primarily followed Manish’s guide for the majority of the install process, but had to bring forward the step of setting environment variables. This is because Oracle XE starts immediately after the configuration step (oracle-xe configure). I also referred to another blog for guidance on setting kernel parameters. Here are my modified installation steps:

    Download Oracle Database Express Edition 11g R2

    Unzip archive:

    unzip oracle-xe-11.2.0-1.0.x86_64.rpm.zip
    

    Install the required packages (note I omitted unixodbc as I didn’t require it):

    sudo apt-get install alien libaio1
    

    Convert the RPM package to a DEB package:

    cd Disk1
    sudo alien --scripts oracle-xe-11.2.0-1.0.x86_64.rpm
    

    Create a /sbin/chkconfig file with the following contents (requires root):

    #!/bin/bash
    # Oracle 11gR2 XE installer chkconfig hack for Ubuntu
    file=/etc/init.d/oracle-xe
    if [[ ! `tail -n1 $file | grep INIT` ]]; then
    echo >> $file
    echo '### BEGIN INIT INFO' >> $file
    echo '# Provides: OracleXE' >> $file
    echo '# Required-Start: $remote_fs $syslog' >> $file
    echo '# Required-Stop: $remote_fs $syslog' >> $file
    echo '# Default-Start: 2 3 4 5' >> $file
    echo '# Default-Stop: 0 1 6' >> $file
    echo '# Short-Description: Oracle 11g Express Edition' >> $file
    echo '### END INIT INFO' >> $file
    fi
    update-rc.d oracle-xe defaults 80 01
    

    Set execute privileges for the file:

    sudo chmod 755 /sbin/chkconfig
    

    Create a /etc/sysctl.d/60-oracle.conf file with the following contents (requires root):

    # Oracle 11g XE kernel parameters
    fs.file-max=6815744
    kernel.sem=250 32000 100 128
    kernel.shmmax=1073741824
    net.ipv4.ip_local_port_range=9000 65000
    

    Load the new kernel parameters:

    sudo service procps start
    

    Run the following commands:

    sudo ln -s /usr/bin/awk /bin/awk
    sudo mkdir /var/lock/subsys
    sudo touch /var/lock/subsys/listener
    

    To avoid MEMORY_TARGET errors:

    sudo rm -rf /dev/shm
    sudo mkdir /dev/shm
    sudo mount -t tmpfs shmfs -o size=2048m /dev/shm
    

    Create a /etc/rc2.d/S01shm_load file with the following contents (requires root):

    #!/bin/sh
    case "$1" in
    start) mkdir /var/lock/subsys 2>/dev/null
    	   touch /var/lock/subsys/listener
    	   rm /dev/shm 2>/dev/null
    	   mkdir /dev/shm 2>/dev/null
    	   mount -t tmpfs shmfs -o size=2048m /dev/shm ;;
    *) echo error
       exit 1 ;;
    esac
    

    Set execute privileges for the file:

    sudo chmod 755 /etc/rc2.d/S01shm_load
    

    Install the Oracle XE package:

    sudo dpkg --install oracle-xe_11.2.0-2_amd64.deb
    

    Add the following environment variables to .bashrc:

    export ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe
    export ORACLE_SID=XE
    export NLS_LANG=`$ORACLE_HOME/bin/nls_lang.sh`
    export ORACLE_BASE=/u01/app/oracle
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
    export PATH=$ORACLE_HOME/bin:$PATH
    

    Reload the bash profile:

    source ~/.bashrc
    

    Run the Oracle XE configuration:

    sudo /etc/init.d/oracle-xe configure
    

    Oracle XE should now be installed.

    If anything goes wrong during installation, to uninstall:

    sudo -s
    /etc/init.d/oracle-xe stop
    ps -ef | grep oracle | grep -v grep | awk '{print $2}' | xargs kill
    dpkg --purge oracle-xe
    rm -r /u01
    rm /etc/default/oracle-xe
    update-rc.d -f oracle-xe remove
    

    I’ve used these instructions on two Ubuntu environments (my own VM and an Amazon EC2 instance) and Oracle XE is running happily.

  • History of the Bible

    I ran a different type of study with our church youth group today where we investigated the history of the Bible. It was a combination of a trivia-style and lecture-style presentation and I’ve uploaded the notes I used. It took a little while to put it together – most of the time was spent reading on the Internet and distilling the important (and fun) facts – history can be a little dry. I have included references for most of the resources I used except Wikipedia (which is pretty much the foundation for most of the material). Having done this, I do have a greater appreciation for biblical scholars and academics.

  • Adding CSRF token to jQuery AJAX requests

    When using a jQuery-supported framework such as Backbone, underlying jQuery AJAX requests are typically abstracted at the model layer. To insert Cross-Site Request Forgery (CSRF) tokens or other session data into the request, one method is to proxy a method in the call stack and add the token via an option (example). This does have a disadvantage if you need to call $.ajax directly as you’ll need to again insert the CSRF token as a header option.

    The DRY way? Use jQuery’s ajaxPrefilter API:

    $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
      var token;
      if (!options.crossDomain) {
        token = $('meta[name="csrf-token"]').attr('content');
        if (token) {
          return jqXHR.setRequestHeader('X-CSRF-Token', token);
        }
      }
    });
    
  • GUS Gives

    I was approached two years ago by a colleague from the Queensland Department of Education and Training (DET) to help set up a web application for GUS Gives – a charity portal that collects payments from members and provides detailed analytics for charity organisations. My role was to provide data management support and the first task on the list was creating sample data sets in order to test the report generation functions of the website.

    I had done similar work when I was working at DET of rule-based generation of staff and student data sets. Using the same technique, I developed an application that generated random people/members as a CSV file (file type choice by the application developers). The reference data of first and last names, locations, phone number prefixes, salaries, etc. were from public sources – US Census Bureau, Australian Bureau of Statistics, OpenStreetMap, and Wikipedia.

    Now that GUS Gives looks like it’s a non-starter, I have uploaded the source to Github. The project also contains the data requirements and the collated reference data so the application can run without further dependencies.

  • Parallel Bible

    My 85 year old grandma has been getting into reading various bible translations from her iPad. In order to improve her Hindi reading skills, she was looking for a side-by-side translation of a Malayalam bible and Hindi bible. While we could find Malayalam-English and Hindi-English versions, we couldn’t find a Malayalam-Hindi one that she could access on her computer or iPad.

    I decided to help her out and the result is Parallel Bible. I have also uploaded the source code to Github.

    The application is static site generator using Razor templates – I took this approach as I couldn’t host a Ruby on Rails or .NET website using my current hosting provider. It uses jQuery Mobile as my grandma uses her iPad for the majority of her browsing, and I wanted the site to be reasonably usable on a mobile. To run the application, the bible data itself must be downloaded for the English version, but is screen scraped for the Indian translations. The translations are then merged during the template execution process.

    I did find it interesting that the number of chapters and verses did vary per translation. It was more frequent with the English vs Malayalam where there were quite a few instances of ±1 verse.

  • Reducing Rails asset precompile times on JRuby

    Rails asset precompile times on JRuby are considerably slower compared to MRI. I came across this post which provided suggestions on speeding up the asset precompile task.

    Using the following options – using Node.js instead of therubyrhino for JS compilation, forcing the JVM to 32 bit (although this can be omitted on a 32 bit JVM) and not using JIT compilation – cut my asset precompile time from 4 mins 37 secs to 2 mins 8 secs. Using Node.js contributed to the majority of that time since I’m using a 32 bit VM.

    EXECJS_RUNTIME='Node' JRUBY_OPTS="-J-d32 -X-C" rake assets:precompile
    
  • Silencing noise in the Rails development log

    The standard Rails development log contains a lot of noise that is rarely meaningful for debugging. The Quiet Assets gem is a mandatory part of my Rails development process as it removes the logging noise of the asset pipeline.

    Also, if WEBrick is used as a development server, the following entry is logged for each asset pipeline log entry (whether silenced or not by Quiet Assets):

    WARN Could not determine content-length of response body.
    Set content-length of the response or set Response#chunked = true
    

    While some have suggested monkey-patching WEBrick or installing Thin as an alternate server (which doesn’t work under JRuby), the simplest way to remove those statements is to add WEBrick specifically in your Gemfile:

    gem 'webrick', '~> 1.3.1', group: :development
    
  • Mixing DatabaseCleaner transaction and truncation strategies

    RSpec by default issues a database transactional rollback that is executed after the completion of a block. When using Capybara with the :js option (to enable testing with Selenium or Webkit), the transactional rollback offered by RSpec is unusable as the browser is loaded via a separate thread and has a separate database connection. Thus any uncommitted data cannot be read by the browser.

    Most people suggest employing DatabaseCleaner using a truncation strategy to overcome this deficiency. The performance of cleaning via truncation vs transaction depends on the size of data – with smaller fixtures, transactions are preferable.
    Instead of using one or the other, we can mix strategies to have the best of both worlds:

    config.use_transactional_fixtures = false # Using DatabaseCleaner instead
    
    config.before(:suite) do
    DatabaseCleaner.strategy = :transaction # Default strategy
    DatabaseCleaner.clean_with(:truncation) # Initially clean with truncation
    end
    
    config.before(:each, type: :request) do
    # Swap to truncation as Selenium runs in separate thread with a different
    # database connection
    DatabaseCleaner.strategy = :truncation
    end
    
    config.after(:each, type: :request) do
    # Reset so non-request specs can use transaction
    DatabaseCleaner.strategy = :transaction
    end
    
    config.before(:each) do
    DatabaseCleaner.start
    end
    
    config.after(:each) do
    DatabaseCleaner.clean
    end
    

    On my current test suite of around 461 tests with 73 request specs, this dropped the run time by just over a minute.

  • Mocking instances created via ActiveRecord’s find

    Most Ruby mocking frameworks have the ability to mock a new object created via a constructor. However, when an object is created via ActiveRecord’s find or find_by_* methods, the .new method isn’t invoked. Instead, the .instantiate method is called.

    For example, to specify :instantiate as the object creation method using FlexMock:

    flexmock(Dog).new_instances(:instantiate)
    .should_receive(:bark)
    .at_least.once
    .and_return(:woof)
    
  • Persisting IRB & Rails Console History

    Continuing the theme on customising IRB and Rails Console, add these lines to ~/.irbrc to persist the command history across console sessions:

    require 'irb/ext/save-history'
    IRB.conf[:SAVE_HISTORY] = 100
    IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb_history"