Search posterous

Search all posts and users. Type a name, type a favorite song title, whatever! See what comes up.
  

More posterous blogs











More recommended blogs »

Here are posterous posts filed under helloworld...

rickscott says...

I created this space because I need to write more about the technical stuff I get up to, and because I need to write more, period. Some really amazing people whom I greatly respect have encouraged me to get going on this, especially when it comes to writing about testing.

There are a lot of different technical areas I'm interested in, and I'm not going to restrict topics here to just one. However, it seems to me that there's a ton of writing "out there" about programming, systems admin, even UI design, but a dearth of writing about testing. I'm the furthest thing from a Great Ghod of Testing, but I *can* share what I've done, what's worked and what hasn't, and people will find some value in that.

So, I had best get writing.

Filed under: hello world

Rabby says...

Hey... just testing out posterous.. I might... just might move here from Livejournal/Wordpress.. this is much easier.. I will still explore features here.. And possible update this everyday utilizing Microsoft Outlook.. fast simple easy!

Filed under: hello world

Tina says...

I'm still trying to understand the concept of Posterous. It seems like the exact opposite of a lifestream blog, because you only need to send an email to Posterous and all your other sites will be updated automatically. I'm not sure that I'm ready to do that... yet. We will see...

Filed under: hello world

kossa says...

Hello guys,

this is my first posterous. i learn to share my thought from twitter, then i need some bigger space then 140 characters.. sooo.. this is my posterous.

i will write about bike, programming, gadget, how to, my thought, joke maybe, my life, my friends, my family, and many other things. hope you enjoy your stay here at my posterous. maybe i'll be writing my new stuff soon.. i just got an idea. soon i will share that idea.

bubye..

Filed under: hello world

acidlogik says...

Ignore this, just testing

Filed under: Hello World!

felideon says...

Today's post will kick off a series of posts introducing UnCommon Web (UCW). It'll pretty much be my own Cliff Notes version of getting-started.txt, where I'll explore and write about topics I've found interesting or somewhat confusing.

In this post, I'll discuss two aspects of CLOS I found interesting (read as "I did not understand"), as well as describing UCW's RERL protocol by creating a hello world application.

CLOS newbie

Not being too familiar with CLOS, I had to look into a few things after reading the getting started doc, including skimming through the two chapters on CLOS ("Object Reorientation") in PCL. I also found a nice, brief guide to CLOS if you really want a quick refresher.

If you're an experienced Lisper, you may want to skip ahead to the section on Uncommon Web's RERL.

Mixins
One thing I see a lot in the code snippets class definitions that seem to inherit some sort of superclass with the -mixin naming convention. I really had no idea what this was or what it meant. Not being entirely convinced with Wikipedia's definition, I asked around in the #lisp channel:

"What are mixins?"
They're regular super-classes, but instead of being used to define a class hierarchy, you use them as a means of adding features to your class. -tic

Mixins [are] an abstract concept involving the way multiple classes can be inherited from. There's no such thing as a "mixin" in Lisp: only classes and multiple inheritance. -sykopomp

"When should I call something a mixin?"
Usually, 'mixins' are just classes that you only wrote with the intent of adding behavior. In general, you don't use mixins directly, you inherit from them. -sykopomp

Mixin-ness is an information intent. When the class is not meant to be [instantiated] (abstract), nor meant to be inherited from alone (not just a regular abstract base class). -pkhuong

Thank you, kind sirs.

Now let's look at an example. When we define a sample application class in UCW, such as:

(defclass example-application (standard-application 
cookie-session-application-mixin)
()
(:default-initargs
:url-prefix "/example/"))

We are inheriting from both standard-application and cookie-session-application-mixin classes. the intent here is that example-application directly specializes the standard-application superclass—establishing an is-a relationship—but it also needs the features provided by the cookie-session-application-mixin. (In contrast, probably establishing a has-a relationship, if one could say "Example application has a cookie session feature.")

What's up with the empty parens?
Something else that got my attention in the code is the use of empty parens in the body of defclasses. The only thing supplied is a default-initarg for :url-prefix. What is url-prefix?

With help from SLIME's M-. command, we can easily find that :url-prefix is a slot in the MINIMAL-APPLICATION class (defined in src/rerl/basic-classes.lisp) which is an indirect superclass of our example application as so:

