<commit_before>boot-gae
--------

boot for Google AppEngine development

[IMPORTANT]
====
The documentation, like the code, is unpolished and partially
incomplete.  In particular the reader will probably need to have some
idea of how boot works.
====


* <<tasks>>
* <<usage>>
* <<repl>>
* <<config,config>>
* <<servlets,servlets>>
* <<config-map,configuration map>>

[[tasks]]
== tasks

* `gae/assets`          copy assets to build-dir
* `gae/config`          configure gae xml config files
* `gae/deploy`          install a new version of the application onto the server
* `gae/libs`            install dependency jars in <build-dir>/WEB-INF/lib
* `gae/install-sdk`     unpack and install the SDK zipfile
* `gae/logging`		configure gae logging
* `gae/run`		run devappserver
* `gae/servlets`	aot compile master servlet file


[[usage]]
== usage

[source,clojure]
.build.boot
----
...
:dependencies ... [migae/boot-gae "0.1.0-SNAPSHOT" :scope "test"] ...
...
(require '[migae.boot-gae :as gae] ...
----

[NOTE]
====
This documentation will use the namespace alias `gae`, as just shown,
to refer to boot-gae tasks.  For example, `gae/config` means `migae.boot-gae/config`.
====


Then you need to define a map named `gae` to configure things; see
<<config-map,below>> for details.

[source,clojure]
.build.boot
----
(def gae { ... details below ...}
----

[[repl]]
==== replry

Then you'll need to prepare things, as described below.  Once that's
done, you'll no doubt want to do repl-based development: change some
source code and have the results show up immediately in the browser.
We're not quite that replish: you have to refresh the browser.  To
make this work, you have to copy your changes into `WEB-INF/classes`.
That's because the GAE dev server will refuse to look anywhere else
for resources, for security reasons.

So if you want repl, you need to do two things. First, run the
following command before you start editing:

```
$ boot watch sift -i "clj$" target -d "build/WEB-INF/classes" -C
```

Now when a source file changes, `sift -i "clj$"` will exclude anything
not matching the include regex "clj$" and pass the result to `target`,
which will move everthing into the classpath.

[WARNING]
====
If you're going to be working with multiple file types you'll need to adjust the regex and/or run multiple watch pipelines.

For example, if you want to edit .css files located at <approot> (that
is, not in WEB-INF), you would run something like: 

```
$ boot watch sift -i "html$" target -d "build" -C
```
====


The second thing you need to do is install a filter servlet that will
reload your Clojure files from `WEB-INF/classes`.  Here's an example:

[source,clojure]
.migae/servlets.clj
----
(ns migae.servlets)
...
(gen-class :name migae.reloader
           :implements [javax.servlet.Filter]
           :impl-ns migae.reloader)
----

[source,clojure]
.migae/reloader.clj
----
(ns migae.reloader
  (:import (javax.servlet Filter FilterChain FilterConfig
                          ServletRequest ServletResponse))
  (:require [ns-tracker.core :refer :all]))
(defn -init [^Filter this ^FilterConfig cfg])
(defn -destroy [^Filter this])
(def modified-namespaces (ns-tracker ["./"]))
(defn -doFilter
  [^Filter this
   ^ServletRequest rqst
   ^ServletResponse resp
   ^FilterChain chain]
  (doseq [ns-sym (modified-namespaces)]
    (require ns-sym :reload))
  (.doFilter chain rqst resp))
----

[source,xml]
.WEB-INF/web.xml
----
  <filter-mapping>
    <url-pattern>/*</url-pattern>
    <filter-name>reloader</filter-name>
  </filter-mapping>
  <filter>
    <filter-name>reloader</filter-name>
    <filter-class>migae.reloader</filter-class>
  </filter>
----

To make this work, all you need to provide is the `migae/reloader.clj`
file and set the configuration map.  The `WEB-INF/web.xml` files will
be autogenned as explained in <<config>>, and the
`migae/servlets.clj` file will be autogenned, aot-compiled, and
discarded, as explained in <<servlets>>.

== prep
Once your `build.boot` is set up, you need to prepared the system.
boot-gae has a dependency on the GAE sdk, so the first time you run it
it will be downloaded.  Don't be alarmed if it takes a while; the SDK
is a ~165 MB zipfile.

The GAE dev server requires that the SDK be available in exploded
form.  The maven artifact that gets installed into `~/.m2/repository`
is a zipfile; the `gae/install-sdk` task will explode it and install
it.

Use the `:sdk-root` key in the `gae` configuration map to specify a
location.  The default is `~/.appengine-sdk`; if you want to be
compatible with Gradle, use `:sdk-root "~/.gradle/appengine-sdk".

Once the SDK is installed, proceed with preparing your webapp.  GAE
has strict security rules; the dev server will not allow access to
anything outside of the webapp's root directory.  That means that<commit_msg>README tweaks<commit_after>boot-gae
--------

boot for Google AppEngine development

[IMPORTANT]
====
The documentation, like the code, is unpolished and partially
incomplete.  In particular the reader will probably need to have some
idea of how boot works.
====


* <<tasks>>
* <<usage>>
* <<repl>>
* <<config,config>>
* <<servlets,servlets>>
* <<config-map,configuration map>>

[[tasks]]
== tasks

* `gae/assets`          copy assets to build-dir
* `gae/config`          configure gae xml config files
* `gae/deploy`          install a new version of the application onto the server
* `gae/libs`            install dependency jars in <build-dir>/WEB-INF/lib
* `gae/install-sdk`     unpack and install the SDK zipfile
* `gae/logging`		configure gae logging
* `gae/run`		run devappserver
* `gae/servlets`	aot compile master servlet file


[[usage]]
== usage

[source,clojure]
.build.boot
----
...
:dependencies ... [migae/boot-gae "0.1.0-SNAPSHOT" :scope "test"] ...
...
(require '[migae.boot-gae :as gae] ...
----

[NOTE]
====
This documentation will use the namespace alias `gae`, as just shown,
to refer to boot-gae tasks.  For example, `gae/config` means `migae.boot-gae/config`.
====


Then you need to define a map named `gae` to configure things; see
<<config-map,below>> for details.

[source,clojure]
.build.boot
----
(def gae { ... details below ...}
----

[[repl]]
==== replry

Then you'll need to prepare things, as described below.  Once that's
done, you'll no doubt want to do repl-based development: change some
source code and have the results show up immediately in the browser.
We're not quite that replish: you have to refresh the browser.  To
make this work, you have to copy your changes into `WEB-INF/classes`.
That's because the GAE dev server will refuse to look anywhere else
for resources, for security reasons.

So if you want repl, you need to do two things. First, run the
following command before you start editing:

```
$ boot watch sift -i "clj$" target -d "build/WEB-INF/classes" -C
```

Now when a source file changes, `sift -i "clj$"` will exclude anything
not matching the include regex "clj$" and pass the result to `target`,
which will move everthing into the classpath.

[WARNING]
====
If you're going to be working with multiple file types you'll need to adjust the regex and/or run multiple watch pipelines.

For example, if you want to edit .css files located at <approot> (that
is, not in WEB-INF), you would run something like: 

```
$ boot watch sift -i "html$" target -d "build" -C
```
====


The second thing you need to do is install a filter servlet that will
reload your Clojure files from `WEB-INF/classes`.  Here's an example:

[source,clojure]
.build.boot
----
(def gae
 {...
   :filters [{:ns 'migae.reloader   ; REQUIRED
              :name "reloader"      ; REQUIRED
              :display {:name "Clojure reload filter"} ; OPTIONAL
              :urls [{:url "/echo/*"}
                     {:url "/math/*"}]
              :desc {:text "clojure reload filter"}}]
  ...}
----

[source,clojure]
.migae/servlets.clj
----
;; DO NOT EDIT THIS FILE
;; autogenned from build.boot and template
(ns migae.servlets)
...
(gen-class :name migae.reloader
           :implements [javax.servlet.Filter]
           :impl-ns migae.reloader)
----

[source,clojure]
.migae/reloader.clj
----
(ns migae.reloader
  (:import (javax.servlet Filter FilterChain FilterConfig
                          ServletRequest ServletResponse))
  (:require [ns-tracker.core :refer :all]))
(defn -init [^Filter this ^FilterConfig cfg])
(defn -destroy [^Filter this])
(def modified-namespaces (ns-tracker ["./"]))
(defn -doFilter
  [^Filter this
   ^ServletRequest rqst
   ^ServletResponse resp
   ^FilterChain chain]
  (doseq [ns-sym (modified-namespaces)]
    (require ns-sym :reload))
  (.doFilter chain rqst resp))
----

[source,xml]
.WEB-INF/web.xml
----
  <filter-mapping>
    <url-pattern>/echo/*</url-pattern>
    <filter-name>reloader</filter-name>
  </filter-mapping>
  <filter-mapping>
    <url-pattern>/math/*</url-pattern>
    <filter-name>reloader</filter-name>
  </filter-mapping>
  <filter>
    <filter-name>reloader</filter-name>
    <filter-class>migae.reloader</filter-class>
  </filter>
----

To make this work, all you need to provide is the `migae/reloader.clj`
file and set the configuration map.  The `WEB-INF/web.xml` file will
be autogenned as explained in <<config>>, and the
`migae/servlets.clj` file will be autogenned, aot-compiled, and
discarded, as explained in <<servlets>>.

== prep
Once your `build.boot` is set up, you need to prepared the system.
boot-gae has a dependency on the GAE sdk, so the first time you run it
it will be downloaded.  Don't be alarmed if it takes a while; the SDK
is a ~165 MB zipfile.

The GAE dev server requires that the SDK be available in exploded
form.  The maven artifact that gets installed into `~/.m2/repository`
is a zipfile; the `gae/install-sdk` task will explode it and install
it.

Use the `:sdk-root` key in the `gae` configuration map to specify a
location.  The default is `~/.appengine-sdk`; if you want to be
compatible with Gradle, use `:sdk-root "~/.gradle/appengine-sdk".

Once the SDK is installed, proceed with preparing your webapp.  GAE
has strict security rules; the dev server will not allow access to
anything outside of the webapp's root directory.  That means that
{'fraction_non_alphanumeric': 0.12471833055746057, 'fraction_numerical': 0.001371607720192025, 'mean_word_length': 3.4056970220112213, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1005427', 'n_tokens_mistral': 3345, 'n_tokens_neox': 3193, 'n_words': 1261}