jruby/warbler

NoMethodError: undefined method `new_ostruct_member' for No value for 'public' found

tedt10e opened this issue ยท 24 comments

Hello @headius,

I'm just trying to upgrade from 9.2.19.0 to 9.3.3.0. But I could not able to generate the war file and get the error below.

Is there anything do I need to upgrade?

warbler version 2.0.5
JDK openjdk-16.0.1

Many Thanks.
Ted

warble war --trace

warble aborted!
NoMethodError: undefined method `new_ostruct_member' for No value for 'public' found
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits/war.rb:200:in `method_missing'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits/war.rb:53:in `default_webxml_config'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits/war.rb:27:in `before_configure'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits.rb:29:in `block in before_configure'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits.rb:29:in `each'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/traits.rb:29:in `before_configure'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/config.rb:215:in `initialize'
config/warble.rb:6:in `new'
config/warble.rb:6:in `initialize'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/task.rb:46:in `eval'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/task.rb:46:in `initialize'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/application.rb:27:in `new'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/application.rb:27:in `load_rakefile'
/home/dev/.rvm/rubies/jruby-9.3.3.0/lib/ruby/gems/shared/gems/rake-13.0.6/lib/rake/application.rb:82:in `block in run'
/home/dev/.rvm/rubies/jruby-9.3.3.0/lib/ruby/gems/shared/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/dev/.rvm/rubies/jruby-9.3.3.0/lib/ruby/gems/shared/gems/rake-13.0.6/lib/rake/application.rb:80:in `run'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/application.rb:79:in `run'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/lib/warbler/application.rb:74:in `run'
/home/dev/.rvm/gems/jruby-9.3.3.0/gems/warbler-2.0.5/bin/warble:11:in `<main>'
/home/dev/.rvm/gems/jruby-9.3.3.0/bin/warble:25:in `load'
/home/dev/.rvm/gems/jruby-9.3.3.0/bin/warble:25:in `<main>'
/home/dev/.rvm/gems/jruby-9.3.3.0/bin/jruby_executable_hooks:22:in `eval'
/home/dev/.rvm/gems/jruby-9.3.3.0/bin/jruby_executable_hooks:22:in `<main>'

๐Ÿ‘‹ I believe this is connected to ruby/ostruct#40

Thanks @olleolleolle ๐Ÿ™

Hope this will resolve soon before the next JRuby release.

For the time being, I'll just use 9.3.2.0.

