Trinidad 0.8, gem extensions and database pooling 0

Posted by david

I think, the release of the latest version of JRuby-Rack was the perfect moment to do a new release of Trinidad and some new features. If this is the first time you bump into Trinidad, it's a Rack compatible server build on top of Apache Tomcat and release as a rubygem.

One of my main concerns about the project was that I wanted to build a lightweight gem and until now you had to download more than 5Mb with each release. The first step to avoid this was to split the gem in two, the main gem, trinidad, is now 12Kb, while the jars gem, trinidad_jars is just 3Mb, thus if I don't change the jars you'll just need to download 12Kb with each new release.

The second step is to stop adding features to the main gem. With each new feature that I wanted to implement more jar files were required and added to the package. Now Trinidad includes a little extensions api that allows to release features as little gems out of the core, you can find more details on the api into the wiki. So, from now I'll try to release new features as extensions and leave the core as tiny as possible.

The first extension that I've written adds support for database connection pooling through Tomcat and JNDI. The project is also hosted on github, and the installation and configuration are pretty straightforward.

Finally, an extra point. Of course, the coolest new feature is the Rails 3 support due to JRuby-rack already supports it, and, as you'll probably know, Rails 3 routes allow to split your application in several ones and route between each other. Just remember that Trinidad also allows you to run all those distributed applications within the same container with just a few configuration lines.

All in all, if you find a bug or you'd like to see other new features, please don't hesitate filing an issue in the project's tracker.

Have fun.

Loading several Rails applications into a single Tomcat container with Trinidad 0

Posted by david

Sometimes you meet that kind of people that complain about the lack of any feature in an open source project but they don't do anything to solve the problem. Last releases of Trinidad try the solve one of that complaints, so that people have one excuse less to use it :)

The goal of the project was pretty simple, allow to run a Rails application under Apache Tomcat without generating a war file in a more familiar "rails way". But that guy complained because he wanted to run several applications into the same instance of Tomcat, and actually he was partially right, Tomcat is a powerful application server and it can run several applications at once, thus, why don't allow to Trinidad to run several Rails applications?

After a few changes in its architecture, Trinidad allows to run as many Rails applications as Tomcat can support into the same instance. We just need add the application's context and their system path to the Trinidad's configuration file and run Trinidad with the option to read that file.

For instance, if we want to load three applications we had to add this nodes to the yaml file:


---
  :web_apps:
    :default:                                         # context path is '/'
      :web_app_dir: 'rails_apps/mock'
    :mock1:                                         # context path is '/mock1'
      :web_app_dir: 'rails_apps/mock1'
    :mock2:
      :web_app_dir: 'rails_apps/mock2'
      :context_path: '/mock2'

and run Trinidad with the configuration option:


$ jruby -S trinidad --config

That's it. Hope it will useful. Btw all the configuration options can be found in the Trinidad's wiki.

Rails load balancing with Apache and Trinidad 1

Posted by david

I just released a new version of Trinidad with two major features. The first one is that it supports ssl connections adding a simple starting option:


  $ trinidad --ssl

The second one is also related with connections, but this one is about AJP, a protocol designed to increase tomcat's performance, if you already have worked with tomcat or jboss I'm sure you already know it.

But what I'd like to show you is one of its main adventages, how to create a really stable load balancer with Apache httpd and Trinidad thanks to ajp.

First we have to ensure all the apache modules that we need are loaded:


  $ sudo a2enmod proxy_ajp proxy_balancer

After that, we have to configure our virtual host to proxy the connections through ajp, this is an actually basic configuration, there are a lot of resources about mod_proxy_balancer on internet:


<Proxy balancer://trini>
  BalancerMember ajp://127.0.0.1:8009
  BalancerMember ajp://127.0.0.1:8099
</Proxy>

ProxyPass / balancer://trini/

Notice that I'm using my development machine and that's why the two balancer members have the same ip but different port.

Finally, we have to run two different instances of Trinidad with the ajp option enabled, with the ports we specified in the balancer configuration (8009 is the default one), and different http ports due to I'm running it in my machine:



$ trinidad --port 3001 --ajp
$ trinidad --port 3002 --ajp 8099

That's it, quite straightforward.

By the way, I've also set up a google group where you can ask doubts or discuss about the development itself, and, as always, if you find a bug or have a new cool functionality you can add it to the issue tracker.