STANDARD-APPLICATION -> BASIC-APPLICATION -> MINIMAL-APPLICATION -> APPLICATION

In this respect, here's how each subclass specializes its superclass:

MINIMAL-APPLICATION
Defines a slots called url-prefix which is a string specifying the start (prefix) of all the urls this app should handle. This value is used by the STANDARD-SERVER to decide what app a particular request is aimed at and for generating links to actions within the app.

Also defines the following slots: request-context-class, server, lock, and debug-on-error.

BASIC-APPLICATION
Additionally inherits a mixin called APPLICATION-WITH-SESSION-HANDLING-MIXIN, which as you might guess, adds session handling capabilities to applications.

Defines slots named charset and dispatchers. Kind of self-explanatory but see documentation strings in basic-classes.lisp for more info.

STANDARD-APPLICATION
Defines a slot named action-class. Actions and callbacks will be explored in a future post, but you can read about them in the getting started document.

Also notice the empty parens when defining the "hello.ucw" entry point:

(defentry-point "hello.ucw" (:application *example-application*
:with-call/cc nil)
()
(format (html-stream (context.response *context*))
"Hello World"))

Now, this one isn't as obvious since DEFENTRY-POINT is a macro. But without looking at the code, it seems like that list form is used when you need to supply parameters to an entry point, as seen in this example:

(defentry-point "hello2.ucw" (:application *example-application*
:with-call/cc nil)
((message "World"))
(format (html-stream (context.response *context*))
"Hello ~A" message))

If left empty, you are defining an entry-point that does not need URL arguments.

What is the RERL?

From the getting started doc:

UCW is based around the Request Eval Response Loop (RERL). The RERL is an extensible CLOS protocol that takes care of the details, while still allowing the programmer to hook in at any point. Because of this extensibility, UCW is suitable for all types of web applications. The more advanced features of Uncommon Web are especially suited for highly stateful applications with a complex control flow. The developer is free to use an much or as little of the RERL as desired for any given request. One can freely intermix a REST-style with a heavily stateful CPS approach where appropriate.

(Emphasis mine, keep reading.)

There is also another concise definition from the documentation in src/rerl/protocol.lisp:

A UCW server sits in a tight loop waiting for incoming HTTP requests, elaborating them and then sending out the HTTP responses. This loop is called the "RERL" (Request-Eval-Response Loop) and the objects, methods and variables involved in the RERL are described here.

In the documentation we can see that objects and methods for:

  • Backends
  • Servers
  • Applications
  • Rendering
  • Components
  • Request contexts
  • Sessions
  • Session Frames

Are defined as being part of the RERL.

This sheds some light on the phrase I emphasized above. For example, you don't have to use components or session frames when building web apps with UCW. You can even use components without sessions if you wanted to. (Thanks unknown_lamer.) In other words, the RERL gives you tools to build a web application in the style you need—anywhere from basic parameter passing through forms to continuation-passing style control flow.

Backends, servers, and applications