For those who use 9.3.2.0, you may run into issues with running tests if you are using Simplecov. (jruby/jruby#6984)

Just skip the Simplecov in test_helper.rb file.

  unless RUBY_ENGINE == 'jruby'
    require 'simplecov'
    SimpleCov.start 'rails' do
      add_filter %r{^/app/channels/}
      add_filter %r{^/app/jobs/}
    end
  end

We're experiencing the same problem on our application. I think it'd make sense to keep this GH issue open since the issue exists and has not been fixed yet (https://github.com/jruby/warbler/blob/master/lib/warbler/traits/war.rb#L185 still uses the deprecated method).

Pulled the following from ostruct to our warble.rb configuration file (added it at the top of the file):

class Warbler::Traits::War::WebxmlOpenStruct
  def new_ostruct_member(name)
    unless @table.key?(name) || is_method_protected!(name)
      getter_proc = Proc.new { @table[name] }
      setter_proc = Proc.new {|x| @table[name] = x}
      if defined?(::Ractor)
        ::Ractor.make_shareable(getter_proc)
        ::Ractor.make_shareable(setter_proc)
      end
      define_singleton_method!(name, &getter_proc)
      define_singleton_method!("#{name}=", &setter_proc)
    end
  end
end

Gross, but seems to work.

enebo commented

@kovyrin I believe we should just open a new issue for this change (or another) since once there is a new ostruct release warbler should work again. There is nothing directly actionable to be done here (at least not until that deprecated method is actually removed). I definitely agree with you that we need to change this class though. Just as a new issue.

Frankly, I did not spend very much time but I find it confusing this is using ostruct at all. It override [], []=, and method_missing. If I look at []= I wonder why this needs to be overriden at all? I am sure there is a reason but we could probably just eliminate this dependency if it actually needs the metaprogramming it already has.

Pulled the following from ostruct to our warble.rb configuration file (added it at the top of the file):

class Warbler::Traits::War::WebxmlOpenStruct
  def new_ostruct_member(name)
    unless @table.key?(name) || is_method_protected!(name)
      getter_proc = Proc.new { @table[name] }
      setter_proc = Proc.new {|x| @table[name] = x}
      if defined?(::Ractor)
        ::Ractor.make_shareable(getter_proc)
        ::Ractor.make_shareable(setter_proc)
      end
      define_singleton_method!(name, &getter_proc)
      define_singleton_method!("#{name}=", &setter_proc)
    end
  end
end

Gross, but seems to work.

With this workaround file META-INF/init.rb will contain line ENV['RAILS_ENV'] ||= ENV_JAVA[ 'RAILS_ENV' ] || 'No value for 'env' found' unless in warble configuation config.webxml.rails.env is set.

This means that with default warble configuration init.rb is invalid.

Error message from tomcat is something like:

.../META-INF/init.rb:10: syntax error, unexpected tIDENTIFIER
  ...S_ENV' ] || 'No value for 'env' found'

Workaround for that is to uncomment/add line config.webxml.rails.env = ENV['RAILS_ENV'] || 'production' in warble configuration file. Usually config/warble.rb.

I also had to add guard return if name.nil? to make this work with minimal rails 6.1.1. Added as the first line for def new_ostruct_member(name)

Please reopen this issue because the reason is not fixed.

FWIW, I came up with a simpler and less copy-pasty version of @kovyrin's warble.rb workaround:

class Warbler::Traits::War::WebxmlOpenStruct
  def new_ostruct_member(name)
    send(:new_ostruct_member!, name)
  end
end

This defines a public alias on Warbler::Traits::War::WebxmlOpenStruct for the private OpenStruct#new_ostruct_member! method. Of course this will break if the private method is ever removed or changed in an incompatible way, but then, any kluge that pokes into the OpenStruct internals like this is liable to break if those internals are changed.

On Apple Silicon if I try the fix from @ikaronen-relex or @jlahtinen I get "TypeError: nil is not a string"

Still seems to be issues here so let's sort that out.

We're seeing this with 9.3.4.0 as we're trying to upgrade to the 9.3 series.

It seems there is and additional issue discovered by @joerixaop being modifiable method removed from ostruct as per

#521

I fixed this issue with installing warbler directly from GitHub repo instead of "gem install warbler".
Release value stays the same but the issue with "undefined method `new_ostruct_member' " has gone.

gem install specific_install
gem specific_install https://github.com/jruby/warbler.git

@rammpeter so perhaps we have fixed this on warbler master but need a release?

@headius Yes, it looks like this was probably fixed in c65a44c (and apparently cleaned up further in bb68db9).

Hi @headius,

A new release would be good and greatly appreciated. In my side, warbler is part of our build process and because this issue we are not able to upgrade to JRuby 9.3.x.x

We have Release 2.1.0 ticket #498

  • Jbundler, to allow bundler 2, this is resolved as per mkristian/jbundler#102
  • we had a issue with rake build when building the gem which was resolved #522

The only pending thing is update the History.txt which we have a pull request (it needs to be updated with the recent changes though)

Another thing we might need to look after is the compiler line the Mavenfile, no sure if it needs to be updated since only Java 8+ is supported

plugin :compiler, '3.1', :source => '1.6', :target => '1.6'

@rammpeter so perhaps we have fixed this on warbler master but need a release?

Yes, this seems to be the case

Following @rammpeter's suggestion, I created a working Tomcat 9 app using Sinatra 3.0.5 and JRuby 9.4.0.0 with these two extra steps:

Change the gem 'warbler' line in my Gemfile to this:
gem 'warbler', '2.0.5', git: 'https://github.com/jruby/warbler', branch: 'master', platforms: :jruby

bundle update and bundle exec warble as usual, then...

Manually copy *.gemspec into the resulting war:
mkdir WEB-INF && cp myapp.gemspec WEB-INF && zip myapp.war WEB-INF/myapp.gemspec && rm -r WEB-INF

New release of warbler would still be much appreciated!

F2Chem commented

A year and a quarter later, and still not fixed?

I'm just developing an alternative approach for deploying a Rails application in a self executing jar file (jarbler). Coming soon.

As mentioned before, for creating a self executing jar file there's an alternative now available with Jarbler ( https://github.com/rammpeter/jarbler ).
This does not help if execution in a servlet container is needed, but for simply providing a Ruby app (like Rails) as Java application it does the job.