Tomcat-rails is now called Trinidad 1

Posted by david

One month ago I released Tomcat-rails, a little gem to simplify my development process with tomcat.

To get feedback I decided to send some emails to several mail lists. I was really interested in answers from jruby and tomcat users and developers, perhaps they could send me some advice to improve my code or ideas for new features.

I got good feedback from the jruby-user list, people used it with good results, others bump into problems with jruby-rack... but the answers from tomcat-user lists actually took me by surprise, just two or three minutes after I sent the email the first reply asked me to read the tomcat's legal page, from his own words, the name of my project didn't conform to the guidance set out in the trademarks section, and specifically in this point:

If you use the words "Tomcat" or "Apache" in your product name then you must call your product "... for Apache Tomcat" or "... for Tomcat". You may not call your product "Apache ..." or "Tomcat ...".

Some days after, the same guy sent me an email directly to remember me that I had to change the name of the project, and of course, reading the internal lists of the ASF I know the project got some mentions.

Well, the problem just finishes today, from now this project is called Trinidad. In few days the old repository and the web page will be remove, the new web page and the repository are still hosted in github but I also set up the project in rubyforge, so install the gem is even easier:


jgem install trinidad

Remember if you find a bug, you have improvements over my code or just have suggestions for new features, you can use the repository issues' page.

Tomcat-rails, develop rails app within tomcat 0

Posted by david

UPDATE: This project has been renamed and it's not longer mantained, please read this post if you want to know the reasons or just go to the new project web page.

This days I'm working every day with this stack, jruby+rails+tomcat. I was quite tired to have to pack the application and restart tomcat every time I wanted to test every slight change, so as a result, I wrote a script to use an embed tomcat within my application and this morning I wrapped it as a gem.

There is a lot of work to do but you can already download it from github.

It's usage is quite simple, just install the gem with jruby, go to the root directory of your rails app and run jruby -S tomcat_rails, or copy and paste this lines:


  jgem install calavera-tomcat-rails -s http;//gems.github.com
  cd myrailsapp
  jruby -S tomcat_rails

Any feedback will be really appreciated.

Rails Hackathon in Madrid 1

Posted by david

Last month some friends of mine organized a great event called Monsters of Ruby. The topic was Ruby without Rails, and the challenge was mix random technologies and create a simple web app, my teammates and I suffered with SproutCore, Ramaze and Sequel.

Following its essence I'm organizing a new event called Rails Hackathon next February 7 in the 11870.com's office. The topic will be dive into the Rails core and send as patch as we can to the issue tracker.

Our office is not too much big so I've decided to close this event to 20 people, some of them have been already invited but there are some available places yet. If you are a Rails core contributor or you want to be and you enjoy diving in foreign source code send me a mail to calavera AT apache DOT org and I'll include you in the list.

rubyMetrics 1.2 supports Rails stats 4

Posted by david

I've just released the version 1.2 of the rubyMetrcics plugin for Hudson, and I've added support for Rails stats, so, if you check the right option hudson generates the report and its trend graph:

You can find more info into the plugin page.

Rails plugin: atom_pub_server 0

Posted by david

Update: he cambiado el repositorio y ahora el plugin se puede instalar desde GitHub:

   $script/plugin install git://github.com/calavera/atompub-server.git

Coincidiendo con el lanzamiento de la api de 11870.com tenía ganas de liberar un plugin para Rails que me ha ayudado a experimentar con AtomPub.

Como no soy muy original con los nombres lo he llamado atom_pub_server y básicamente sirve para empezar a implementar AtomPub dentro de una aplicación desarrollada con Rails. Ya que el punto de entrada del protocolo es su documento de servicio este plugin sirve para generar un documento de servicio a partir de los controllers de una aplicación. A partir de ahí, y gracias al genial soporte de REST por parte de rails y a alguna de las novedades de la versión 2.0 implementar un servidor de Atom Publishing Protocol con una aplicación rails es francamente sencillo.

Pero para ver como funciona el plugin lo mejor es ver un ejemplo. Empezaremos instalándolo en la aplicación desde el repositorio:

    $script/plugin install http://svn.thinkincode.net/rails/plugins/atom_pub_server