One thing to clarify is that the backend is the web server responsible for handling HTTP requests, whereas the server object (we'll call it the UCW server) is the abstracted "logical server". The UCW server's main responsibilities are to take request and response objects provided by the backend and run one iteration of the RERL, and to determine the application which should handle the request. (See more functionality provided by the SERVER class in protocol source code.)

Note that you can use UCW on top of any backend, e.g. mod_lisp, but UCW has a decent internal HTTPD. This is another reason a logical server object comes in handy, as it even allows UCW to deal with multiple backends. (I'll try to write about this in a future blog post.)

As far applications go, their main responsibility in UCW is to serve as containers for DISPATCHERS (e.g. ENTRY-POINTS), and as a place to store SESSION objects.

Hello, world!

Alright, it's time we write a simple hello world with UCW. We need to instantiate a backend server and application that will host our web application.

Instantiating a server and application with Uncommon Web
To start a server, we need to first make an instance of the STANDARD-SERVER class and pass it a BACKEND object. We can create a BACKEND object with the MAKE-BACKEND method and return it to the :backend slot of our STANDARD-SERVER instance.

After this object is created, we can use the STARTUP-SERVER method to start it.

(defvar *example-server* 
(make-instance 'standard-server
:backend (make-backend :httpd :port 8080)))

(defun start-example-server ()
(startup-server *example-server*))

Once you've evaluated the code above, go ahead and call START-EXAMPLE-SERVER at the REPL. You should see some output log from UCW, and if you go to your browser and navigate to http://localhost:8080, you should get a 404 error. This means we have the server up and running. If not, you would have gotten an error message from your browser stating something to the effect of not finding the server or not being able to establish a connection.

The next step is to create an application. In order to create an application, you can define a new subclass that inherits from STANDARD-APPLICATION and any mixins you want to add, as well as specifying a default URL-PREFIX to match requests with. Once you instantiate the application you need to register it with the server created above.

(defclass example-application (standard-application 
cookie-session-application-mixin)
()
(:default-initargs
:url-prefix "/example/"))

(defvar *example-application* (make-instance 'example-application))

(register-application *example-server* *example-application*)

If we try to browse to our site, we will still get a 404 error even if we try http://localhost:8080/example/. UnCommon Web matches the request against its default dispatchers, i.e. ACTION-DISPATCHER, but we have not defined any handlers. We thus enter the EVAL stage of the RERL.

Creating your first entry point
I think the sections on entry-points in the getting started doc are pretty straightforward. But to summarize, entry points are pretty much external URLs that are "bookmarkable, REST-style linkable resources exposed directly to the web." You can also think of an entry point as a page.

(defentry-point "hello.ucw" (:application *example-application*
:with-call/cc nil)
()
(format (html-stream (context.response *context*))
"hello, uncommon world"))

Please refer to getting-started.txt for more information on what this code is doing.

Go ahead and evaluate DEFENTRY-POINT above to create the hello.ucw entry point and browse to http://localhost:8080/example/hello.ucw. A page is finally served, completing UCW's RESPONSE stage.

Additionally, entry points can handle query strings. Suppose we wanted to change our greeting by passing in a string in the URL.

(defentry-point "hello.ucw" (:application *example-application*
:with-call/cc nil)
((message "world"))
(format (html-stream (context.response *context*))
"hello, uncommon ~A" message))

Here we specify an argument message with a default value of "world". If we go back to our "page" and specify a query string, such as in http://localhost:8080/example/hello.ucw?message=universe, "hello, uncommon universe" will be displayed. Otherwise, the default one will be displayed.

Next Time: UCW Components

For my next post, I plan on writing about Uncommon Web's components. I'll probably skip this section on creating an HTML form with YACLML, so you should read that in getting-started.txt on your own if you are interested. (It's pretty straightforward.)

Hopefully I'll get some time to starting writing it sooner and for longer periods of time. My initial goal is to have at least two posts per month. I'll be posting updates, so you should follow me on twitter here if you are interested.

Filed under: hello world

Robin says...

let's give this a go!

---
Life happens at the level of events, not of words

Filed under: hello world

Angel says...

Hey world! Im just trying to test this posterous account see how well it works.

Filed under: Hello World

mullany says...

howdy folks! - I'm gonna just jump in here, I've never held a blog, yeah, sure, I've signed up for loads of stuff over the years, but quite frankly, I've always lacked the commitment to keeping a blog up-to-date - there is always another webapp to visit, or another app to use.

 But, when I was at FOWD this week, I noticed a lot of folk using this service - and, after asking around, I soon discovered that the main reason folks love this place is the posting method, email. It's so easy, yet quite brilliant.

 So, here I am, and I'm gonna give this a go, and see where it goes. I'm just hoping that I can stick with this, I have a lot of thoughts to share, and I'm in need of an outlet!

Filed under: Hello World

Arkion says...

Jetzt ernsthaft und Spaß beiseite: Die wohl unsinnigsten Beiträge im Internet sind solcherlei Einleitungsbeiträge, wie auch dieses einer ist. Trotzdem kann man irgendwie nicht darauf verzichten. Ein simples "Test" über Twitter oder ein typisches "Hello World" im neuen Blog. Das muss sein, obwohl der inhaltliche Gehalt ungefähr so wertvoll ist, wie abgelaufene Frühstückscerealien.

Ich könnte also jetzt also etwas über das "warum hier" oder das "worüber und was" schreiben, ich kann es aber auch einfach sein lassen.

Filed under: Hello World