In VisualWorks, the Web Toolkit makes it pretty easy to create
ASP/JSP style applications, complete with support for servlets. The
way you get a servlet invoked is the same whether you use Smalltalk
or anything else; you simply name the servlet appropriately at the
client side, in the web page.
Take this blog, for example - there's a login page for the site
bloggers to use if they want to post from the web form or use the
online admin tools - here's the snippet from the SSP (Smalltalk
Server Page):
<form action="servlet/LoginServlet" method="post" name="blogLoginForm">
Looks pretty normal, doesn't it? That's the point - you don't have to do anything special from the client side to support the web toolkit. You can even use JSP tags - I have no experience with that, but there are examples that ship with the product. How do things look on the server? This form is very basic - two fields, one for username, one for password. Here's the servlet definition:
Smalltalk.Blog defineClass: #LoginServlet
superclass: #{Blog.AbstractServlet}
indexedType: #none
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: 'Blog'
AbstractServlet is a simple subclass of SingleThreadModelServlet, with some code specific to the needs of the blog server. There are two servlet classes in VW - the one I just mentioned, and HttpServlet. What's the difference? HttpServlet passes the request and response as arguments into the API methods, while SingleThreadModelServlet passes them in as instance variables - i.e., it maintains them as state information. Which one is right depends on your usage.
The entry point for a post servlet is going to be #doPost: or #doPost:response: - the latter for the stateless model. Here's how that looks in the LoginServlet:
doPost
| model userOrNil |
model := BlogUser new.
model appkey: self appkey.
model getInputFrom: request parameters.
userOrNil := model validate.
userOrNil notNil
ifTrue: [self session initialize.
self session at: 'currentUser' put: userOrNil.
self determineDestinationFor: userOrNil]
ifFalse: [self redirectTo: (self handler linkNamed: 'blogLogin')]
Basically, I grab the input, ask it to validate (which checks the input against the valid users of this blog), and then determine where login should take them. In general, there are two types of users - people who can post, and people who can post and have admin rights. The method #determineDestinationFor: redirects valid users to the appropriate page, based on their access rights.
And that's pretty much it - the heart of this servlet is that one method, with the supporting code being simple lookup stuff. The bottom line - getting a Smalltalk servlet working is pretty easy - and, since it's Smalltalk, you can debug the code during test. In fact, when I was refining the MetaWebLog API servlet, I did just that - one of the bloggers on the site tested a client against my test server, and I had breakpoints in to see what I was being sent (and more importantly, what I was expected to send back). The fact that the servlet was just another Smalltalk object - rather than a file artifact that would have to be loaded, flushed, and reloaded repeatedly - made the whole things a lot easier to deal with.