Supongamos que nuestra aplicación tiene dos controllers, uno llamado PostsController y otro llamado ServicesController. El primero será en encargado de gestionar una colección de recursos, así que le añadiremos el siguiente método:

    class PostsController < ApplicationController
      acts_as_collection :title => 'posts', :workspace => 'blog',
        :href=> 'http://myblog', :accept => Mime::ATOM_ENTRY
    ...

Al marcar este primer controlador para que actúe como una colección automáticamente se le añade un filtro anterior a los métodos de crear y actualizar un elemento. El método que invoca el filtro se debe llamar filter_content_type y los nombres de los métodos sobre los que se ejecuta se pueden configurar como variables de entorno, siendo por defecto create y update.

El segundo controlador será el encargado de generar el documento de servicio, así que lo marcaremos como tal:

    class ServicesController < ApplicationController
        acts_as_service_document
    ...

Finalmente, para que el controlador genere el documento de servicio solo tendremos que llamar al método "service_document" que le aporta el plugin dentro de otro de los métodos del controlador:

    def index
      render :xml => service_document
    end

y nos generará un xml parecido a este:

  <service xmlns:atom='http://www.w3.org/2005/Atom' xmlns='http://www.w3.org/2007/app'>
    <workspace>
      <atom:title>blog</atom:title>
      <collection href='http://myblog'>
          <atom:title>posts</atom:title>
          <accept>application/atom+xml;type=entry</accept>
     </collection>
    </workspace>
  </service>

Además, este plugin añade varios tipos Mime necesarios para la cumplir especificación de AtomPub:

    Mime::ATOM_ENTRY == 'application/atom+xml;type=entry'
    Mime::ATOM_SVC == 'application/atomsvc+xml'
    Mime::ATOM_CAT == 'application/atomcat+xml'

Para finalizar, he decidido sobreescribir uno de los nuevos helpers de rails, concretamente el que nos ayuda a escribir documentos Atom. El método original no permite añadir nuevos espacios de nombres siendo su llamada tal que así:

    atom_feed do |feed|
    ...

mientras que con este plugin podríamos escribir:

    atom_feed( 'xmlns:app' => 'http://www.w3.org/2007/app') do |feed|
    ...

Cabe decir que el método para sobreescribir 'atom_feed' sólo funciona con la versión actual de Rails (2.0RC) y posteriores. En el fichero README del plugin se puede encontrar una documentación mucho más detallada. Cualquier duda, sugerencia o mejora es bienvenida.

Validando feeds contra el w3c 1

Posted by david

Ultimamente he pasado demasiado tiempo jugando con los feeds de 11870, pero aunque tengo el proceso de creación bastante trillado y lo he dejado muy DRY nunca está de más validarlos.

El w3c tiene una web que te permite validar un feed alojado en una determinada url o pastearle el código que este genera dentro den un textarea. La principal pega es que si tu url es la de tu ordenador de desarrollo no la acepta y tienes que optar por la segunda opción.

Por suerte se les ocurrió liberar un api para no tener que estar copiando y pegando cada vez que queramos validar un feed que estemos desarrollando. Con esta api me he creado un script que indicándole el host y la ruta del feed, lo descarga y lo intenta validar contra el w3c, no es nada del otro mundo y seguro que es muy mejorable pero a mi me ha sido bastante útil.

Básicamente se trata de recoger el xml que genera el feed con la siguiente instrucción:

@response = Net::HTTP.get_response ARGV[0], ARGV[1], 80

Y enviarlo al validador:

v = W3C::FeedValidator.new
v.validate_data @response.body.to_s 

Una vez hecho esto podremos comprobar si el feed es válido con el método valid? y acceder a los mensajes a través de las variables errors, warnings e informations.

NOTA: El validador del w3c no funciona muy bien y de vez en cuando da algún error al validar, solo hay que insistir un poco hasta que pilla vuestro feed ;)

Extender relaciones de ActiveRecord 1

Posted by david

Hay veces que te encuentras pequeños trucos de Rails que muestran en unas pocas líneas de código toda la potencia de este framework.

En este caso James Buck, nos enseña como extender relaciones entre objectos ActiveRecord añadiendoles métodos adicionales.

Con este simple truco podremos escribir código tan limpio como:

mail.inbox.unreaded

de una forma mucho más eficiente de la que algunos estamos acostumbrados.