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.

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.

Apache Abdera supports AtomPub-multipart creation 0

Posted by david

One of the most weird stuff in the AtomPub specification is the media creation flow. First, you need to send a request in order to post the new media resource and once the response is correct you can update the media link entry related with it.

In order to avoid the second step, the Picassa team added to their api a new way to add photos, and now, they allow to send a multipart file that wraps the photo and its metadata.

This atom extension is been covered by an IEFT draft that Joe Gregorio published, and this morning I've updated the Abdera trunk in order to implement this specification.

You can read more into the Abdera wiki. Enjoy it.

Using Hudson as Rails CI server 3

Posted by david

For some time, Hudson has become my favorite continuous integration server. It's easy to configure and provides a handful of really interesting plug-ins. The only thing that I missed was the possibility of use Rake as a project build tool and thus I'll be able to take my java, ruby or rails projects into the same CI server.

Well, past weekend I had too much spare time so I decided to develop my first Hudson plugin and this morning I've released the first version of the Hudson Rake plugin.

Once you have installed Hudson you just need to donwload the plug-in and upload it from the Manage Hudson section:

When the plugin is avalable it detects your ruby instances installed from your PATH but it allows you to add other ruby or jruby paths:

Finally you just need to select the Invoke Rake option into the project configuration and select the tasks that you want to Hudson executes:

That's it, you are ready to go with Rake, Hudson and the Continuous Integration Game.

Usa ruby para testear tu código java 2

Posted by david

Aunque navegando por la web se pueden encontrar artículos sobre cómo usar rspec para testear código java y ya existe algún framework de bdd para java, desde hace unas semanas existe una librería que nos da las mejores herramentas de test que ruby posee para aplicarlas con nuestro código java.

JtestR es una librería que integra jruby con rspec, dust, mocha y ActiveSuport, y permite ejecutar nuestros test escritos en ruby con herramentas de automatización como Ant o Maven.

Para ejecutarlos con Ant es tan facil como incluir una nueva tarea en nuestro fichero de configuración:

<target name="test" description="Runs all tests">
  <taskdef name="jtestr" classname="org.jtestr.ant.JtestRAntRunner" classpath="lib/jtestr.jar"/>

  <jtestr tests="test/ruby"/>
</target>

Pero lo que más me gusta de este framework es poder usar rspec para testear mis clases java, un sencillo ejemplo podría ser este:

import java.util.HashMap

describe HashMap, "is empty" do
  before :each do
    @map = mock(HashMap)
  end

  it "should be empty" do
    @map.stubs(:size).returns(0)

    @map.should be_empty
  end
end

Una herramienta a tener en cuenta si, como yo, pasas el día entre código java y código ruby :-).

Consumir microformatos con XQuery

Posted by david

XQuery es un lenguaje para hacer consultas bien formadas sobre documentos xml. Combinado con TagSoup, que permite parsear cualquier documento html como si fuera xml, y un procesador de documentos como Nux es muy facil consumir microformatos de cualquier web.

Como supuesto veamos como consumir el hcard de uno de mis sitios favoritos en 11870, el café Costello.

XQuery está basado en XPath pero además nos permite hacer consultas más cercanas al sql. La consulta para extraer del dom de un documento xml un elemento cuyo atributo contenga la palabra vcard podría ser así:

    String query = "declare namespace xhtml=\"http://www.w3.org/1999/xhtml\"; \n" +
        " for $data in //xhtml:* \n"+
        " where contains($data/@class, \"vcard\") \n" +
                " return  { data($data) } ";

Refinandola un poco más podríamos decir que solo queremos mostrar unos cuantos nodos, como los que contengan el nombre, dirección, localidad, provincia y país del sitio:

    String query = "declare namespace xhtml=\"http://www.w3.org/1999/xhtml\"; \n" +
        "for $data in //xhtml:* \n"+
    " where contains($data/@class, \"vcard\") \n"+
    " return <vcard> \n" + 
        " <fn> { data($data//xhtml:*[contains(@class, \"fn\")]) } </fn>" +
        " <street-address> { data($data//xhtml:*[contains(@class, \"street-address\")]) } </street-address>" +
        " <locality> { data($data//xhtml:*[contains(@class, \"locality\")]) } </locality>" +
        " <region> { data($data//xhtml:*[contains(@class, \"region\")]) } </region>" +
        " <country-name> { data($data//xhtml:*[contains(@class, \"country-name\")]) } </country-name>" +
    " </vcard> ";

Una vez tenemos la consulta, podemos obtener el html haciendo una llamada por get a la dirección de nuestra página:

    GetMethod get = new GetMethod("http://11870.com/pro/20770"); 
    get.setFollowRedirects(true); 

    HttpClient httpClient = new HttpClient();
    httpClient.executeMethod(get); 
    InputStream in = get.getResponseBodyAsStream(); 

Y transformar el html en xml para ejecutar nuestra consulta xquery:

    XMLReader parser = new org.ccil.cowan.tagsoup.Parser();
    Document doc = new Builder(parser).build(in);
    Nodes results = XQueryUtil.xquery(doc, query);

La variable results almacenaría el resultado de ejecutar la consulta, donde quedaría un xml parecido a este:

    <vcard>
        <fn>Costello Cafe</fn>
        <street-address>Calle del Caballero de Gracia 10</street-address>
        <locality>Madrid</locality>
        <region>Madrid</region>
        <country-name>España</country-name>
    </vcard>

