pl-web, almost a web development framework
OK so I've got a first draft of something simple. As opposed to what has been requested before this is NOT a web development framework in the sense of RoR or even Ring. Instead I've opted to create a simple environment from which frameworks utilizing conventions and such can be built, both a RoR type of thing or a simpler Ring style framework is possible to create from pl-web. What we have is a few basic things: 1.) An ability to inspect the current look of the URL (se line 87 and 120 in pl-web.l). 2.) File based sessions (ugly yes but will not make demands on how any database should look like). See line 109 in pl-web.l. 3.) Trying as hard as we can to utilize Linux system functions/commands in order to alleviate the need for libraries (see cmd.l). How to test: 1.) Unpack the attached file into /opt/picolisp and create /tmp/pl-web/sessions/. 2.) Create a folder called simple-web-app in /opt/picolisp/projects and paste the following into a main.l file there: (load pl-web/pl-web.l pl-web/pl-html.l) (de login (Msg) (plw-form NIL (span NIL Username:) (plw-field text username (gReq username)) (br) (span NIL Password:) (plw-field password password ) (br) (submit Submit) (br) (span NIL Msg) ) ) (de app () (fatApp (html 0 PL Web *Css NIL (div NIL (println Post: *Post Cookies: *Cookies)) (cond ((= (car *Urll) login) (ifn (and (= (gReq password) test) (= (gReq username) test)) (login (if (gReq username) User not found. Please login. ) ) (sSess 'logged-in-user test) (div NIL Login successful.) ) ) ((= (car *Urll) whoami) (div NIL (prin You are: (gSess 'logged-in-user))) ) (T (Nothing to do.)) ) ) ) ) (de start () (off *JS)) (de go () (server 8080 !start) ) 3.) Start it: henrik@henrik-laptop:/opt/picolisp$ ./pil projects/simple-web-app/main.l -go 4.) Browse to: http://localhost:8080/login and submit the form with test in both fields. 5.) Browse to: http://localhost:8080/whoami That's it, I think inspection of the code plus testing in #4 and #5 above should be enough to understand how this works. A few TODO/Thoughts: 1.) Swiping stale sessions in the sessions folder. Some kind of timeout value might be needed, if combined with a random initializer we have recreated the ugliness of PHP session handling to perfection. 2.) Port of the current xhtml.l library (which we are currently relying heavily on), as can be seen I've started a little in the pl-html.l file, all that *JS stuff etc needs to go. 3.) Some brave soul needs to create a real, clever, framework from this that is beautiful enough that it might get some attention. What was that earlier suggestion, Bumblebee? Don't know about the name though as it brings to mind something that looks so heavy it should not be able to fly, yet does. Perhaps not something we want associated with PicoLisp. 4.) If it would be possible for PL to have several databases open at the same time (I have a vague memory of discussing this at some point in the past) stuff like session handling could done through a DB instead and without making demands on the main application E/R. Comments? /Henrik Sarvell pl-web.tar.bz2 Description: BZip2 compressed data
ersatz - can not access a member
I'm trying to write a simple java web server using the simpleframework. I'm close, but I process anything in the method handler: (de handler (request response) (java response 'close)) (setq cont (interface org.simpleframework.http.core.Container 'handle handler)) (setq con (java org.simpleframework.transport.connect.SocketConnection T cont)) (setq addr (java java.net.InetSocketAddress T 8005)) (java con 'connect addr) When I run this and then curl http://localhost:8005 I get the following exception: java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public I've tried every other method I can think of from this doc: http://www.simpleframework.org/doc/javadoc/index.html If I intentionally put a missing method in, it correctly reports it: (de handler (request response) (java response 'close2)) : !? (java response 'close2) java.lang.NoSuchMethodException: close2 If my handler is this, I get a response. (de handler (request response) (prinl response)) : HTTP/1.1 200 OK I need to be able access the request/response to process it. I am not sure if I need to use javac because of the interface but then I'm not sure how I'd add picolisp code to process the request/response. Thanks for any help
Re: ersatz - can not access a member
This is the java example I'm trying to duplicate: http://www.simpleframework.org/doc/tutorial/tutorial.php import org.simpleframework.http.core.Container; import org.simpleframework.transport.connect.Connection; import org.simpleframework.transport.connect.SocketConnection; import org.simpleframework.http.Response; import org.simpleframework.http.Request; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.io.PrintStream; public class HelloWorld implements Container { public void handle(Request request, Response response) { PrintStream body = response.getPrintStream(); long time = System.currentTimeMillis(); response.set(Content-Type, text/plain); response.set(Server, HelloWorld/1.0 (Simple 4.0)); response.setDate(Date, time); response.setDate(Last-Modified, time); body.println(Hello World); body.close(); } public static void main(String[] list) throws Exception { Container container = new HelloWorld(); Connection connection = new SocketConnection(container); SocketAddress address = new InetSocketAddress(8080); connection.connect(address); } } On Sat, Jan 28, 2012 at 6:33 AM, Joe Bogner joebog...@gmail.com wrote: I'm trying to write a simple java web server using the simpleframework. I'm close, but I process anything in the method handler: (de handler (request response) (java response 'close)) (setq cont (interface org.simpleframework.http.core.Container 'handle handler)) (setq con (java org.simpleframework.transport.connect.SocketConnection T cont)) (setq addr (java java.net.InetSocketAddress T 8005)) (java con 'connect addr) When I run this and then curl http://localhost:8005 I get the following exception: java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public I've tried every other method I can think of from this doc: http://www.simpleframework.org/doc/javadoc/index.html If I intentionally put a missing method in, it correctly reports it: (de handler (request response) (java response 'close2)) : !? (java response 'close2) java.lang.NoSuchMethodException: close2 If my handler is this, I get a response. (de handler (request response) (prinl response)) : HTTP/1.1 200 OK I need to be able access the request/response to process it. I am not sure if I need to use javac because of the interface but then I'm not sure how I'd add picolisp code to process the request/response. Thanks for any help -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
Hello Joe, I'm trying to write a simple java web server using the simpleframework. I'm close, but I process anything in the method handler: OK. I can't reproduce the problem, as I don't have access to that framework. But perhaps I can give some hints to help locate the problem. (de handler (request response) (java response 'close)) (setq cont (interface org.simpleframework.http.core.Container 'handle handler)) (setq con (java org.simpleframework.transport.connect.SocketConnection T cont)) (setq addr (java java.net.InetSocketAddress T 8005)) (java con 'connect addr) One note first: In PicoLisp, it is advisable to use uppercase names for (local) variables, because otherwise there is a risc for name conflicts. For example, the expression (setq con (java org.simpleframework... changes the value of the symbol 'con', which happens to be a function (setting the CDR of a cell). Later calls to that function will crash. This risk also exists for function parameters, so I would write the above as: (de handler (Request Response) (java Response 'close) ) (setq Cont (interface org.simpleframework.http.core.Container 'handle handler) ) (setq Con (java org.simpleframework.transport.connect.SocketConnection T Cont) ) (setq Addr (java java.net.InetSocketAddress T 8005)) (java Con 'connect Addr) But this is probably not the problem here. When I run this and then curl http://localhost:8005 I get the following exception: java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public It would be interesting to see _where_ things get wrong. Could you try to trace the execution? Please call (trace 'java) (trace 'interface) before starting execution. And possibly trace other functions too, e.g. (trace 'handler), or (traceAll) to trace all Lisp-level functions. There must be a situation where perhaps the argument type (number?) doesn't match. Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
Hi Alex, Thanks for the response! Here's the output from trace. It's neat to see, but I don't know enough to interpret it: java -DPID=42 -cp .;picolisp.jar;simple-4.1.21.jar PicoLisp lib.l go.l + interface : org.simpleframework.http.core.Container handle ((Request Response) (java Response 'close)) interface = $$Proxy0 java : org.simpleframework.transport.connect.SocketConnection T $$Proxy0 java = $SocketConnection java : java.net.InetSocketAddress T 8005 java = $InetSocketAddress java : $SocketConnection connect $InetSocketAddress java = $InetSocketAddress : java : $ResponseEntity close !? (5 $4354460 $3195425) java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public ? Another question: I started down an alternate path to use java.net.ServerSocket but it doesn't seem to like threads/thread pool calls. Here's a really simple example: : (setq Thread (java java.lang.Thread T (interface java.lang.Runnable 'run '(() (prinl hi)) - $Thread (java Thread start) : - NIL : Exception in thread Thread-1 java.lang.NullPointerException at PicoLisp$Number$1.invoke(Unknown Source) at $Proxy0.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Any clues on this one either? Thank you! Joe On Sat, Jan 28, 2012 at 7:18 AM, Alexander Burger a...@software-lab.de wrote: Hello Joe, I'm trying to write a simple java web server using the simpleframework. I'm close, but I process anything in the method handler: OK. I can't reproduce the problem, as I don't have access to that framework. But perhaps I can give some hints to help locate the problem. (de handler (request response) (java response 'close)) (setq cont (interface org.simpleframework.http.core.Container 'handle handler)) (setq con (java org.simpleframework.transport.connect.SocketConnection T cont)) (setq addr (java java.net.InetSocketAddress T 8005)) (java con 'connect addr) One note first: In PicoLisp, it is advisable to use uppercase names for (local) variables, because otherwise there is a risc for name conflicts. For example, the expression (setq con (java org.simpleframework... changes the value of the symbol 'con', which happens to be a function (setting the CDR of a cell). Later calls to that function will crash. This risk also exists for function parameters, so I would write the above as: (de handler (Request Response) (java Response 'close) ) (setq Cont (interface org.simpleframework.http.core.Container 'handle handler) ) (setq Con (java org.simpleframework.transport.connect.SocketConnection T Cont) ) (setq Addr (java java.net.InetSocketAddress T 8005)) (java Con 'connect Addr) But this is probably not the problem here. When I run this and then curl http://localhost:8005 I get the following exception: java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public It would be interesting to see _where_ things get wrong. Could you try to trace the execution? Please call (trace 'java) (trace 'interface) before starting execution. And possibly trace other functions too, e.g. (trace 'handler), or (traceAll) to trace all Lisp-level functions. There must be a situation where perhaps the argument type (number?) doesn't match. Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
Hi Joe, Another question: I started down an alternate path to use java.net.ServerSocket but it doesn't seem to like threads/thread pool calls. Here's a really simple example: : (setq Thread (java java.lang.Thread T (interface java.lang.Runnable 'run '(() (prinl hi)) - $Thread (java Thread start) : - NIL : Exception in thread Thread-1 java.lang.NullPointerException HA! You found a bug in 'interface' :) It seems that 'interface' could not handle correctly functions with empty parameter lists, like the above '(() ..). This resulted in the NullPointer exception. I fixed ersatz/fun.src: 239a240,242 if (arg == null) return w.apply(null, false, null, 0); else { 244a248 } (also uploaded a fixed version). With that: abu:~/pico ersatz/pil + : (setq Thread (java java.lang.Thread T (interface java.lang.Runnable 'run '(() (prinl hi))) ) ) (java Thread start) - $Thread : - NIL : hi BUT! While this simple example works, I'll have to warn stronly to use Java threads in real code. The problem is the same as with the other versions of PicoLisp: Threads cannot be handled cleanly, due to symbol binding conflicts. You'll open a pandora box, because each thread will overwrite the other thread's bindings. Unfortunately, Java doesn't come with a fork() system call ... Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
Hi Joe, Thanks for the response! Here's the output from trace. It's neat to see, but I don't know enough to interpret it: OK, this looks helpful (a little ;) If I intermix the previous code with the trace output in the editor (not just in mind as usual), I get: (de handler (Request Response) (java Response 'close) ) (setq Cont (interface org.simpleframework.http.core.Container 'handle handler) ) interface : org.simpleframework.http.core.Container handle ((Request Response) (java Response 'close)) interface = $$Proxy0 'interface' is called with the strng org.., the symbol 'handle', and the list ((Request Response) (java Response 'close)). FYI: The output of 'trace' shows a line with ':' when a function/method is entered, and a line with '=' after the function returned. So we see that 'interface' here returns an object '$$Proxy0'. (setq Con (java org.simpleframework.transport.connect.SocketConnection T Cont) ) java : org.simpleframework.transport.connect.SocketConnection T $$Proxy0 java = $SocketConnection 'Con' is set to an object '$SocketConnection' (setq Addr (java java.net.InetSocketAddress T 8005)) java : java.net.InetSocketAddress T 8005 java = $InetSocketAddress and 'Addr' to an '$InetSocketAddress' (java Con 'connect Addr) java : $SocketConnection connect $InetSocketAddress java = $InetSocketAddress Looks all right so far. Now: : java : $ResponseEntity close !? (5 $4354460 $3195425) java.lang.IllegalAccessException: Class PicoLisp$Number can not access a member of class org.simpleframework.http.core.ResponseEntity with modifiers public This must have happened in the body of 'handler'. We don't have a clear trace of what happened in between. But we see that 'java' is called with and object '$ResponseEntity' (i.e. 'Response' is bound to that object) and the symbol 'close' (java Response 'close) Hmm, I don't know. Is the handler, and the way it is installed, correct? Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz web server example benchmarks
Hi Joe, I created a very simple proof of concept web server using ersatz and wrote up a bit of the experience and benchmarks here: http://picolisp.com/5000/!wiki?ExampleErsatzWebServer Cool! Perhaps you might also plant a link to it in the Examples page? Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: pl-web, almost a web development framework
Ops, the httpHead redifinition part in pl-web.l can be removed, I think I thought I would need to make changes there but I did not. On Sat, Jan 28, 2012 at 4:25 PM, Henrik Sarvell hsarv...@gmail.com wrote: OK so I've got a first draft of something simple. As opposed to what has been requested before this is NOT a web development framework in the sense of RoR or even Ring. Instead I've opted to create a simple environment from which frameworks utilizing conventions and such can be built, both a RoR type of thing or a simpler Ring style framework is possible to create from pl-web. What we have is a few basic things: 1.) An ability to inspect the current look of the URL (se line 87 and 120 in pl-web.l). 2.) File based sessions (ugly yes but will not make demands on how any database should look like). See line 109 in pl-web.l. 3.) Trying as hard as we can to utilize Linux system functions/commands in order to alleviate the need for libraries (see cmd.l). How to test: 1.) Unpack the attached file into /opt/picolisp and create /tmp/pl-web/sessions/. 2.) Create a folder called simple-web-app in /opt/picolisp/projects and paste the following into a main.l file there: (load pl-web/pl-web.l pl-web/pl-html.l) (de login (Msg) (plw-form NIL (span NIL Username:) (plw-field text username (gReq username)) (br) (span NIL Password:) (plw-field password password ) (br) (submit Submit) (br) (span NIL Msg) ) ) (de app () (fatApp (html 0 PL Web *Css NIL (div NIL (println Post: *Post Cookies: *Cookies)) (cond ((= (car *Urll) login) (ifn (and (= (gReq password) test) (= (gReq username) test)) (login (if (gReq username) User not found. Please login. ) ) (sSess 'logged-in-user test) (div NIL Login successful.) ) ) ((= (car *Urll) whoami) (div NIL (prin You are: (gSess 'logged-in-user))) ) (T (Nothing to do.)) ) ) ) ) (de start () (off *JS)) (de go () (server 8080 !start) ) 3.) Start it: henrik@henrik-laptop:/opt/picolisp$ ./pil projects/simple-web-app/main.l -go 4.) Browse to: http://localhost:8080/login and submit the form with test in both fields. 5.) Browse to: http://localhost:8080/whoami That's it, I think inspection of the code plus testing in #4 and #5 above should be enough to understand how this works. A few TODO/Thoughts: 1.) Swiping stale sessions in the sessions folder. Some kind of timeout value might be needed, if combined with a random initializer we have recreated the ugliness of PHP session handling to perfection. 2.) Port of the current xhtml.l library (which we are currently relying heavily on), as can be seen I've started a little in the pl-html.l file, all that *JS stuff etc needs to go. 3.) Some brave soul needs to create a real, clever, framework from this that is beautiful enough that it might get some attention. What was that earlier suggestion, Bumblebee? Don't know about the name though as it brings to mind something that looks so heavy it should not be able to fly, yet does. Perhaps not something we want associated with PicoLisp. 4.) If it would be possible for PL to have several databases open at the same time (I have a vague memory of discussing this at some point in the past) stuff like session handling could done through a DB instead and without making demands on the main application E/R. Comments? /Henrik Sarvell -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
Thanks! Regarding threading, I stepped away for a few and the thought crossed my mind as well. I came back tried the main thread do this: (loop (setq Method nope)) And I can see that Method gets overwritten in child threads. Neither bind nor job helps either. Is there any way around this? I supposed I could stick all my symbols in java thread local storage and always refer to symbols by (java ... ) instead of directly calling them. I may try that... Otherwise I'll have to make it single threaded which basically kills the idea of it because of slow pages. If not, it was a fun experiment nonetheless. On Sat, Jan 28, 2012 at 11:59 AM, Alexander Burger a...@software-lab.de wrote: Hi Joe, Another question: I started down an alternate path to use java.net.ServerSocket but it doesn't seem to like threads/thread pool calls. Here's a really simple example: : (setq Thread (java java.lang.Thread T (interface java.lang.Runnable 'run '(() (prinl hi)) - $Thread (java Thread start) : - NIL : Exception in thread Thread-1 java.lang.NullPointerException HA! You found a bug in 'interface' :) It seems that 'interface' could not handle correctly functions with empty parameter lists, like the above '(() ..). This resulted in the NullPointer exception. I fixed ersatz/fun.src: 239a240,242 if (arg == null) return w.apply(null, false, null, 0); else { 244a248 } (also uploaded a fixed version). With that: abu:~/pico ersatz/pil + : (setq Thread (java java.lang.Thread T (interface java.lang.Runnable 'run '(() (prinl hi))) ) ) (java Thread start) - $Thread : - NIL : hi BUT! While this simple example works, I'll have to warn stronly to use Java threads in real code. The problem is the same as with the other versions of PicoLisp: Threads cannot be handled cleanly, due to symbol binding conflicts. You'll open a pandora box, because each thread will overwrite the other thread's bindings. Unfortunately, Java doesn't come with a fork() system call ... Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: ersatz - can not access a member
On January 28, 2012 at 1:18 PM Alexander Burger a...@software-lab.de wrote: Hello Joe, I'm trying to write a simple java web server using the simpleframework. I'm close, but I process anything in the method handler: And this excellent discussion is why we could say that we have official PicoLisp Q/A on Stackoverflow.com This was a perfect fit. I would even ask you Joe to ask the same thing on Stackoverflow.com again. ;-) best regards, Jakob -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: pl-web, almost a web development framework
On January 28, 2012 at 10:25 AM Henrik Sarvell hsarv...@gmail.com wrote: OK so I've got a first draft of something simple. As opposed to what has been requested before this is NOT a web development framework in the sense of RoR or even Ring. But a very nice start! :-D //Jakob -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe