36 votes

Le développement de Compojure sans redémarrage du serveur Web

J'ai écrit un petit Swing Application avant d'en Clojure et maintenant, je voudrais créer un style Ajax Web-App. Compojure ressemble le meilleur choix pour l'instant, alors c'est ce que je vais essayer.

J'aimerais avoir un réel minuscule modifier/essayer de rétroaction en boucle, donc je préfère ne pas redémarrer le serveur web après chaque petit changement que je fais.

Quelle est la meilleure façon d'accomplir cette? Par défaut mon Compojure de l'installation (la norme des choses avec ant deps/ant avec Jetty) ne semble pas recharger toute les modifications que je fais. Je vais avoir à redémarrer avec de l'exécution du serveur pour voir les modifications. En raison de la Java, du patrimoine et de la façon dont le système est démarré, etc. C'est sans doute parfaitement normale, et la façon dont il devrait être quand j'ai démarrer le système à partir de la ligne de commande.

Toujours, il doit y avoir un moyen de recharger les choses de façon dynamique pendant l'exécution du serveur. Dois-je utiliser Compojure de REPL pour accomplir mon objectif? Si je devrais le faire, comment puis-je recharger mon truc là?

38voto

mtnygard Points 4517

C'est tout à fait une vieille question, et il y a eu des changements récents qui font de ce beaucoup plus facile.

Il y a deux choses principales que vous souhaitez:

  1. Le contrôle devrait revenir à la RÉPLICATION de sorte que vous pouvez garder à interagir avec votre serveur. Ceci est accompli en ajoutant {:rejoindre? false} options lors du démarrage du serveur Jetty.
  2. Vous souhaitez récupérer automatiquement les changements dans certains espaces de noms lors de la modification des fichiers. Cela peut être fait avec l'Anneau du "wrap-reload" middleware.

Un jouet application devrait ressembler à ceci:

(ns demo.core
  (:use webui.nav
    [clojure.java.io]
    [compojure core response]
    [ring.adapter.jetty :only [run-jetty]]
    [ring.util.response]
    [ring.middleware file file-info stacktrace reload])
  (:require [compojure.route :as route] view)
  (:gen-class))

; Some stuff using Fleet omitted.    

(defroutes main-routes
  (GET "/" [] (view/layout {:body (index-page)})
  (route/not-found (file "public/404.html"))
)

(defn app
  []
  (-> main-routes
      (wrap-reload '(demo.core view))
      (wrap-file "public")
      (wrap-file-info)
      (wrap-stacktrace)))

(defn start-server
  []
  (run-jetty (app) {:port 8080 :join? false}))

(defn -main [& args]
  (start-server))

Le wrap-fonction reload décore votre application routes avec une fonction qui détecte les changements dans la liste des espaces de noms. Lors du traitement d'une demande, si ces espaces ont été modifié sur le disque, ils sont rechargés avant le traitement de la demande. (Ma "vue" de l'espace de noms est créé dynamiquement par la Flotte, de sorte que cette auto-recharge mes modèles chaque fois qu'elles changent, aussi.)

J'ai rajouté quelques morceaux de middleware que j'ai trouve toujours utile. enveloppez-les descripteurs de fichiers statiques actifs. enveloppez-fichier-info définit le type MIME sur ceux statique actifs. enveloppez-stacktrace aide au débogage.

À partir de la REPL, vous pouvez lancer cette application en utilisant l'espace de noms et d'appel start-serveur directement. L' :gen-classe de mot-clé et la fonction principale signifie que l'application peut également être emballés comme un uberjar pour le démarrage de l'extérieur de la REPL, trop. (Il y a un monde en dehors de la REPL? Eh bien, certaines personnes ont demandé pour elle de toute façon...)

22voto

auramo Points 4511

Voici une réponse que j'ai reçu de James Reeves dans le Compojure Groupe Google (la réponse est ici avec son autorisation):

Vous pouvez recharger un espace de noms en Clojure à l'aide de l' :recharger la clé de l'utilisation ou d'exiger des commandes. Par exemple, disons que vous avez un fichier "demo.clj" qui contient vos itinéraires:

(ns demo 
  (:use compojure))

(defroutes demo-routes 
  (GET "/" 
    "Hello World") 
  (ANY "*" 
    [404 "Page not found"]))

Lors de la RÉPLICATION, vous pouvez utiliser ce fichier et démarrer un serveur:

user=> (use 'demo) 
nil 
user=> (use 'compojure) 
nil 
user=> (run-server {:port 8080} "/*" (servlet demo-routes)) 
...

Vous pouvez aussi mettre de l'exécution des commandes du serveur dans un autre clojure fichier. Cependant, vous ne voulez pas mettre dans le même fichier que les trucs que vous voulez recharger.

Maintenant de faire quelques changements à la démo.clj. Lors de la RÉPLICATION de type:

user=> (use 'demo :reload) 
nil

Et vos modifications devraient maintenant s'afficher sur http://localhost:8080

13voto

emil10001 Points 349

Je voulais ajouter une réponse, puisque les choses ont un peu changé depuis la dernière réponse et j'avais passé un peu de temps à la recherche de moi-même.

  1. Installer leiningen (il suffit de suivre les instructions)

  2. Créer un projet

    lein new compojure compojure-test 
    
  3. Modifier l'anneau de la section de projet.clj

    :ring {:handler compojure-test.handler/app 
           :auto-reload? true
           :auto-refresh? true}
    
  4. Démarrer le serveur sur n'importe quel port que vous souhaitez

    lein ring server-headless 8080
    
  5. Vérifiez que le serveur est en cours d'exécution dans votre navigateur, la valeur par défaut de la base de route devrait simplement dire "Bonjour le monde". Ensuite, allez modifier votre gestionnaire (c'est dans src/project_name). Changer le bonjour tout le monde, le texte, enregistrer le fichier et de recharger la page dans votre navigateur. Il doit refléter le nouveau texte.

5voto

cemerick Points 3279

Pour faire suite au lien de Timothy avec la configuration de Jim Downing , j'ai récemment publié un ajout critique à cette référence qui, à mon avis, était nécessaire pour permettre le redéploiement automatique des applications compojure au cours du développement .

4voto

dnolen Points 12833

J'ai un script shell qui ressemble à ceci:

 #!/bin/sh                                                                                                                                   
CLASSPATH=/home/me/install/compojure/compojure.jar
CLASSPATH=$CLASSPATH:/home/me/clojure/clojure.jar
CLASSPATH=$CLASSPATH:/home/me/clojure-contrib/clojure-contrib.jar
CLASSPATH=$CLASSPATH:/home/me/elisp/clojure/swank-clojure

for f in /home/me/install/compojure/deps/*.jar; do
    CLASSPATH=$CLASSPATH:$f
done

java -server -cp $CLASSPATH clojure.lang.Repl /home/me/code/web/web.clj
 

web.clj ressemble à ceci

 (use '[swank.swank])                                                                                                                        
(swank.swank/ignore-protocol-version "2009-03-09")                                                                                          
(start-server ".slime-socket" :port 4005 :encoding "utf-8")
 

Chaque fois que je veux mettre à jour le serveur, je crée un tunnel ssh de ma machine locale à la machine distante.

Enclojure et Emacs (exécutant SLIME + swank-clojure) peuvent se connecter au REPL distant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X