Skip to content
Gabriel Horner edited this page Jul 4, 2013 · 12 revisions

Aspects

The Pedestal development tools are themselves just a Clojure web application and can easily be modified to meet the specific needs of a project.

The Tools menu contains several links which allow us to view and work with our application in different ways. Each of these "ways" is called an aspect because it allows us to focus on one part of the application in isolation.

  • Data UI - run application logic without a renderer and with a simulated back-end
  • Render - render without running application logic
  • Development - run everything in development mode
  • Production - run everything with advanced compilation

In this section we will see that it is easy to add our own new aspects.

Combining the custom renderer and the simulated back-end

It would good to have a new aspect that combined the simulated back-end with the custom renderer. This would allow us to see and interact with a more realistic version of the application without having to run a service and simulate activity from multiple browsers.

To add an aspect, open the configuration file for the project. This is a Clojure file with a var named configs. Within this configuration map is a :aspects key associated with map containing each aspect.

The new aspect will have the key :ui and is shown below.

:ui {:uri "/tutorial-client-dev-ui.html"
     :name "UI"
     :order 2
     :out-file "tutorial-client-dev-ui.js"
     :main 'tutorial_client.simulated.start
     :recording? true
     :logging? true
     :output-root :tools-public}

Most of this configuration is straight forward. We give the aspect a unique URI, name and the order in which it will appear in the tools menu. We name the JavaScript output file. We define weather recording or logging are enabled for this aspect.

As you can see in other aspects, we can set the optimization level for each aspect using the :optimizations key.

The :output-root key determines where compiled output will be written on the file system. There are two possibilities: :public and :tools-public. :public will put compiled output into out/public and :tools-public will compile output to out/tools/public. Because this aspect is only used for development and will not be deployed, we compile output to :tools-public.

The main thing that makes each aspect different is the main function which is run to start the application. Each main function will wire things together in a different way. In the config file you will notice that the :data-ui aspect starts from tutorial_client.simulated.start while the :development and :production aspects start from tutorial_client.start. These are namespaces which contain a function named main.

The new new :ui aspect, we will use the same starting point :data-ui.

If we were to restart the server, we would see that there is now a new aspect named UI that is exactly the same as the Data UI aspect. They are the same because we are using the same starting point. We could make a new starting point but the only difference between these two aspects is the renderer which will be used. We will update the main function in tutorial_client.simulated.start to dynamically select the renderer based an a URL parameter.

To cause an aspect to send a parameter, we can add a :params key. Add the following key and value to the :data-ui aspect.

:params "renderer=auto"

We can now restart the server to test that the two aspects work and the new parameter is being sent when we use the Data UI aspect.

Determine the renderer to use at runtime

In the namespace tutorial-client.simulated.start, add the following new required namespaces.

[tutorial-client.rendering :as rendering]
[goog.Uri :as guri]

We need to update the main function to choose the renderer to use based on the value of the renderer parameter in the URL. The updated version of main is shown below.

(defn ^:export main []
  (let [uri (goog.Uri. (.toString (.-location js/document)))
        renderer (.getParameterValue uri "renderer")
        render-config (if (= renderer "auto")
                        d/data-renderer-config
                        (rendering/render-config))
        app (start/create-app render-config)
        services (services/->MockServices (:app app))]
    (app/consume-effects (:app app) services/services-fn)
    (p/start services)
    app))

If we now refresh the browser, we will see that the Data UI aspect uses the data renderer while the UI aspect now uses the custom renderer. Both aspects use the same simulated back-end so that we can now see updates to the other counters in the custom renderer.

Next steps

We have created a working client. It is now time create a service. In the next section we will build a simple service for our client to talk to. In the section after that we will connect to the server and have a completely working interactive counter application.

The tag for this step is v2.0.12.

Home | Making the Service | Connecting to a Service

Clone this wiki locally