Tuesday, December 9, 2014

Has been quite a long time in entering anything in here - will be updating more regularly with coding issues.

 Since my last entry, I had been involved in writing a pretty extensive iOS 7 app for my job. This took about a year+, and I should have been writing all of my findings from that here as well, but - (whew) - that was a job. :)

This app was an XMPP-based communication app for hospital employees (nurses) to receive/interact/user alarms and alerts much more efficiently and smarter. It is now been taken over by another group, but was invaluable experience.

I had worked on iOS apps before - but not with this intensity or scrutiny to do right, and I learned a great deal more about Obj-C and the environment then I could before just on my own. Really grateful for that.

No reason going back and re-hashing my notes on that, so will just continue on what is coming up and what I work on, having a place to come back for notes.

This will include all of the Java 8 conversion that I have been working on, as well as updates to GlassFish (4), and AngularJS updates.

We are still using pre-release AngularJS for most of our stuff, but it still works great and gets the job done.

That will be changing, and will be converting/upgrading to the latest release (1.3) - totally stoked on that. And with all of the updates from Java 6 -> 8, many more on that as well.

:)

Friday, August 10, 2012

Enabling Sites in Mountain Lion

Seems Mountain Lion removed the default paths to enable the 'Sites' directory for web access in Mountain Lion (10.8). They still included Apache - so easy enough to bring back to norm. Create a configuration file with your username as the filename such as:
/etc/apache2/users/rweeks.conf
File contents:
<Directory "/Users/rweeks/Sites/">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
Then simply restart apache and the dir will be restored:
% sudo apachectl restart

Tuesday, March 27, 2012

Upgrading to angular 1.0.0 - compiler

I have been working on upgrading all of our client side libraries and such that were developed using angular (latest was 0.10.5) to the FCS release coming up (using the latest builds -1.0.0-rc3 as of this post).

There have been some massive changes since 0.10.5, so will be putting some of the updates here as reference.

One of the things that has changed is the initialization/bootstrapping of an angular app.

The majority of our angular based apps are loaded via xhr from OSGi bundles that are serving the content (statically via html streams) and being injected into existing UI framework.

Before this push, we were able to do something similar to:

$('#myContainer').load(url, function(responseText, textStatus, XMLHttpRequest) {
    ...
    angular.compile($('#myContainer'))().$apply();
    ...
});

This has changed now and can be accomplished a couple of ways.

A little background - to be explained in further as they are developed - is that the new upgrade introduces "modules" that are defined to encapsulate how an application should be bootstrapped, configured, and what services can be added.

So say if we have defined a module for the app called 'interfaceSettings':

var interfaceSettingsModule = angular.module('interfaceSettings' ['interfaceApp.services', 'interfaceApp.filters', 'interfaceApp.directives']);