TagSoup facilita bastante la tediosa tarea de parsear un html ya que transforma hasta los documentos peor formados, y con unos conocimientos de xquery las posiblidades son casi infinitas. Todo el código del ejemplo se puede descargar de aqui.

Java 6 y tu dni electrónico

Posted by david

Ahora que han pasado unos meses desde el lanzamiento de Java 6 y que en casi en cualquier provincia puedes expedir un dni electrónico ya podemos empezar a pensar como hacer uso de ambos.

Dentro de nuestro dnie se encuentran varios certificados digitales para firma electrónica o autenticación, para acceder a ellos necesitamos es un lector de tarjetas que acepte nuestro documento.

Una de las nuevas incorporaciones en java 6, y de las menos publicitadas, es el soporte nativo para acceder al almacen de claves de windows. Hasta ahora teníamos que usar complejas DLLs de windows para acceder a este almacen, pero con esta nueva release es tan fácil como esto:

KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);

Como no todos en este mundo usamos ese sistema operativo, dentro de nuestro dnie también podremos encontrar los certificados dentro de una librería PKCS#11 llamada opensc-pkcs11.so que podremos usar en cualquier otro sistema. El proceso de acceder a una librería PKCS#11 es un poco más tedioso pero hay muy buenos artículos en la red que lo explican . Una aproximación rápida podría ser que tenemos que añadir esta librería como un proveedor de certificados a nuestro almacen de claves PKCS#11 y luego acceder a este para recuperar los certificados. Para añadir la librería a nuestro almacén necesitaríamos algo como esto:

String pkcs11config = "name = DNIE\nlibrary = opensc-pkcs11.so ";
InputStream confStream = new ByteArrayInputStream(pkcs11config.getBytes());

Class sunPkcs11Class = Class.forName("sun.security.pkcs11.SunPKCS11");
Constructor pkcs11Constr = sunPkcs11Class.getConstructor(InputStream.class);

Provider pkcs11Provider = (Provider) pkcs11Constr.newInstance( confStream );
Security.addProvider(pkcs11Provider);

para acceder a este almacén:

KeyStore keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, password);

Una vez cargado nuestro almacén de claves correspondiente podríamos acceder a todos los certificados que contiene a través de sus alias:

Enumeration enumeration = keyStore.aliases();
while (enumeration.hasMoreElements()) {

String alias = enumeration.nextElement().toString();
Certificate[] certs = store.getCertificateChain( alias );

}

Y con esto ya tendríamos acceso a los certificados de nuestro dni electrónico y podríamos ir pensando en como darles uso.

Actualización: Si nuestros usuarios usan Mac OS X y queremos acceder al almacén de claves de este sistema tendríamos que usar el siguiente código:

KeyStore keyStore = KeyStore.getInstance("KeychainStore", "Apple");
keyStore.load(null, null);

Ahorrar tiempo con hibernate-tools 1

Posted by david

Una de las pegas que encuentro al trabajar con Hibernate es que me obliga a escribir el script de creación de tablas en base de datos, el fichero de mapeo de estas tablas en Hibernate y las clases Java que actuan como entidad.

Hibernate Tools, aporta un plugin de Eclipse y una serie de tareas para Ant que facilitan un poco la vida del desarrollador. En este artículo vamos a hacer una pequeña introducción a estas tareas para ver como podemos generar diréctamente el script de creación de las tablas y las clases Java a partir de nuestro fichero de mapeo hbm.

Para trabajar con la extensión de Ant no es necesario todo el paquete que nos descargamos. Podemos extraer únicamente el fichero hibernate-tools.jar que se ecuentra dentro del directorio /plugins/org.hibernate.eclipse_3.2.0.beta9a/lib/tools/.

Una vez tenemos la librería en nuestro directorio de trabajo lo primero que tenemos que hacer es definir la tarea hibernatetool dentro de nuestro fichero build.xml:

    <taskdef name="hibernatetool" 
         classname="org.hibernate.tool.ant.HibernateToolTask" 
     classpathref="buildpath" />

En el capítulo dedicado a las tareas de Ant nos indican varias formas para añadir la configuración de Hibernate. Para mí, la más cómoda es decirle donde se encuentra el fichero con la configuración básica y luego añadir los hbm que queremos que utilice:

    <configuration configurationfile="hibernate.cfg.xml">
        <fileset dir="${xml.dir}">
            <include name="**/${hbm.file}.hbm.xml"/>
        </fileset>
    </configuration>

Una vez que ya tenemos configurada nuestra tarea veamos los métodos que tenemos disponibles para exportar los ficheros hbm.

El primero de ellos es hbm2java, el encargado de generar nuestras clases Java. Su uso es muy sencillo:

    <hbm2java/>

El segundo que vamos a ver es hbm2ddl. Este exporter nos genera el sql de creación de las tablas en base de datos. Los atributos más comunes que se le añaden suelen ser el nombre del fichero que quieres que genere, si quieres que este fichero tenga un buen formateado o si deseas que además ejecute el sql directamente contra la base de datos:

    <hbm2ddl outputfilename="hbm2ddl.sql" 
        export="false" create="true" format="true"/>

Con todo esto ya tenemos nuestra nueva tarea creada. Para el que no le apetezca hacer mucho copy/paste puede ver todo el código en el fichero que yo suelo utilizar.