Не так давно я взялся за небольшой проект с клиент-серверной архитектурой. JSON веб-сервис мне позволили реализовать на clojure, что я очень быстро и сделал при помощи библиотек: Noir, Lobos, Korma и Cheshire. Но зато была масса непоняток с деплойментом этого готового сервиса на хостинг. Во-первых, по непонятной причине, оригинальный сервер, поработав какое-то время, попросту отваливается. Я до сих теряюсь в догадках, что заставляет его так капризничать. Понятное дело, что я решил задеплоить всё на Tomcat.
Мне не удалось нигде найти нормальной инструкции о том, как деплоить noir-приложение под томкат, так что я решил восполнить этот пробел.
Данная инструкция рассчитана на веб-сайт, разработанный на clojure при помощи фреймворка Noir (опробовано на noir 1.3.0-alpha10).
1) Добавьте [lein-ring "0.5.4"] в :dev-dependencies вашего файла project.clj.
Внимание! [uk.org.alienscience/leiningen-war "0.0.13"] – это не то же самое, что lein-ring. Плагин lein-ring умеет создавать ring-handler для noir-приложения и запаковать все в war-ку. А плагин leiningen-war только создает war-ку, а ring-handler-а не создает.
2) В файле project.clj укажите ваш ring-handler и пространство имен для ahead-of-time компиляции.
:ring {:handler MyProject.server/handler}
:aot [MyProject.server]
3) Создайте ring-handler в server.clj:
(:require [noir.server :as server])
. . .
(def handler (server/gen-handler {:base-url "/myproject"}))
Внимание! Обязательно нужно указать :base-url, иначе редиректы и линки задеплоенного в томкат приложения будут указывать не на localhost:8080/myproject/, а на localhost:8080/ . Эпик фейл будет фееричный!
4) Уберите такую загрузку вьюх: (server/load-views "src/MyProject/views/") из файла server.clj. Вьюхи нужно загружать явно:
(:require [noir.server :as server]
. . .
[MyProject.views.pages])
Если этого не сделать, то после упаковки в war-ку и даже jar-ку, ни один ваш маршрут работать не будет.
5) Все линки и формы, если вы их генерите из hiccup, нужно создавать функциями:
(hiccup.form-helpers/form-to [:post "/myurl"] ...)
(hiccup.page-helpers/link-to "/myurl" …)
Если этого не сделать, то они будут вести на localhost:8080/ вместо localhost:8080/myproject.
6) Создайте war-ку командой lein ring uberwar.
Внимание! Команда lein ring uberwar поставляется с lein-ring-плагином, и в нашем случае она работает. Команда lein uberwar поставляется с плагином leiningen-war, и здесь она не работает. Так что этот плагин вообще лучше не использовать с noir.
7) Скопируйте war-ку в webapps томката и переименуйте её в myproject.war.
Теперь, после запуска томката, по адреусу localhost:8080/myproject будет ваше приложение.
Мне не удалось нигде найти нормальной инструкции о том, как деплоить noir-приложение под томкат, так что я решил восполнить этот пробел.
Данная инструкция рассчитана на веб-сайт, разработанный на clojure при помощи фреймворка Noir (опробовано на noir 1.3.0-alpha10).
1) Добавьте [lein-ring "0.5.4"] в :dev-dependencies вашего файла project.clj.
Внимание! [uk.org.alienscience/leiningen-war "0.0.13"] – это не то же самое, что lein-ring. Плагин lein-ring умеет создавать ring-handler для noir-приложения и запаковать все в war-ку. А плагин leiningen-war только создает war-ку, а ring-handler-а не создает.
2) В файле project.clj укажите ваш ring-handler и пространство имен для ahead-of-time компиляции.
:ring {:handler MyProject.server/handler}
:aot [MyProject.server]
3) Создайте ring-handler в server.clj:
(:require [noir.server :as server])
. . .
(def handler (server/gen-handler {:base-url "/myproject"}))
Внимание! Обязательно нужно указать :base-url, иначе редиректы и линки задеплоенного в томкат приложения будут указывать не на localhost:8080/myproject/, а на localhost:8080/ . Эпик фейл будет фееричный!
4) Уберите такую загрузку вьюх: (server/load-views "src/MyProject/views/") из файла server.clj. Вьюхи нужно загружать явно:
(:require [noir.server :as server]
. . .
[MyProject.views.pages])
Если этого не сделать, то после упаковки в war-ку и даже jar-ку, ни один ваш маршрут работать не будет.
5) Все линки и формы, если вы их генерите из hiccup, нужно создавать функциями:
(hiccup.form-helpers/form-to [:post "/myurl"] ...)
(hiccup.page-helpers/link-to "/myurl" …)
Если этого не сделать, то они будут вести на localhost:8080/ вместо localhost:8080/myproject.
6) Создайте war-ку командой lein ring uberwar.
Внимание! Команда lein ring uberwar поставляется с lein-ring-плагином, и в нашем случае она работает. Команда lein uberwar поставляется с плагином leiningen-war, и здесь она не работает. Так что этот плагин вообще лучше не использовать с noir.
7) Скопируйте war-ку в webapps томката и переименуйте её в myproject.war.
Теперь, после запуска томката, по адреусу localhost:8080/myproject будет ваше приложение.
Где ж Вы были две недели назад? Впрочем, это мало что поменяло бы. :)
ОтветитьУдалить>Мне не удалось нигде найти нормальной инструкции о том, как деплоить noir-приложение под томкат
А я почему-то нашёл кучку форумов, списков рассылки, gist'ов, где написано что делать, хоть и не так пошагово. Или Вы на русском искали? ;)
> :aot [MyProject.server]
Интересно, но у меня и без него компилируется.
> Обязательно нужно указать :base-url, иначе редиректы и линки задеплоенного в томкат приложения будут указывать не на localhost:8080/myproject/, а на localhost:8080/
Вылечил при помощи mod_proxy. :)))
Но спасибо, что рассказали - не придётся потом искать.
>Уберите такую загрузку вьюх: (server/load-views "src/MyProject/views/")
Как пишут, именно она и должна лечить проблему с war'ами, но по факту не лечит. :) Так что тоже сделал ручной импорт вьюх, но и эту строчку убирать не стал - не мешает же. :)
> Скопируйте war-ку в webapps томката и переименуйте её в myproject.war
А я через web деплою. :)))
Надеюсь, следующие поколения Clojure web-программистов ещё выразят Вам благодарность - теперь всё расписано по шагам и по-русски.
Спасибо! :)
> А я почему-то нашёл кучку форумов, списков рассылки, gist'ов, где написано что делать, хоть и не так пошагово. Или Вы на русском искали? ;)
ОтветитьУдалитьИнфа, конечно, есть, но она размазана ровным слоем по разным форумам. Здесь я решил всё собрать в одном месте.