EDIT: For a working sample, take a look at this demo project.
Disclaimer: I'm a total noob in building java web applications.
I'm trying to use JWT with Clojure but I simply don't know how deal with this "servlet" thing. So far, my idea was:
Create a WApplication with a "Hello World" form.
(defn make-hello-app [env]
(let [wapp (WApplication. env)
root (.getRoot wapp)]
(.setTitle wapp "Hello world")
(.addWidget root (WText. "Hello!!!!"))
wapp))
Create a servlet, inherited from WtServlet.
(def servlet
(proxy [WtServlet] []
(createApplication [env]
(make-hello-app env))))
Start jetty and use the servlet. This is what I don't know how to do. So far, this was my best shot:
(ns jwttest.core
(:use compojure.core)
(:use ring.adapter.jetty)
(:import (org.eclipse.jetty.server Server))
(:import (eu.webtoolkit.jwt WApplication WEnvironment WtServlet WText WPushButton WLineEdit WBreak)))
;; (the funcions above were defined here)
;; create a jetty server
(defn create-a-jetty-server []
(let [connector (doto (SelectChannelConnector.)
(.setPort 8080)
(.setHost "localhost"))
server (doto (Server.)
(.addConnector connector)
(.setSendDateHeader true))]
server))
;; start the application
(defn start-the-app []
(let [server (create-a-jetty-server)]
;; ???? .addServlet ? How?
(.start server)))
In my project.clj I have:
[org.clojure/clojure "1.4.0"]
[eu.webtoolkit/jwt "3.2.0"]
[compojure "1.1.1"]
[ring "1.1.2"]
I know ring can create a servlet from a handler, but in this case I already have a servlet so... what should I do to run this?
Note: I'm basing my code on this very old post made in 2009.
I dug through some of the Jetty API and the Ring/Noir jetty handling code and here's a summary of what I found (and haven't had a chance to test)
Jetty Server has a "setHandler" method which takes a handler (thanks Ring)
There is a ServletHandler class which looks like it fits into the above and which has a number of addServlet like methods which look like they do what you need them to.
You should be able to set the handler to a Servlet handler and go from there.
Related
I am currently working on a route planning robot that will deliver parcels around an office. The office is set up as a graph with weighted edges using ubegraph.
I have a recursive function that can plan the route for a journey between any amount of rooms. However I'm now trying to add 'parcels' to the robot and I'm unsure if the way I'm going about it is correct.
(defn journey [start end]
(alg/pprint-path (alg/shortest-path all-edges {:start-node start, :end-node end, :cost-attr :weight})))
(defn fullpath [& stops]
(doall (map (fn [a b] (journey a b)) stops (rest stops) )))
Above is the recursive function that at the moment takes in a set of stops and then rights out the route using journey. My idea is that instead of stops I pass in the robot to full path and robot will contain parcels and stops.
;;passed into fullpath to plan journey of robot
(def robot [parcels ;;needs to contain a set of parcels
stops]) ;;stops are all of the end's gathered from parcel
The parcels will come from another structure.
;;passed into robot
(def parcel [start
end
delivered])
Is this a viable way of doing it or will it be impossible?
Any help greatly appreciated.
I'm creating a program in Prolog using a HTTP server to make requests...
I'm want to encapsulate the code in a way I can reuse it and have the http stuff in one module, my "controller" to handle requests in another module, etc.
I started having problems with the http dispatch handler registration:
:- http_handler('/test', foobar, []).
Is it possible to have something like this:
register_handler(path, callback) :-
http_handler(path, callback, []).
I tried using that but I got a error must likely due to the "callback" parameter. Also, the callback predicate is defined in a different module so I used:
:-consult(api_controller).
[EDIT]
server.pl
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_parameters)).
:- use_module(library(http/http_json)).
:- use_module(api_controller).
:- http_handler('/test', foo, []).
server(Port):-http_server(http_dispatch, [port(Port)]).
api_controller.pl
foo(_request) :-
format('Content-type: text/plain~n~n'),
format('Hello world!~n').
Error:
http_dispatch:call_action/2: Undefined procedure: foo/1
http_handler/3 is a directive, and you can place such directives in other files and then use include/1 to load them.
In addition, you can have total control over the HTTP dispatch by installing a generic handler as follows:
:- http_handler(/, handle_request, [prefix]).
Note the prefix option.
Then, you supply a suitable handle_request/1, for example like this:
handle_request(Request) :-
debug(my_dispatch, "~q\n", [Request]),
memberchk(path(Path0), Request),
atom_concat(., Path0, Path1),
http_safe_file(Path1, []),
absolute_file_name(Path1, Path),
( reply_file(Path0, File) -> http_reply_file(File, [unsafe(true)], Request)
; redirect(Path0, Other) -> http_redirect(moved, Other, Request)
; see_other(Path0, Other) -> http_redirect(see_other, Other, Request)
; hidden_file(Path0) -> http_404([], Request)
; exists_file(Path) -> http_reply_file(Path, [unsafe(true)], Request)
; ...
).
In this example, the following predicates are meant to be supplied by you to tailor the server to your exact use cases:
reply_file(Path, File): Send contents File in response to request Path.
redirect(Path0, Path): Redirect to Path in response to Path0.
see_other/2: Meaning left as an exercise.
hidden_file/1: Meaning left as an exercise.
These rules can be defined elsewhere, and you can include these files with the directive:
:- include(other_source).
A related directive you should check out is multifile/1.
I leave figuring out the precise libraries you need for the above to work as an exercise. A starting point:
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_server_files)).
:- use_module(library(http/http_files)).
:- use_module(library(http/http_header)).
I am using jet for asynchronous ring adapter.
Jet also comes with async http-client which returns a channel whose value's :body is also a channel.
Also, async server route handler can return a map whose :body key can contain a channel. When this channel would be closed, the response would be returned to the client.
I am writing following go code :
(defn- api-call-1 []
(go (-> (jet-client/get "api-url-1")
<!
:body ;; jet http client :body is also a channel.
<!
api-call-1-response-parse)))
(defn- api-call-2 []
(go (-> (jet-client/get "api-url-2")
<!
:body
<!
api-call-2-response-parse)))
(defn route-function []
(let [response-chan (chan)]
(go
(let [api-call-1-chan (api-call-1) ;; using channel returned by go
api-call-2-chan (api-call-2)]
(-> {:api-1 (<! api-call-1-chan)
:api-2 (<! api-call-2-chan)}
encode-response
(>! response-chan)))
(close! response-chan))
;; for not blocking server thread, return channel in body
{:body response-chan :status 200}))
In my route-function, i can not block.
Though this code works fine, Is using go in api-call-1 is bad ?
I found that to use <! in api-call-1 i need to put it in a go block.
Now i use this go block's channel in route-function. Does this look unidomatic ? I am concerned about not exposing api-call-1-response-parse or even :body as channel to the route-function.
What is the right way to structure go block code and functions ?
Should i care about extra go blocks in functions api-call-1/2 ?
What you have looks much like the equivalent code I have in production. This is quite idiomatic, so I think your code is structured correctly.
The fact that core.async parking opperations can't cross function boundaries stems from the fact that it's written as a macro and needs to process the whole chunk of code at once (or at least while it's lexically available). This tends to make all core.async code come out in the pattern you are using.
I am trying to re-use a class and run it in a job to prove something out. Here is the job code:
InventQuarantineOrder_Scrap scrap = new InventQuarantineOrder_Scrap();
;
scrap.parmInventQuarantineId('00016749_077');
scrap.parmScrapQty(360);
scrap.parmTransDate(Today());
scrap.run();
When I run this code, I get the error:
The cursor is invalid for instantiating recordViewCache
Researching this error led to me this link, which I tried to implement but I got syntax errors I'm not sure how to fix. I copied the class and created a new runOnServer method. But then a validate method doesn't work. So I modify the validate method to run on the server:
static server boolean validate()
{
InventQuarantineOrder inventQuarantineOrder = InventQuarantineOrder::find(inventQuarantineId);
;
....
}
Which gave me this error:
Variable inventQuarantineId has not been declared.
If I comment out the validate() call from the runOnServer method, I get the same error/problem with the inventQuarentineId variable not being declared (it's also used in the run method).
From here, I am not sure how to continue. What am I doing wrong? Is it possible to use these methods inside a server method? Another thing worth noting I think is that I think the job code actually worked, but it did throw 3 lines those "cursor is invalid for instantiating recordViewCache." info alerts.
As you already found out, a RecordViewCache can only be used on the server tier. By starting your process in the job on the client tier, the method that creates the RecordViewCache (method viewCacheInventTransId of table InventTrans) is also executed on the client tier, which causes the error. If you put a breakpoint in this method, the call stack in the debugger shows you this:
Tier Method Line
[c] \Data Dictionary\Tables\InventTrans\Methods\viewCacheInventTransId 9
[c] \Classes\InventMovement\viewCacheInventTransId 7
[s] \Classes\InventUpd_Financial\initUpdate 14
[s] \Classes\InventUpd_Financial\newVirtuelQuarantineLoss 19
[c] \Classes\InventQuarantineOrder_Scrap\run 76
[c] \Jobs\Job4
The solution in the link you gave is for your case a bit more complicated than it needs to be (my comment was my first idea to fix this solution). You just need to create a class with a static server method that executes your job code. You can then call this static server method in your code. Now the debugger will show you the following call stack:
Tier Method Line
[s] \Data Dictionary\Tables\InventTrans\Methods\viewCacheInventTransId 9
[s] \Classes\InventMovement\viewCacheInventTransId 7
[s] \Classes\InventUpd_Financial\initUpdate 14
[s] \Classes\InventUpd_Financial\newInventQuarantineOrder 21
[s] \Data Dictionary\Tables\InventQuarantineOrder\Methods\startFinancial 12
[s] \Classes\InventQuarantineOrder_Scrap\run 54
[s] \Classes\Class1\jobOnServer 10
[c] \Jobs\Job4 5
I am writing a web app that would require the hunchentoot web server. I have almost no working knowledge of hunchentoot, or any web server for that matter, and I am wondering how my app written in Common Lisp would serve pages to a web client. I have seen some excellent examples (e.g. Hunchentoot Primer, Lisp for the Web) esp. the one listed on the Hunchentoot page. Do you know where I can find more of such examples?
Thanks.
I am wondering how my app written in Common Lisp would serve pages to a web client.
Hunchentoot serves all things that are in its *dispatch-table*, which is just a list of dispatch handlers.
The simplest thing to do is to serve a static file. One typical example would be a CSS file:
(push (create-static-file-dispatcher-and-handler "/example.css"
"example.css")
*dispatch-table*)
For a web application, you would most likely want to dynamically create a web page. You do this by defining a function that returns the page as a string (e.g. with CL-WHO), then creating a handler for this function:
(defun foo ()
(with-html-output-to-string ; ...
))
(push (create-prefix-dispatcher "/foo.html" 'foo)
*dispatch-table*)
You can eliminate a lot of boilerplate through macros, by the way:
(defmacro standard-page ((title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html :xmlns "http://www.w3.org/1999/xhtml"
:xml\:lang "de"
:lang "de"
(:head
(:meta :http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css"
:rel "stylesheet"
:href "/example.css"))
(:body
,#body))))
(defmacro defpage (name (title) &body body)
`(progn
(defmethod ,name ()
(standard-page (,title)
,#body))
(push (create-prefix-dispatcher ,(format nil "/~(~a~).html" name) ',name)
*dispatch-table*)))
The examples you have found should be sufficient to get you started, and if you run into problems, read the manual, then ask concrete questions.
define-easy-handler registers the handler you are defining automatically in a global variable which gets checked when a HTTP request arrives (the variable is called *easy-handler-alist*). So it's being taken care of automatically. Do you want to use a handler of a different form than the one defined in the tutorial?
I think there is an example using Hunchentoot in the Elephant distribution (Elephant being a Persistent Object Database for Common Lisp.)