2011-10-10 9 views
8

Estoy diseñando un servidor REST JAX-RS usando Clojure y RESTEasy.Programación Clojure "DSL"

Tengo entendido que las aplicaciones escritas en lenguajes de familias Lisp son, más que en los lenguajes imperativos "tradicionales", creadas como "lenguajes específicos de dominio". La aplicación se diseña de abajo arriba como más y más funciones "refinadas" hasta que, en el nivel "superior", la aplicación se convierte en una serie de llamadas a funciones de muy alto nivel.

Estoy intentando hacer esto para mi servidor REST, comenzando con las clases de recursos que sirven las solicitudes de URL (GET, POST, PUT, DELETE).

Aquí es mi primer recurso:

(ns com.example.server.resources.buildtime 
    (:import [javax.ws.rs CookieParam GET Produces Path] 
      [javax.ws.rs.core Context Cookie NewCookie Response UriInfo] 
      [org.jboss.resteasy.annotations.providers.jaxb Formatted])) 

(definterface BuildTime 
    (getBuildTime [^javax.ws.rs.core.UriInfo info 
       ^javax.ws.rs.core.Cookie security-cookie])) 

(deftype 
    ^{Formatted true} 
    BuildTimeResource [] 
    BuildTime 
    (^{GET true 
    Path "/buildtime" 
    Produces ["application/json"]} 
    getBuildTime 
    [this info security-cookie] 
    (.. (Response/ok "20111009") build))) 

Este recurso devuelve el tiempo de creación de servidores como una cadena (encerrado en un paquete JSON) cuando se llama a la URL "/ Buildtime" con el método HTTP GET.

Escribiré muchas más de estas clases de recursos y métodos incluidos (la mayoría de las clases tendrán más de un método), cada una con un definterface y un deftype. Esto parece ser un uso perfecto para macros.

Estoy solicitando sugerencias sobre cómo se podría hacer esto como una DSL. ¿Cómo se puede pensar en términos de DSL?

+3

Para empezar: deje de pensar en términos de "clases". Ya es un DSL, ya un poco de semántica potencialmente alienígena que puede que no desee ver en la DSL final. Comience especificando el problema formalmente. Enumere las entidades, defina un álgebra sobre ellas y cristalizará de forma natural en su DSL. Solo entonces debes comenzar a pensar en la implementación. –

+1

¿Conoces el compojure? https://github.com/weavejester/compojure Proporciona un DSL similar al que parece tener en mente. También encontré este artículo http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure útil para entrar en 'dsl-mode'. Pero crear un buen DSL no parece una tarea fácil ... – Paul

+0

@Paul: Consideré Compojure. Ya tenemos un gran servidor REST escrito en RESTEasy/Java. Facilitar una nueva versión basada en Clojure en la organización tendrá menos resistencia si utilizo un marco con el que estamos familiarizados. Además, JAX-RS tiene algunas características muy agradables. – Ralph

Respuesta

3

Si estuviera haciendo esto, creo que comenzaría creando un adaptador de anillo para RESTEasy. Una vez hecho esto, Compojure sabrá cómo manejar y responder a las solicitudes http de una manera que funcione con RESTEasy. Aquí hay información para ayudarlo a comenzar.

Ring es una biblioteca de clojure que representa solicitudes y respuestas HTTP de forma estándar. Esta norma se detalla en here.

Funciona al recibir una solicitud http de cualquiera de una variedad de bibliotecas (es decir, embarcadero, netty, finagle) y traducirla a la representación estándar. A continuación, entrega la solicitud a un manejador de solicitudes (a menudo esto se define usando Compojure). El manejador luego devuelve una respuesta (también definida en la especificación anterior). Esta respuesta se traduce por devolución de llamada a un formulario que el embarcadero, netty, etc. puede entender.

Esta traducción se realiza mediante adaptadores de anillo. Hay algunos enumerados here, y el anillo viene con un adaptador para embarcadero incorporado. Tal vez pueda usar uno de ellos como plantilla para crear un adaptador RESTEasy. Después de que hayas hecho eso, puedes usar compojure de la manera estándar.

El anillo y los componentes son excelentes ejemplos de cómo crear un DSL. Al igual que todas las DSL buenas, simplifica la creación de soluciones en su dominio problemático (servidores HTTP en este caso). Son excelentes ejemplos de cómo pensar en términos de DSL. Si los estudias, estarás en camino a pensar en términos de DSL.