Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: to explicit Java (driver) class name loading #96

Merged
merged 5 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.1.9
- Refactor: to explicit Java (driver) class name loading [#96](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/96),
the change is expected to provide a more robust fix for the driver loading issue [#83](https://github.com/logstash-plugins/logstash-integration-jdbc/issues/83).

## 5.1.8
- Fix the blocking pipeline reload and shutdown when connectivity issues happen [#85](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/85)

Expand Down
27 changes: 13 additions & 14 deletions lib/logstash/plugin_mixins/jdbc/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Common

private

# NOTE: using the JRuby mechanism to load classes (through JavaSupport)
# makes the lock redundant although it does not hurt to have it around.
DRIVERS_LOADING_LOCK = java.util.concurrent.locks.ReentrantLock.new()

def complete_sequel_opts(defaults = {})
Expand All @@ -30,16 +32,16 @@ def load_driver
begin
load_driver_jars
begin
@driver_impl = Sequel::JDBC.load_driver(normalized_driver_class)
rescue Sequel::AdapterNotFound => e # Sequel::AdapterNotFound, "#{@jdbc_driver_class} not loaded"
# fix this !!!
@driver_impl = load_jdbc_driver_class
rescue => e # catch java.lang.ClassNotFoundException, potential errors
# (e.g. ExceptionInInitializerError or LinkageError) won't get caught
message = if jdbc_driver_library_set?
"Are you sure you've included the correct jdbc driver in :jdbc_driver_library?"
else
":jdbc_driver_library is not set, are you sure you included " +
"the proper driver client libraries in your classpath?"
end
raise LogStash::PluginLoadingError, "#{e}. #{message} #{e.backtrace}"
raise LogStash::PluginLoadingError, "#{e.inspect}. #{message}"
end
ensure
DRIVERS_LOADING_LOCK.unlock()
Expand Down Expand Up @@ -71,16 +73,13 @@ def jdbc_driver_library_set?
!@jdbc_driver_library.nil? && !@jdbc_driver_library.empty?
end

# normalizing the class name to always have a Java:: prefix
# is helpful since JRuby is only able to directly load class names
# whose top-level package is com, org, java, javax
# There are many jdbc drivers that use cc, io, net, etc.
def normalized_driver_class
if @jdbc_driver_class.start_with?("Java::", "Java.")
@jdbc_driver_class
else
"Java::#{@jdbc_driver_class}"
end
def load_jdbc_driver_class
# sub a potential: 'Java::org::my.Driver' to 'org.my.Driver'
class_name = @jdbc_driver_class.gsub('::', '.').sub(/^Java\./, '')
# NOTE: JRuby's Java::JavaClass.for_name which considers the custom class-loader(s)
# in 9.3 the API changed and thus to avoid surprises we go down to the Java API :
JRuby.runtime.getJavaSupport.loadJavaClass(class_name) # throws ClassNotFoundException
end

end
end end end
2 changes: 1 addition & 1 deletion logstash-integration-jdbc.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'logstash-integration-jdbc'
s.version = '5.1.8'
s.version = '5.1.9'
s.licenses = ['Apache License (2.0)']
s.summary = "Integration with JDBC - input and filter plugins"
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
Expand Down
23 changes: 17 additions & 6 deletions spec/inputs/jdbc_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1620,16 +1620,27 @@
describe "jdbc_driver_class" do
context "when not prefixed with Java::" do
let(:jdbc_driver_class) { "org.apache.derby.jdbc.EmbeddedDriver" }
it "loads the class prefixed with Java::" do
expect(Sequel::JDBC).to receive(:load_driver).with(/^Java::/)
plugin.send(:load_driver)
it "loads the class" do
expect { plugin.send(:load_driver) }.not_to raise_error
end
end
context "when prefixed with Java::" do
let(:jdbc_driver_class) { "Java::org.apache.derby.jdbc.EmbeddedDriver" }
it "loads the class as-is" do
expect(Sequel::JDBC).to receive(:load_driver).with(jdbc_driver_class)
plugin.send(:load_driver)
it "loads the class" do
expect { plugin.send(:load_driver) }.not_to raise_error
end
end
context "when prefixed with Java." do
let(:jdbc_driver_class) { "Java.org::apache::derby::jdbc.EmbeddedDriver" }
it "loads the class" do
expect { plugin.send(:load_driver) }.not_to raise_error
end
end
context "when class name invalid" do
let(:jdbc_driver_class) { "org.apache.NonExistentDriver" }
it "raises a loading error" do
expect { plugin.send(:load_driver) }.to raise_error LogStash::PluginLoadingError,
/java.lang.ClassNotFoundException: org.apache.NonExistentDriver/
end
end
end
Expand Down