Best/Most Elegant Way to Share Objects Between a Stack of Rack Mounted Apps/Middlewares

JRuby: Calling Java Code From A Rack App And Keeping It In Memory

Yes, a setup it's possibile ( see below about Deployment ) and to accomplish it I would suggest to use a Singleton

Singletons in Jruby

with reference to question: best/most elegant way to share objects between a stack of rack mounted apps/middlewares? I agree with Colin Surprenant's answer, namely singleton-as-module pattern which I prefer over using the singleton mixin

Example

I post here some test code you can use as a proof of concept:

JRuby sinatra side:

#file: sample_app.rb

require 'sinatra/base'
require 'java' #https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
java_import org.rondadev.samples.StatefulCalculator #import you java class here

# singleton-as-module loaded once, kept in memory
module App
module Global extend self
def calc
@calc ||= StatefulCalculator.new
end
end
end
# you could call a method to load data in the statefull java object
App::Global.calc.turn_on

class Sample < Sinatra::Base
get '/' do
"Welcome, calculator register:#{App::Global.calc.display}"
end

get '/add_one' do
"added one to calculator register, new value:#{App::Global.calc.add(1)}"
end
end

You can start it in tomcat with trinidad or simply with rackup config.ru but you need:

#file: config.ru
root = File.dirname(__FILE__) # => "."
require File.join( root, 'sample_app' ) # => true
run Sample # ..in sample_app.rb ..class Sample < Sinatra::Base

something about the Java Side:

package org.rondadev.samples;

public class StatefulCalculator {

private StatelessCalculator calculator;

double register = 0;

public double add(double a) {
register = calculator.add(register, a);
return register;
}

public double display() {
return register;
}

public void clean() {
register = 0;
}

public void turnOff() {
calculator = null;
System.out.println("[StatefulCalculator] Good bye ! ");
}

public void turnOn() {
calculator = new StatelessCalculator();
System.out.println("[StatefulCalculator] Welcome !");
}
}

Please note that the register in here is only a double but in your real code you can have a big data structure in your real scenario

Deployment

You can deploy using Mongrel, Thin (experimental), Webrick (but who would do that?), and even Java-centric application containers like Glassfish, Tomcat, or JBoss. source: jruby deployments

with TorqueBox that is built on the JBoss Application Server.
JBoss AS includes high-performance clustering, caching and messaging functionality.

trinidad is a RubyGem that allows you to run any Rack based applet wrap within an embedded Apache Tomcat container

Thread synchronization

Sinatra will use Mutex#synchronize method to place a lock on every request to avoid race conditions among threads. If your sinatra app is multithreaded and not thread safe, or any gems you use is not thread safe, you would want to do set :lock, true so that only one request is processed at a given time. .. Otherwise by default lock is false, which means the synchronize would yield to the block directly.

source: https://github.com/zhengjia/sinatra-explained/blob/master/app/tutorial_2/tutorial_2.md

Call subapp route within Padrino app

You cant, as for rails render_controller is dead.

You can workaround with an "old" iframe.

You can call links from others app like:

MainApp.url :backend, :index

Using Rack to run a React application is not working as it should

It was all a matter of wrong mime type, caused by a typo.

It may be clearly seen in my question that I wrote:

def content_type
{
'html' => 'text/html',
'js' => 'text/javascript',
'css' => 'text/css',
'svg' => 'image/svg+xm', # <== Here is the error!!!
'ico' => 'image/x-icon',
'map' => 'application/octet-stream'
}
end

when the correct mime type for SVG files is 'image/svg-xml', with an 'l'...

This was making the browser ignore the file received and so it won't display it correctly.



Related Topics



Leave a reply



Submit