Skip to content

mongoid driver does not work in JRuby on Windows or JRuby loads incorrect socket constants on Windows. #5477

@cshupp1

Description

@cshupp1

Consider the following irb session:

irb(main):001:0> JRUBY_VERSION
=> "9.2.4.0"
irb(main):005:0> require 'socket'
=> true
irb(main):009:0> Socket::PF_INET
=> 4
irb(main):016:0> java.lang.System.getProperties['os.name']
=> "Windows 10"

Let us compare it to MRI Ruby:

irb(main):001:0> RUBY_VERSION
=> "2.5.1"
irb(main):002:0> RUBY_PLATFORM
=> "x64-mingw32"
irb(main):003:0> require 'socket'
=> true
irb(main):004:0> Socket::PF_INET
=> 2

Note the socket constants are not consistent. What about JRuby on Linux?

java -jar jruby-complete-9.2.4.0.jar -S jirb
irb(main):001:0> java.lang.System.getProperties['os.name']
=> "Linux"
irb(main):002:0> require 'socket'
=> true
irb(main):003:0> Socket::PF_INET
=> 2

The Mongoid driver versions:

    mongoid (6.4.2)
    mongo (2.6.2)

fail as a result. On a stock rails install (5.2.1) with the mongoid driver installed the following model:

class ToyModel
  include Mongoid::Document
  include Mongoid::Timestamps
  store_in :collection => "toy_model"
  field :toy, :type => String
end

with the following code:

 t = ToyModel.new
 t.toy = "rails server coming up at #{Time.now}"
 t.save!

fails as follows:

MONGODB | EVENT: #<Mongo::Monitoring::Event::TopologyOpening topology=Unknown>
MONGODB | Topology type 'unknown' initializing.
MONGODB | EVENT: #<Mongo::Monitoring::Event::ServerOpening address=127.0.0.1:27017 topology=Unknown>
MONGODB | Server 127.0.0.1:27017 initializing.
MONGODB | undefined method `new' for nil:NilClass
MONGODB | undefined method `new' for nil:NilClass
MONGODB | undefined method `new' for nil:NilClass #<===repeats forever...

The following monkey patch, in an initializer, repairs the problem:

WINDOWS = java.lang.System.getProperties['os.name'] =~ /windows/i
if WINDOWS
  module Mongo
    PF_INET = 2 #Socket::PF_INET = 2 #2 in MRI ruby, 4 in JRuby on windows, 2 on Linux. We need 2.
    class Address
      def socket(socket_timeout, ssl_options = {})
        unless ssl_options.empty?
          Socket::SSL.new(host, port, host_name, socket_timeout, Mongo::PF_INET, ssl_options)#force it to see properly defined constant
        else
          Socket::TCP.new(host, port, socket_timeout, Mongo::PF_INET)#Mongo:: is Socket:: in original code
        end
      end
    end
  end
else
  puts "Linux Yay!"
end

Now the same toy_model code yields:

irb(main):001:0> t = ToyModel.new
=> #<ToyModel _id: 5bfdc5168726e31af7d27464, created_at: nil, updated_at: nil, toy: nil>
irb(main):002:0> t.toy = "rails server coming up at #{Time.now}"
=> "rails server coming up at 2018-11-27 17:28:44 -0500"
irb(main):003:0> t.save!
MONGODB | EVENT: #<Mongo::Monitoring::Event::TopologyOpening topology=Unknown>
MONGODB | Topology type 'unknown' initializing.
MONGODB | EVENT: #<Mongo::Monitoring::Event::ServerOpening address=127.0.0.1:27017 topology=Unknown>
MONGODB | Server 127.0.0.1:27017 initializing.
MONGODB | EVENT: #<Mongo::Monitoring::Event::TopologyChanged prev=Unknown new=Single>
MONGODB | Topology type 'unknown' changed to type 'single'.
MONGODB | EVENT: #<Mongo::Monitoring::Event::ServerDescriptionChanged>
MONGODB | Server description for 127.0.0.1:27017 changed from 'unknown' to 'standalone'.
MONGODB | EVENT: #<Mongo::Monitoring::Event::TopologyChanged prev=Single new=Single>
MONGODB | There was a change in the members of the 'single' topology.
MONGODB | 127.0.0.1:27017 | dif_development.insert | STARTED | {"insert"=>"toy_model", "ordered"=>true, "lsid"=>{"id"=><BSON::Binary:0x2058 type=uuid data=0x063280eed79c45b4...>}, "documents"=>[{"_id"=>BSON::ObjectId('5bfdc5168
726e31af7d27464'), "toy"=>"rails server coming up at 2018-11-27 17:28:44 -0500", "updat...
MONGODB | 127.0.0.1:27017 | dif_development.insert | SUCCEEDED | 0.012s
=> true
irb(main):004:0>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions