pl-web, almost a web development framework

2012-01-28 Thread Henrik Sarvell
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

2012-01-28 Thread Joe Bogner
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

2012-01-28 Thread Joe Bogner
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

2012-01-28 Thread Alexander Burger
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

2012-01-28 Thread Joe Bogner
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

2012-01-28 Thread Alexander Burger
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

2012-01-28 Thread Alexander Burger
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

2012-01-28 Thread Alexander Burger
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

2012-01-28 Thread Henrik Sarvell
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

2012-01-28 Thread Joe Bogner
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

2012-01-28 Thread Jakob Eriksson


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

2012-01-28 Thread Jakob Eriksson


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