The ape 1.5 released 0

Posted by david

Yesterday I released a new version of The atom protocol exerciser. We have been working in order to simplify its architecture and create a modular system that anyone may extend.

Now it works from the command line as well the web interface. We've added some rake tasks that you can use for exercise your server implementation and you can select the output format just invoking the correct option:


 $ rake ape:go:text['service document uri']
 $ rake ape:go:html['service document uri']
 $ rake ape:go:atom['service document uri']

It allows some configuration options through its config file $APE_HOME/aperc:


Ape.conf[:REQUESTED_ENTRY_COLLECTION] = 'collection name'
Ape.conf[:REQUESTED_MEDIA_COLLECTION] = 'collection name'

And finally, this last release allows to create and add new tests easily. The test cases must to extend the Ape Validator class and override the validate method.


module Ape
  class CustomValidator < Validator
    def validate(opts = {}) end
  end
end

We've implemented a little system for select the variables to use in your tests, just call the requires_presence_of method into the class declaration and pass the variable name that you require.


module Ape
  class CustomValidator < Validator
    requires_presence_of :entry_collection #OR
    requires_presence_of :entry_collection => 'comments' #OR
    requires_presence_of :media_collection => {:accept => 'image/png'}
    #...

Once your custom validator is ready you just need to move it to $APE_HOME/validators.

But if you really want to learn how to write your custom validator you just need to take a look at the source code.

Using Hudson as Rails CI server 2

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.

2 cosas que acabo de aprender sobre Rake 0

Posted by david

  1. Que si creas una carpera llamada rakelib en el raiz de tu proyecto, rake carga todos los ficheros con la extensión .rake que encuentre dentro de ella. Con lo que supongo que esta feature no estaba en las primeras versiones porque Rails se está cargando toda la convención de esta librería al hacer esto dentro del fichero railties/lib/tasks/rails.rb:

    
    Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
    Dir["#{RAILS_ROOT}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
    
  2. Que puedes pasarle argumentos a tus tareas. No puede ser una lista variable de argumentos y no pueden tener valor por defecto:

    
    task :go, :uri, :username, :password do |task, args|
    end
    
    
    $ rake -T
    rake go[uri,username,password]
    

Shoes promete pero tampoco cumple 0

Posted by david

El jueves pasado celebramos en la ofi un pequeño workshop sobre nuestra api. Nuestra idea inicial era hacer una pequeña introducción y plantear un par de ejercicios previamente preperados por nosotros para que los asistentes picaran algo de código. Por desgracia, tampoco teníamos demasiado tiempo y al final decidimos exponer los ejercicios y comentar el código que nosotros habíamos escrito.

Personalmente, mi principal objetivo era dejar muy claro que es muy fácil de usar más allá de lo pone en la documentación y que se pueden hacer más cosas a parte de integraciones de búsqueda de sitios y servicios.

Como hacía tiempo que quería probar Shoes decidí hacer una pequeña aplicación que se conectaba con la cuenta de un usuario en 11870.com, se descargaba los últimos servicios que se habían guardado sus contactos y permitía que ese usuario se los guardara y los comentara. Para el que no conozca Shoes decir que es un pequeño framework para escribir pequeñas aplicaciones de escritorio multiplataforma de una forma sencilla. Mientras desarrollaba la aplicación ya me quedó claro que lo de "forma sencilla" ya no era cierto, ya que además de tener una documentación pésima (su autor, aunque es un desarrollador muy brillante, se dedica a hacer pdfs llenos de dibujitos sin sentido y no explicar como usar sus frameworks), el feedback que te da el framework es inexistente, no muestra excepciones si las hay y creo que tiene una consola de log pero no he encontrado como usarla ni como verla. Como punto final, cuando más o menos tenía la aplicación terminada decidí probarla en mi powerbook, la había desarrollado en mi sobremesa con ubuntu, y por supuesto el resultado fue el esperado después de dos días peleandome con el framework, la aplicación no llegó a arrancar.

Como tenía una cuenta de github sin estrenar he subido el código fuente ahí por si alguien quiere echarle un vistazo, si usas git simplemente ejecuta este comando:


  git clone git://github.com/calavera/oos-with-shoes.git

si no, puedes ver el código en el proyecto que he abierto.

The APE meets RubyGems 2

Posted by david

When I talked about the ape in the past Conferencia Rails 07 I remarked that it wasn't quite easy to install and configure. Today I can announce that this is no longer true.

We've transformed a lot of scripts in a ruby gem that provides a Mongrel based server. Once the ape gem is installed and this server is running, the web interface is available in the port 4000 of your localhost.


  $ sudo gem install ape && ape_server

Moreover, the new ape gem uses the erubis library to load the atom entry templates that it uses to test the atomPub server. These templates can be overrided by the user, the gem searchs the APE_HOME enviromment variable or the .ape directory into the user home directory. Within this directory the user can leave his atom entry templates with the names mini_entry.eruby, basic_entry.eruby or unclean_xhtml_entry.eruby.

We are excited with this release and we are working hard to eliminate possible bugs and add documentation in addition to new capabilities in order to test any atomPub server behaviour.

Enjoy it!

La charla de los viernes 5

Posted by david

Hace unos meses instauramos una costumbre en la ofi, los viernes un miembro del equipo de tecnología debía dar una charla sobre algún tema que le pareciera interesante. En este tiempo hemos hablado sobre behaviour driven development, atom publishing protocol, amazon s3, python, metodología ágiles...

Pero como tampoco somos tanta gente, y ya nos estamos quedando sin ideas, hemos decidido abrir nuestras puertas a la gente de la calle. Así, si alguien se encuentra por Madrid un viernes y le apetece pasarse a evangelizarnos sobre algún tema en concreto puede enviarme un correo a david.calavera arroba 11870.com contando un poquillo de lo que nos quiere hablar y proponiendo una fecha.

Aclaraciones

En principio debería ser un viernes antes de comer, a eso de las 13h (luego podemos organizar un comida familiar), aunque podríamos buscar otro día por la tarde si es imposible ese día. Por problemas de espacio, de momento, no podemos aceptar público externo, aunque podemos hacer alguna excepción.

Por cierto, mañana tenemos nuestro primer invitado, con una charla muy interesante sobre grid computing.

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 :-).

BDD & RSpec rulez 0

Posted by david

¿Por qué deberías pensar en usar BDD y RSpec?

Un ejemplo vale más que mil palabras

AtomPub, ruby y la api de 11870.com 2

Posted by david

Así se titula la charla que imparto en la segunda conferencia rails. Pretende ser una introducción a atomPub, la api de 11870 y todo esto mezclado con un poco de ruby.

Ya podéis descargar la presentación en formato pdf. Agradezco cualquier comentario, espero que sea útil.

Actualización: he subido la presentación a SlideShare para que se pueda ver desde aquí.

Conferencia Rails 2007 0

Posted by david

Este jueves comienza la segunda Conferencia Rails Hispana. Este año estaré hablando sobre AtomPub, ruby y la api de 11870.com. Cuando acabe subiré la presentación aqui para uso y disfrute.

ponente

Nos vemos allí.

Rails plugin: atom_pub_server 0

Posted by david

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.

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.

Validando feeds contra el w3c 0

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 ;)

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);

Crear fixtures fácilmente 2

Posted by david

Ruby on rails nos proporciona muchas comodidades a la hora de hacer desarrollos orientados a test. Quizá uno de los mayores inconvenientes sea tener que escribir nuestas fixtures, porque al trabajar con modelos algo complicados puede que no sean todo lo válidas que nos gustaría.

Fixturease es una gema que nos permite crear fixtures directamente a partir del modelo de nuestra aplicación.

Su instalación es muy sencilla:

sudo gem install fixturease

Una vez instalada, nos situamos en el directorio raiz de nuesta aplicación y ejecutamos el script fixturease.rb. Este, nos abrirá una consola que nos permitirá crear nuestas fixtures.

Supongamos que ejecutamos en esta consola el siguiente comando:

@david = User.create(:login => 'david', :password => 'pass')

Fixturease nos creará el fichero fixtures/users.yml con la siguiente entrada:

david:
  id: 1
  password: pass
  login: david
  created_at: 2007-01-20 21:40:23.250000 +02:00

Creo que es una buena forma de tener un poco más de control sobre nuestas fixtures y no tener que centrarnos en escribir un fichero yaml a mano.