(This is defining an angular module named 'interfaceSettings' that is also injecting the modules 'interfaceApp.services', 'interfaceApp.filters', interfaceApp.directives', which were defined previously).

So, for automatic bootstrapping, we can define our app directly in the element that is the root element of the app:

<div ng-app="interfaceSettings" id="ng-app" ng-controller="...">...</div>

The ng-app directive tells angular that this is the root of the application, and to use the module defined as 'interfaceSettings'.

You will also notice a repeated 'ng-app' call in the 'id' tag. This is to allow IE 7/8 to recognize this as well, since there are some issues with earlier releases not recognizing the app call (just dreaming of the day when don't have to do so much crap just because of IE shortcomings. They should have to do community service forever for releasing the normal junk they usually do. sigh....)

We can also still manually bootstrap it by taking the root element:

angular.bootstrap($('#interface_myContainer_container'),['interfaceSettings']);

Which will take the root element and compile it, using the module(s) indicated in the array.

This actually gives us some great flexibility in definitions, but will also allow us to just load in external apps and embed anywhere inside the existing framework.

To allow us to do this automatic bootstrapping though, we have to make sure to load in the angular lib inside the main framework. Before, the reference to the library was loaded with each loaded app.

A near future goal is to have the ability to define different elements of the web-based GUI based on OSGi bundles and angular as well, so this change to include the library by default is a good one anyway.

Tuesday, November 29, 2011

Auto install of Java on Ubuntu

We recently had an issue on our appliances for builds that was causing a problem when it came time to install Java via apt-get on Ubuntu.

Found this gem that should save a lot of time:

sudo sh -c ‘echo sun-java6-jre shared/accepted-sun-dlj-v1-1 select true | /usr/bin/debconf-set-selections’;

sudo apt-get install —yes sun-java6-jre;

http://www.davidpashley.com/blog/debian/java-license

Wednesday, November 9, 2011

Change in 'angular.compile()'

In our app we load in partial GUI's via OSGi bundles that angular then compiles/bootstraps after the pull from the bundle via calls similar to:

$('#eiAuditUI').load(eiAuditURL, function(responseText, textStatus, XMLHttpRequest) {
    if (textStatus == 'error') {
        $('#eiAuditUI').html('Unable to contact the Audit Tool.
');
    } else {
        angular.compile($('#eiAuditUI'))();
    }
});
$('#eiAuditUI').show();

This was with angular up to 0.10.3. As of 0.10.4, needed to apply '$apply()' to the compiled element, since angular.compile does not call $apply on the linked scope.

Being that we are bootstrapping the partial being pulled in itself, we need to now append the calls to compile from:

angular.compile($('#eiAuditUI'))();

to:

angular.compile($('#eiAuditUI'))().$apply();

What this was causing was that when the scope was called/compiled, the rendering didn't happen as was previously, unless some even happened, such as starting to fill out a form or moving a select list.

With the above change - everything back to normal.

Monday, October 10, 2011

angular select list options

Angular allows filling in of selection lists via different data structures, but can be a bit confusing as to how to build them sometimes.

I have had to make certain data structures available as angular services to our developers, making the calls as simple as possible.

Say we have a straight JSON object such as:

{
  "33":"Bed",
  "44":"Call",
  "66":"Emergency"
}

I take this call from an $xhr request:

getDatasets: function(ctrl) {
  $xhr("GET", CURRENT_DATASETS_URL,
    function (code, response) {
      processDatasets(ctrl, code, response);
    },
    function (code, response) {
      processDatasets(ctrl, code, {});
      showError("Unable to load ...");
    }
)};

and inside 'processDatasets()' method - manipulate data structure so turns out such as:

self.datasetsArray = [
  {label:"Bed",value:33},
  {label:"Call",value:44},
  {label:"Emergency",value:66}
]

We can render a select list easily with:

<select name="dataset" ng:model="form.dataset" required 
        ng:options="ds.value as ds.label for ds in datasetsArray">
</select>

Giving us the labels and values needed.

Another challenge for this came up as wanting to utilize groups for values as well. For example, a structure coming in from a service call would come back as:

{
  "MainMenu":  {"Menu Item 1": 5},
  "AlertMenu": {"Alert Item 1": 9, 
                "Alert Item 2": 2, 
                "Alert Item 3": 7, 
                "Alert Item 4": 23
  },
  "TrackMenu": {"Track Item 1": 55, 
                "Track Item 2": 1, 
                "Track Item 3": 8, 
                "Track Item 4": 6, 
                "Track Item 5": 10, 
                "Track Item 6": 3
  }
}

Manipulating this structure in our callback from the service (like above), we create an array such as:

var menuGroups = [
  {group:"MainMenu", label:"Menu Item 1", value:5},
  {group:"AlertMenu", label:"Alert Item 1", value:9},
  {group:"AlertMenu", label:"Alert Item 2", value:2},
  ...
  {group:"TrackMenu", label:"Track Item 1", value:55},
  {group:"TrackMenu", label:"Track Item 1", value:1},
  ...
]

We can now use this to create a select menu with the 'optgroup' already in place:

<select name="menuPage" ng:model="form.menuPage" ng:format="number" required 
        ng:options="mp.value as mp.label group by mp.group for mp in menuGroups">
  <option></option>
</select>

** Updated for changes in form processing with angular 0.10.3+.

Thursday, September 29, 2011

Love of angular

Over the past few months (18+ months now) I have been working on a project that has become pretty involved, being a hybrid Java EE/OSGi app, with a lot of javascript and "trickery" involved.

One of the core goals of this project was to have a central "Core" app that would be the persistence layer, with the ability to create pluggable interfaces that could interact with this layer.

The "Core" layer also houses an Admin Console, which an admin uses to setup and administer these interfaces, so that they can communicate properly.

The legacy app of this involved a combination of Ruby On Rails to house the entire admin console and send information via JMS to the standalone interfaces that were each running in their own space.

When an interface was to be created, that involved not only writing the java code for the interface itself, but much code to be written in the ruby side of the app to support this, including the GUI that would be specific to the interface in question.

With the new architecture, we wanted to make sure that when interfaces are built, that they be completely self contained, so if there were updates needed, only the interface bundle itself would need to be deployed, not any of the surrounding parts.

A huge challenge to me was not only setting up the framework to handle the communications between these interfaces and the core app, but the GUI piece was proving to be an immense challenge.

Then came 'angular'.

I had been following it for a while. One of the guys on my team at Sun (Igor!) had went to work for Google, and I saw this library he was working on - and started messing around with it.

It is an *incredible* library for building client side apps.

Creating a resources bundle that housed the angular library and our custom libraries that the interface bundles could rely on (via manual registration of them via the OSGi HttpService), we were able to make the persistence of the interface data straight JSON objects (which the core app doesn't care about - only cares about saving the data itself), and have that pulled back and manipulated via angular binding.

I will be following up with some of the details of the work that was done, which could be a valuable reference.

I couldn't be happier with how this library has helped in this transition, and made it possible to build the beginnings of a rich SDK for interface developers to use.

Monday, June 20, 2011

@ManagedBean inside OSGi bundle in GlassFish (3.1) - part 2

In previous post talked about utilizing javax.annotation.ManagedBean to create a ManagedBean in an OSGi bundle deployed in GlassFish.

A different (better) route would be to use CDI (Contexts and Dependency Injection) and utilize @Inject annotations instead of @Resource and @EJB for injecting the resources.

For this to work, there must be a 'beans.xml' file present. According to the docs:

An application that uses CDI must have a file named beans.xml. The file can be completely empty (it has content only in certain limited situations), but it must be present.

To make this possible in our bundles, added a 'META-INF' directory to the 'src' dir, with an empty 'beans.xml' file underneath.

Then in our bnd definition file (which builds the OSGi bundle for us), we define the resource to be included in our bundle:

Include-Resource:  META-INF/beans.xml=src/META-INF/beans.xml

With this in place, we no longer need to reference the 'com.sun.ejb.containers, com.sun.ejb.spi.io' libraries in our 'Import-Package' entry (since we are not using the ManagedBean annotation directly).

We can now replace all the @EJB and @Resource calls to @Inject.

@ManagedBean inside OSGi bundle in GlassFish (3.1)

Was struggling getting a @ManagedBean to be able compile correctly under GlassFish - needed to add the following packages to the Import-Package entry of the Manifest:

com.sun.ejb.containers,com.sun.ejb.spi.io

This allowed us to have a ManagedBean in the bundle.

For example - want to have a @Singleton class for some processing.

@Singleton
public class TestSingleton {
    public String testMySingleton() {
        return "This is a test from my singleton!";
    }
}

(this would be a javax.annotation.ManagedBean, not a Faces ManagedBean):

@ManagedBean
public class SingBean {
    @EJB
    private TestSingleton testSingleton;

and for testing purposes - within the MDB:

@MessageDriven(mappedName = "jms/MyQueue", activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class ExtIncMDB {
    @Resource
    SingBean myBean;

Coming back...

Haven't written to this blog in a while - getting caught up with getting the project I have been working on working, but with some of the issues we are finding and the solutions to those issues, I really need to document them for future reference.

I have also been getting deeper into iOS and Android development, and have figured out some cool things there to start documenting and keeping around.

So major posts coming regarding Java EE 6/OSGi hybrid apps, iOS and Android development (as well as anything else I want to blab about just to keep record).

If others can find some of the snippets to help like I did searching around - would be great.

Friday, August 20, 2010

mysql error: Got a packet bigger than 'max_allowed_packet' bytes

I had recently been working on a project where I was getting db dumps (using mysqldump) - and having issues importing the db back into a fresh install of mysql:
% mysql -u [username] -p [database] < sqlDump.sql 
Enter password: 
ERROR 1153 (08S01) at line 1191: Got a packet bigger than 'max_allowed_packet' bytes
Which seemed related to blobs containing larger pdf files mostly (in my case at least). In trying to figure out how to get past this - seeing the default size for 'max_allowed_packet' was too low - in the daemon side (mysqld):
mysql> select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|              1048576 | 
+----------------------+
To fix this, I used the configuration files (optional) - located on my local system (OS X - Snow Leopard) at: /usr/local/mysql/support-files/my-xxx.cnf. I copied one of these (the 'my-small.cnf' specifically) to /etc/my.cnf, and edited the file to increase the default for the server to 64M:
# The MySQL server
[mysqld]
port            = 3306
socket          = /tmp/mysql.sock
skip-locking
key_buffer = 16K
max_allowed_packet = 64M
...
This will increase the limit (globally - since the file is located in /etc/my.cnf and not in ~/.my.cnf) for the server. This increased limit can then be seen here after a server restart (64*1024*1024):
mysql> select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|             67108864 | 
+----------------------+
After trying to re-import my file, I found out I also needed to have this via the client as well while importing, since setting the above limit did not seem to solve my issue:
%  mysql --max_allowed_packet=64M -u  [username] -p [database] < sqlDump.sql 

This finally worked in getting past the limitation I was hitting.

Maybe this will be a quick fix help to someone else running into this problem as well.

Blank lines in JSP output

I had posted some small entries on my old blog at Sun, and wanted to transfer some of those here for reference sake.


I was having an issue with jsp outputting blank lines at the top of output - and if the contentType being text/xml - causing parsing error being that the <?xml... directive not being the first line - causing the exception:

'XML or text declaration not at start of entity'

Come to find out, this had been addressed in JSP2.1 - but was a bit hard to track down.

Adding the line:

<%@page trimDirectiveWhitespaces="true"%>

to the top of your jsp will remove these, thus letting the XML feeds parse correctly.

Small fix - but has cured some headache in creating some feed proxies.

Wednesday, August 18, 2010

OSGi, JavaMail, and the mailcap issue

When developing some of the components for our application, I have been seeing some issues with ClassLoaders when creating them as OSGi bundles.

One main case that had me curious for a while was using JavaMail inside an OSGi bundle, and having to send a multipart mail.

The issue was - JavaMail relies on JAF (the activation framework), which houses a file (mailcap) in it's META-INF directory. So, if these (the javamail and jaf) are stored in separate bundles, then javamail cannot access the configuration file to determine which MIME types it can handle, and thus throwing an UnsupportedDataTypeException:

javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/alternative; 

An UnsupportedDataTypeException usually occurs because JAF cannot find the DataContentHandler (DCH) for a given MIME type by reading the mailcap.

Glassfish 3 actually bundles these together in one bundle (modules/mail.jar), but I was still having the issue described above.

So I went down the path trying to figure out what in the world I could do to get past this. You can't really export resources like you do packages in the manifest, so importing into my bnd file didn't work, and even trying to manually force new mailcaps (which seemed to work elsewhere) didn't work:

MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed; x-java-fallback-entry=true");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);

This is basically just pushing through exactly what is in the mailcap file directly. But - this didn't work either. Odd...

I then went as far as create a new instance of the specific handler that is being used, and testing the support for that DataFlavor:

DataContentHandler dhmm = new com.sun.mail.handlers.multipart_mixed();
DataFlavor[] dtf = dhmm.getTransferDataFlavors();
for (DataFlavor tmpdf : dtf) {
 log.debug("   isSupported? " + tmpdf.getMimeType() + ":" + message.getDataHandler().isDataFlavorSupported(tmpdf));
}

And it shows it is supported: isSupported? multipart/mixed:true

Yet - when sending the message, same Exception. Ugh...

Finally, Sahoo (from the Glassfish team) gave me a suggestion of manipulating the ClassLoaders when I needed to to make the calls, saving the current ClassLoader so it can be put back into place.

In our bundle, we create the session and send the message in two different methods, so this had to be implemented twice, but finally - it worked!

// There is an issue in the OSGi framework preventing the MailCap
// from loading correctly. When getting the session here,
// temporarily set the ClassLoader to the loader inside the bundle
// that houses javax.mail. Reset at the end.
ClassLoader tcl = Thread.currentThread().getContextClassLoader();

try {
    // Set the ClassLoader to the javax.mail bundle loader.
    Thread.currentThread().setContextClassLoader(javax.mail.Session.class.getClassLoader());

    ...
} finally {
    // Reset the ClassLoader where it should be.
    Thread.currentThread().setContextClassLoader(tcl);
}

This is now working fine. I was a bit leery about mucking with the ClassLoaders in here - which was an issue with using JRuby code inside OSGi bundles as well, but this seems to be OK in that we are temporarily changing and immediately changing back.

The Pollers - MDB, Singleton, Glassfish, JRuby

It has been a bit since last posting - has been a whirlwind since then. :)

Ended up utilizing MDBs to be able to get past the issue with the way the app was using the pollers to listen to certain events in the application (observer) and processing them.

Keeping the original logic in ruby, I ended up using a Singleton Bean to create and store a rails instance that was shared with the same VM as the rest of the app. Also slated this Singleton to be instantiated at Startup (@Startup) so it would be available when the rest of the app was ready:

@Singleton
@Startup
public class EIScriptingContainer {


With this, created a separate MDBs for each ruby poller, giving commands via the message selectors to determine which poller to utilize. This gave us the ability to use a central "SystemManager" to send messages to a Topic that the MDBs were listening to, and depending on the serviceName, would know what to do:

@MessageDriven(mappedName = "jms/SysMgrReq", activationConfig = {
    @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "serviceName='EventNotifier' AND messageAction IS NOT NULL"),
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic")
})

I then bundled all of these up in a single jar and deployed as an app to GF.

A big issue was the fact that sometimes we needed to have more than one instance of a poller running, but when re-loading the original script (via the JRuby ScriptingContainer), all of the Rails stack was loading. That was where the Singleton instance of the ScriptingContainer was created and pre-loaded with the rails environment, and this was utilized each time in the stopping, starting, starting additional instance, and refreshing these pollers.

Tuesday, April 6, 2010

JRuby, JMS and Pollers

A common way in Ruby to utilize messaging is to use ActiveMessaging, and for ActiveMessaging to listen to queues/topics, etc. - implement "pollers", which will run as separate processes and listen/react to the messages.

ActiveMessaging takes these processors, and runs them in the environment (which is started externally) - creating new processes.

In trying to get everything in one box (VM), we needed a way to get around this, on top of using ActiveMessaging as a whole (since most of the app will be converted to java eventually).

In doing this, we took the poller processors and turned them into MessageListeners:
class QueueProcessor  < ApplicationProcessor
  include javax.jms.MessageListener

defined them as classes, and made sure they could run on their own and still function much like they did before:

class QueueProcessor  < ApplicationProcessor
  include javax.jms.MessageListener

  def initialize
    ...
  end

  def run
    # Instantiate a Sun Message Queue ConnectionFactory
    queueConnFactory = ConnectionFactory.new

    # Create a connection to the Sun Message Queue Message service
    queueConn = queueConnFactory.createConnection()

    # Create a session within the connection 
    queueSess = queueConn.createSession(false, Session::AUTO_ACKNOWLEDGE)

    # Instantiate a System Message Queue Destination
    # ToDo: Need to lookup via JNDI or some sort of aliasing.
    queueQueue = Queue.new("MyQueue")

    # Create a message consumer and listener
    queueMsgConsumer = queueSess.createConsumer(queueQueue)
    queueMsgConsumer.setMessageListener(self);

    # Start the Connection
    queueConn.start()
  end

  def onMessage(message)
    begin
      # Process our message as needed
      ...
    rescue
      @queue_logger.error "QueueProcessor caught #{$!} \n #{$!.backtrace.join("\n")}"
      ...
    end
  end
end

### Make sure to only run this process, and not any others.
if __FILE__ == $0
 queueProc = QueueProcessor.new
 queueProc.run
end

The next step in getting this to run separately, yet still in the same VM? I am thinking OSGi and ScriptEngine - so onto the next step to see if that is possible. :)

JRuby, JMS, OpenMQ, and Serialization

In working towards getting the current application running entirely within the Glassfish context, one of the issues I had to do was get the current implementation of the communication to the message queues away from ActiveMessaging/ActiveMQ into using JMS/OpenMQ.

There are a lot of fingers that ActiveMessaging has in here, so we will have to do some cleanup, but something that was causing me a few issues we figured out today was with the way the serializing of objects and placing in the queue as TextMessages was getting a bit out of whack when we converted some of the publishing models of ActiveMessaging to the sending of the message via JMS.

The serialization (which we are using Marshal dump/load for the ruby objects) was becoming an instance of TextMessageImpl (Java::ComSunMessagingJmqJmsclient::TextMessageImpl).

Simply pulling the text out of this on the jruby side fixed for us:
message = deserialize(message.getText())
and the deserialization worked ok.

Tuesday, March 30, 2010

Joe Satriani Guitar Clinic

My son and I got to see an incredible guitar clinic put on by Joe Satriani at Sweetwater on March 27th. Was a great time! He played a lot of the Surfing album, and discussed the theory behind the songs.

Some of the videos I was able to get from my cell phone are posted on my YouTube channel.

Converting Ruby/Rails JMS to JRuby/Glassfish/OpenMQ

I have been working lately on trying to get the existing stack - which is a Ruby on Rails app utilizing ActiveMessaging with ActiveMQ via Stomp - and getting it to work completely within a Glassfish JRuby container, using JMS and OpenMQ instead.

It has been challenging for sure, but am making progress little by little. I will be posting any progress I make soon after I get some of the issues ironed out.

Some of the issues I am working on include:
  • Converting current separate daemonized pollers that are the message queue listeners into either jruby pollers or separate jruby classes that run in the same VM as the main app itself (as opposed to running a separate 'jruby' call of some sort).
  • Getting the messaging.rb/broker.yml to use jms and jndi lookups for the ConnectionFactories.
  • How to use/register OSGi bundles in the environment so that they can be queried and monitored.
  • Converting existing component/plugins from a combination of java component (which use sysjava as daemon wrappers) and ruby components into OSGi bundle plugins.
  • Many more... :)
 I will update the solutions as they are worked through.

Wednesday, March 17, 2010

JDBC/JNDI Pooling with a JRuby/Rails app

In working on the transition of this rails app over to the JRuby/Glassfish camp, one of the things I needed to take advantage of was using jdbc/jndi database pooling and configurations.

Of course, using rails, the application was using ActiveRecord for it's DB/ORB interactions, and in researching, the steps needed to get this setup were:
  1. Create the JDBC connection pool
  2. Create the resource with a JNDI name
  3. Update the database.yml
  4. Configure ActiveRecord for disconnects
I also needed to download and put the postgresql jdbc driver in place ($domain/lib/ext/ - using the JDBC version 4 driver).

In looking at the jdbc templates included with Glassfish (glassfish/lib/install/templates/resources/jdbc), I attempted to use the template for my driver (postgresql_type4_datasource.xml). This was causing issues using the 'url' property, so ended up using asadmin to create, using serverName and databaseName as properties.

Starting up the asadmin interactive utility:


asadmin> create-jdbc-connection-pool
--datasourceclassname org.postgresql.ds.PGConnectionPoolDataSource
--restype javax.sql.ConnectionPoolDataSource
--property user=XXX:password=XXX:serverName=localhost:databaseName=extension_dev extensionDevPool

Command create-jdbc-connection-pool executed successfully.
asadmin> create-jdbc-resource --connectionpoolid extensionDevPool jndiExtensionDev

Command create-jdbc-resource executed successfully.
asadmin> list-jdbc-connection-pools
__TimerPool
DerbyPool
extensionDevPool

Command list-jdbc-connection-pools executed successfully.

asadmin> list-jdbc-resources
jdbc/__TimerPool
jdbc/__default
jndiExtensionDev

Command list-jdbc-resources executed successfully.

asadmin> ping-connection-pool extensionDevPool

Command ping-connection-pool executed successfully.
I created separate pools/resources for dev/test/production - which will be commented accordingly for now in the domain.xml file.

Next came setting up the database.yml file to use jndi instead of the regular ActiveRecord drivers. There are some excellent resources on the web for getting this done, but had to do some digging to get this correct.

One of the issues in setting this up correctly was, that especially during development and testing, we are using the jruby console (jruby -S script/console) to create and activate objects and events, which in turn looks at the database.yml file to get its connection.

This was hurting me because once set to use jndi, none of these settings were setup correctly and I would continue to get connection issues as well as the jms missing class issues.

So, to fix, in the database.yml file, we not only test for the RAILS_ENV to be java (or the JRUBY_VERSION to be set), but we needed to test to see if we were in a servlet context (ala Glassfish) as well as to use jndi based connections or regular connections.

So, our database.yml file ended up looking like:
defaults: &defaults
<% jdbc = defined?(JRUBY_VERSION) ? 'jdbc' : '' %>
<% if defined?($servlet_context) %>
adapter: jdbc
driver: org.postgresql.Driver
<% else %>
adapter: <%= jdbc %>postgresql
<% end %>
username: xxx
password: xxx
host: localhost

development:
<% if defined?($servlet_context) %>
jndi: jndiExtensionDev
<% end %>
database: extension_dev
<<: *defaults

test:
<% if defined?($servlet_context) %>
jndi: jndiExtensionTest
<% end %>
database: extension_test
<<: *defaults

production:
<% if defined?($servlet_context) %>
jndi: jndiExtensionProd
<% end %>
database: extension_prod
<<: *defaults

This enabled us to access the db in our app as well as run the console and connect correctly.

We now need to configure ActiveRecord to disconnect after every query - which was not needed before since we are now using JDBC to manage the connection persistence. (See resources below for links to some of the sites that were used to research all of this).
# config/initializers/close_connections.rb
if defined?($servlet_context)
require 'action_controller/dispatcher'

ActionController::Dispatcher.after_dispatch do
ActiveRecord::Base.clear_active_connections!
end
end
Some of the excellent resources I used:

RoR App to run under JRuby

After deciding on the platform, one of the big things to get accomplished was getting the current application to run inside a JRuby container inside Glassfish.

This was a bit challenging at first, and it still isn't all quite there, but the main core of the app is now running in there, with a few changes.

We are not deploying via a war file (yet) - since we are just building this, but deploying as a directory (for development) from my git workspace to build up the configuration steps.

There were quite a few challenges (and more to come) - some of which were based on the gem compatibilities between ruby and jruby - more notably libxml and libxslt - which rely on native libraries.

Before I got here, this was tackled a little bit by another engineer here, Rich, who created an xml_lib.rb that wrapped what we needed via the libxml and libxslt libraries to utilize their java counterparts - so that was a big boost for this process.

We will probably replace those with more robust ones if we need in the future, but this library works great for what we are using it for at the moment. There is a port of libxml-ruby called libxml-jruby, written by Dylan Vaughn, which will do what we need - and we will probably pull out the XSLT functions that Rich wrote and separate the lib this way.

A big part of this was getting the correct gems installed and being used for jruby, and adjustments in the configurations for the current app to separate what to load if running under jruby as opposed to ruby.

Example - in 'conf/environment.rb' - the config gems were separated out:
if RUBY_PLATFORM =~ /java/
config.gem 'jdbc-postgres', :lib => 'jdbc/postgres'
config.gem 'activerecord-jdbc-adapter', :lib => 'jdbc_adapter'
config.gem 'activerecord-jdbcpostgresql-adapter',
:lib => 'active_record/connection_adapters/jdbcpostgresql_adapter'
else
config.gem 'pg', :version => '0.8.0'
config.gem 'libxml-ruby', :lib => 'xml/libxml', :version => '1.1.3'
config.gem 'libxslt-ruby', :lib => 'libxslt', :version => '0.9.2'
end
After installing and setting up Glassfish with a new domain and installing jruby, needed to make the jruby container available to Glassfish:
% asadmin create-domain --adminport 4848 extension
...
...
Command create-domain executed successfully.

% asadmin configure-jruby-container --jruby-home=/usr/local/jruby
and then deployed my current app (being in the parent dir of the rails app directory)
% asadmin deploy --property jruby.rackEnv=development core/

Starting my domain here, I was able to access the app successfully via the context of the app name (http://localhost:8080/core/). Adding 'context-root="/"' to the <application ... section allowed me to access without adding '/core/' to my URL.

Notice the setting of:

--property jruby.rackEnv=development

This is basically the equivalent of setting RAILS_ENV=development in your environment.

Next step was getting the db to work with jdbc/jndi pooling.

*Note: One issue I was having was the complaining of missing the class javax.jms.MessageListener:
/usr/local/jruby/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/object.rb:37:
in `get_proxy_or_package_under_package':
NameError: cannot load Java class javax.jms.MessageListener
Following the directions on http://wiki.glassfish.java.net/Wiki.jsp?page=OpenMQJRuby, I created and moved the appropriate jms/imq jar files to my domain/lib/ext directory and these are no longer an issue. I will have to see why this was when I work with the MQ issues (and converting from ActiveMQ to OpenMQ).
  1. .../mq/lib/jms.jar
  2. .../mq/lib/imq.jar
  3. .../mq/lib/imqjmsra.jar
imqjmsra.jar is created by extracting it from imqjmsra.rar:
jar xvf imqjmsra.rar imqjmsra.jar

Move these into the domain/lib/ext directory. These will also need to be included in your classpath when using the jruby console.