jruby / jruby-rack

Rack for JRuby and Java appservers
MIT License
397 stars 137 forks source link

Cannot use jruby.rack.error.app or jruby.rack.error.app.path #166

Closed stephenlam closed 10 years ago

stephenlam commented 10 years ago

I am trying to use a custom error app instead of the DefaultErrorApplication. I am doing this by specifying the jruby.rack.error.app.path context-param in my web.xml. However, there is a bug in the code that causes jruby-rack to ignore that param.

After tracing through the jruby-rack code, I discovered that in the newErrorApplication() method of DefaultRackApplicationFactory, all code paths cause a new DefaultErrorApplication object to be returned. I wanted to activate the use of the jruby.rack.error.app.path param via the try-block in lines 201-211.

       try {
            RackApplication app = createErrorApplication(
                new ApplicationObjectFactory() {
                    public IRubyObject create(Ruby runtime) {
                        return createErrorApplicationObject(runtime);
                    }
                }
            );
            app.init();
            return app;
        }

That calls createErrorApplicationObject which looks at the error.app.path param and is supposed to create the custom error app. However, the ApplicationObjectFactory is passed as a param to createErrorApplication(), which returns...a DefaultErrorApplication object. setApplication() is called on the custom error app, but getApplication() is not used anywhere within DefaultErrorApplication, so passing in the argument is pointless.

    private RackApplication createErrorApplication(final ApplicationObjectFactory appFactory) {
        final Ruby runtime = newRuntime();
        return new DefaultErrorApplication() {
            @Override
            public void init() {
                setApplication(appFactory.create(runtime));
            }
            @Override
            public void destroy() {
                runtime.tearDown(false);
            }
        };
    }

RIght now I can confirm that the DefaultErrorApplication is being used because the stack trace and 500 status code is displayed in my browser when an exception is thrown.

Another issue which I couldn't figure out is why I don't see the "failed to read jruby.rack.error.app.path" message in my logs when I specify an invalid path for jruby.rack.error.app.path. Even with the aforementioned bug, createErrorApplicationObject() should still be called. init() -> create() -> createErrorApplicationObject(). I do see other lines being logged, so it isn't a problem with my logging config.

jruby.rack - could not acquire application permit within 1.0 seconds (try increasing the pool size)
jruby.rack - resetting rack response due exception
stephenlam commented 10 years ago

Summary of above: there is no way to hide 500 error stack traces coming from jruby-rack from the end-user's browser.

kares commented 10 years ago

thank you - it's behaving differently based on the exception type and where it's coming from, could you include on what kind of exception that is e.g. for running pooled anAcquiteTimeoutException can not be really rescued in Ruby - simply there's no ruby runtime to run Ruby code since we failed acquiring one. do you have any (code) suggestions for improvement ?

kares commented 10 years ago

looking at this in detail - you guys were right ... it's fixed in 1.1.14 including an updated ErrorApp thx!