Your SlideShare is downloading. ×
DataMapper on Infinispan
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

DataMapper on Infinispan

4,649
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
4,649
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
32
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. DataMapper on Infinispan Clustered NoSQL Lance BallThursday, September 22, 11 1
  • 2. Lance Ball •Red Hat senior engineer •TorqueBox core developer •Perl -> C++ -> Java -> Ruby •@lanceballThursday, September 22, 11 2
  • 3. project:oddThursday, September 22, 11 3
  • 4. What are we talking about? • DataMapper - Ruby ORM • Infinispan - Java+Scala distributed cache • Hibernate Search - Java ORM • Lucene - Indexing and search • JBoss AS7 - JEE application server • TorqueBox - JRuby application serverThursday, September 22, 11 4
  • 5. TorqueBox JRuby Application Server http://torquebox.orgThursday, September 22, 11 5
  • 6. TorqueBox The Power of JBoss with the Expressiveness of RubyThursday, September 22, 11 6
  • 7. Thursday, September 22, 11 7
  • 8. TorqueBox •Ruby, baby! •Rack apps •Scheduled Jobs •Background Tasks •Message Queues & Topics •Message Processors •Long-running Services •Distributed / Replicated CacheThursday, September 22, 11 8
  • 9. JRuby •Healthy community •Real threads •Java libraries •Java tools •Fast runtime •Better memory management** ** for long running things like serversThursday, September 22, 11 9
  • 10. Java CacheFactory.java public class CacheFactory {   public CacheFactory() {     config = new Configuration();     store = new FileCacheStoreConfig();     store.purgeOnStartup( false );     config.fluent().loaders().addCacheLoader( store );     manager = new DefaultCacheManager( config.build() );   }   public Cache getCache() { return manager.getCache(); } }Thursday, September 22, 11 10
  • 11. JRuby cache_factory.rb class CacheFactory   def initialize     @config = Configuration.new     @store = FileCacheStore.new     @store.purge_on_startup false     @config.fluent.loaders.add_cache_loader( @store )     @manager = DefaultCacheManager.new( @config.build )   end   def get_cache ; @manager.get_cache end endThursday, September 22, 11 11
  • 12. Infinispan An extremely scalable, highly available data grid http://www.jboss.org/infinispanThursday, September 22, 11 12
  • 13. Infinispan •Key / Value store •Highly concurrent core •Data Grid •Replicated •Distributed •LocalThursday, September 22, 11 13
  • 14. Hotrod •Binary TCP protocol •Clients •Java •Python •Ruby •...Thursday, September 22, 11 14
  • 15. NoSQL? •Non-relational •Scales out, not up •Big data •Low ceremonyThursday, September 22, 11 15
  • 16. Infinispan API Cache.java    cache.put(key, value, lifespan, timeUnit);    cache.putIfAbsent(key, value, lifespan, timeUnit);    cache.replace(key, oldVal, value, lifespan, timeUnit);    cache.putAsync(key, value, lifespan, timeUnit);    cache.keySet();    cache.values();    cache.entrySet();Thursday, September 22, 11 16
  • 17. Hibernate Search Example.java import org.hibernate.search.annotations.*; @Indexed @ProvidedId public class Book { @Field String title; @Field String description; @Field Date publicationYear; }Thursday, September 22, 11 17
  • 18. Indexing: Lucene Search.java org.apache.lucene.search.Query luceneQuery = queryBuilder.phrase() .onField( "description" ) .andField( "title" ) .sentence( "pat the bunny" ) .createQuery(); CacheQuery query = searchManager.getQuery( luceneQuery, Book.class );Thursday, September 22, 11 18
  • 19. DataMapper •Object Relational Mapper •Alternative to ActiveRecord •Written in Ruby •http://datamapper.orgThursday, September 22, 11 19
  • 20. Resources beer.rb class Beer   include DataMapper::Resource   property :id, Serial   property :name, String   property :rating, Integer   property :notes, Text   belongs_to :user endThursday, September 22, 11 20
  • 21. DataMapper Queries sample.rb Beer.all Beer.get(1) Beer.first( :name => Pisgah Pale ) Beer.last( :name.like => IPA ) Beer.all( :notes.like => hoppy )Thursday, September 22, 11 21
  • 22. DataMapper Adapter SPI sample_adapter.rb module DataMapper::Adapters   class SampleAdapter < AbstractAdapter     def initialize( name, options ) ; end     def create( resources ) ; end     def read( query ) ; end     def update( attributes, collection ) ; end     def delete( collection ) ; end   end endThursday, September 22, 11 22
  • 23. DataMapper Filtering some_adapter.rb     def read( query ) records = @search_manager.search( query )       query.filter_records( records )     endThursday, September 22, 11 23
  • 24. Testing adapter_spec.rb require dm-core/spec/shared/adapter_spec describe DataMapper::Adapters::InfinispanAdapter do   before :all do     @adapter = DataMapper.setup(:default, :adapter => infinispan)   end   it_should_behave_like An Adapter   describe "other important things to test" do # Your tests here   end endThursday, September 22, 11 24
  • 25. torquebox-cache • TorqueBox 2.0 gem • dm-infinispan-adapter • TorqueBox::Infinispan::Cache • ActiveSupport::Cache::TorqueBoxStoreThursday, September 22, 11 25
  • 26. dm-infinispan-adapter Use Infinispan as your object data storeThursday, September 22, 11 26
  • 27. dm-infinispan-adapter require dm-core require dm-infinispan-adapter class Beer   include DataMapper::Resource   property :id, Serial   property :name, String   property :rating, Integer   property :notes, Text   belongs_to :user end DataMapper.setup(:default, :adapter=>infinispan, :persist=>true)Thursday, September 22, 11 27
  • 28. But How?Thursday, September 22, 11 28
  • 29. Hibernate Search Annotated Java classesThursday, September 22, 11 29
  • 30. Runtime Class Creation How do we make Ruby’s Beer.class look like an annotated Java class at runtime?Thursday, September 22, 11 30
  • 31. Metaprogramming! dm-infinispan-adapter.rb require datamapper/model module DataMapper::Adapters   class InfinispanAdapter < AbstractAdapter     DataMapper::Model.append_inclusions( Infinispan::Model )   end endThursday, September 22, 11 31
  • 32. Metaprogramming! datamapper/model.rb module Infinispan   module Model     def self.included(model)       model.extend(ClassMethods) model.before_class_method(:finalize, :configure_index)     end end endThursday, September 22, 11 32
  • 33. Annotations datamapper/model.rb require ‘jruby/core_ext’ annotation = {org.hibernate.search.annotations.Field => {}} add_method_annotation( “getName”, annotation )Thursday, September 22, 11 33
  • 34. Annotations datamapper/model.rb require ‘jruby/core_ext’ annotation = {   org.hibernate.search.annotations.Indexed => {},   org.hibernate.search.annotations.ProvidedId => {},   org.infinispan.marshall.SerializeWith => {"value" => org.torquebox.cache.marshalling.JsonExternalizer.java_class }} add_class_annotation( annotation )Thursday, September 22, 11 34
  • 35. Become Java! java_class = become_java!Thursday, September 22, 11 35
  • 36. JSON Externalizer Forget java.io.SerializableThursday, September 22, 11 36
  • 37. JSON Externalizer JsonExternalizer.java public class JsonExternalizer implements Externalizer<IRubyObject> { " @Override " public void writeObject(ObjectOutput output, IRubyObject object) " " " throws IOException { " " String theType = object.getType().getName(); " " output.writeObject( theType ); " " output.writeObject( toJSON(object) ); " }  }Thursday, September 22, 11 37
  • 38. JSON Externalizer JsonExternalizer.java public class JsonExternalizer implements Externalizer<IRubyObject> { " @Override " public IRubyObject readObject(ObjectInput input) throws IOException, ClassNotFoundException { " " String theType = (String) input.readObject(); " " String theJson = (String) input.readObject(); " " return fromJSON(theJson, theType);" " }  }Thursday, September 22, 11 38
  • 39. JSON Externalizer JsonExternalizer.java public class JsonExternalizer implements Externalizer<IRubyObject> {     protected IRubyObject fromJSON(String json, String type) throws ClassNotFoundException {         RubyModule objectClass = runtime.getClassFromPath( type );         return (IRubyObject) JavaEmbedUtils.invokeMethod( runtime, objectClass, "new", new Object[] { jsonHash }, IRubyObject.class);     }  }Thursday, September 22, 11 39
  • 40. JSON Externalizer JsonExternalizer.java public class JsonExternalizer implements Externalizer<IRubyObject> {     protected String toJSON(IRubyObject object) {         return (String) JavaEmbedUtils.invokeMethod( getCurrentRuntime(), object, "to_json", EMPTY_OBJECT_ARRAY, String.class );     }  }Thursday, September 22, 11 40
  • 41. Sequences dm-core/property/serial.rb DataMapper::Property::SerialThursday, September 22, 11 41
  • 42. Sequences dm-core/adapters/abstract_adapter.rb initialize_serial( resource, next_id )Thursday, September 22, 11 42
  • 43. Sequences cache.rb module TorqueBox   module Infinispan     class Cache       def increment( sequence_name, amount = 1 ) # increment an integer       end       def decrement(name, amount = 1) # decrement an integer       end     end   end endThursday, September 22, 11 43
  • 44. Sequences dm-infinispan-adapter.rb @metadata = Cache.new( options ) initialize_serial( resource, @metadata.increment( “metadata/beers/index” ) )Thursday, September 22, 11 44
  • 45. Transactions cache_spec.rb   describe "with JTA transactions" do     it "should behave like a transaction" do       @cache.transaction do |cache|         cache.put(Tommy, Dorsey)         raise "yikes!"         cache.put(Elvis, Presley)       end       @cache.get(Tommy).should be_nil       @cache.get(Elvis).should be_nil     end    endThursday, September 22, 11 45
  • 46. Transactions dm-infinispan-adapter.rb     def delete( collection )       cache.transaction do         collection.each do |resource|           cache.remove( key(resource) )         end       end     endThursday, September 22, 11 46
  • 47. TorqueBox::Infinispan::Cache Use Infinispan for...Thursday, September 22, 11 47
  • 48. Cache some_file.rb include TorqueBox::Infinispan::Cache cache = Cache.new(:name => MyCache, :mode => :replicated) cache.put(key, value) cache.get(key)Thursday, September 22, 11 48
  • 49. ActiveSupport::Cache::TorqueBoxStore Caching in Rails. Replaces in-memory or memcached caches.Thursday, September 22, 11 49
  • 50. TorqueBoxStore config/application.rb module YourApp   class Application < Rails::Application     config.cache_store = :torque_box_store end endThursday, September 22, 11 50
  • 51. TorqueBoxStore my_app.rb require sinatra require torquebox class MyApp < Sinatra::Base   use TorqueBox::Session::ServletStore   get / do     session[:message] = Hello World!     haml :index   end endThursday, September 22, 11 51
  • 52. Beer Catalogue! http://www.flickr.com/photos/burnblue/308441464/Thursday, September 22, 11 52
  • 53. Model beer.rb require dm-core require dm-infinispan-adapter class Beer   include DataMapper::Resource   property :id, Serial   property :name, String   property :rating, Integer   property :notes, Text   belongs_to :user end DataMapper.setup(:default, :adapter=>infinispan, :persist=>true)Thursday, September 22, 11 53
  • 54. Sinatra application.rb module BeerCatalogue   class Application < Sinatra::Base     get / do       @beers = Beer.all( :user_id => current_user.id )       haml :index     end     post /beer do       Beer.create( :name=>params[:name], :notes=>params[:notes], :rating=>params[:rating], :user=>current_user)       redirect /     end   end endThursday, September 22, 11 54
  • 55. View views/index.haml #welcome   Hello   =current_user.name #body   #beer-list     %h2 Your Beers     - if @beers.empty?       %strong You havent rated any beers yet. Do that now!     %ul       - @beers.each do |beer|         %li           =beer.name           =beer.rating =beer.notesThursday, September 22, 11 55
  • 56. Source http://github.com/torquebox/torquebox http://github.com/torquebox/presentationsThursday, September 22, 11 56
  • 57. Installation $ gem install torquebox-server --pre --source http://torquebox.org/2x/builds/LATEST/gem-repo/ $ gem install bundler $ bundle install $ torquebox deploy . Deployed: beer.yml into: /path/to/jboss/standalone/deployments $ torquebox runThursday, September 22, 11 57
  • 58. http://www.flickr.com/photos/crystalflickr/2317183342/Thursday, September 22, 11 58
  • 59. TorqueBox 2.x • Under development • Continuous integration • TorqueBox::Infinispan::Cache • ActiveSupport::Cache::TorqueBoxStore • dm-infinispan-adapterThursday, September 22, 11 59
  • 60. TorqueBox 1.x • Version 1.1.1 released in August • Continuous integration • ActiveSupport::Cache::TorqueBoxStoreThursday, September 22, 11 60
  • 61. Resources • http://torquebox.org/ • http://github.com/torquebox • #torquebox on FreeNode • @torqueboxThursday, September 22, 11 61
  • 62. Questions http://www.flickr.com/photos/eleaf/2536358399/Thursday, September 22, 11 62