If WebGUI is a body then the Session object is WebGUI's nervous system: it sends signals throughout WebGUI. The session object is passed into all newly instantiated WebGUI objects, and many non-object-oriented subroutines as well. It can then be used by the object to access the database, interact with the user's request, find out which user is logged in, and more. In this chapter explores how all of the components of WebGUI::Session come together and how they can be used.
The most common mistake in dealing with the session object is that developers think it is the user's session. In WebGUI, the session object is a page request session, of which the user is a part. The session is all the subsystems needed to service a page request. It is a connection to a database, an interface to the HTTP protocol, a relationship to the currently logged in user, and more. When dealing with the session object, understand that the user is only a part of it. Really, it exists to service the request.
Managing a WebGUI session is relatively easy, and once you have a session you can use all of its resources. To start with, you need to open a WebGUI session:
my $webguiRoot = “/data/WebGUI”;
my $configFile = “www.example.com.conf”;
my $sessionId = “aaaaaaaaaaaaaaaaaaaaaa”;
my $session = WebGUI::Session->open($webguiRoot, $configFile, undef, undef, $sessionId);
To create a session, you need to know where WebGUI is installed, and that's the path in the variable called $webguiRoot. You also need a config file name, which is in the $configFile variable in this example. Once WebGUI has this, it will look in $webguiRoot/etc for a file called $configFile. It will read in the contents of that file using WebGUI::Config. The config file tells WebGUI how to act, and how to connect to external resources like a database.
If you pass in a session id, then WebGUI will check the database to see if that session id is already in use. If it is it will attach you to that existing session. Otherwise it will automatically create a new session for you. If you don't pass in a session id, then WebGUI will check with the $session->http object to see if there is a session cookie from which it can read the session id.
Once you have a session you can make use of all the objects contained in a session, which are described in the following sections of this chapter. If you need a bunch of those objects and don't want to reference them by traversing the object tree (which can get quite verbose), then you can use the “quick” method to retrieve them, like this:
my ($db, $config, $http) = $session->quick(qw(db config http));
If you need to know the sessionId for any reason you can get it by calling:
my $id = $session->getId;
Once you're done with your request, you need to clean up after yourself by calling the following:
$session->close;
This will shut down the database connection, and clean up all the other session attached objects.
This is a reference to the current asset, if any. The current asset is the one that was requested by the user through the URL. Or, if a non-container asset was just created, then the current asset will be the newly created asset's container. See the WebGUI::Asset API for details.
my $id = $session->asset->getId;
This is a reference to a WebGUI::Config object for this site. See the WebGUI::Config API for details. Config files are stored in /data/WebGUI/etc.
my @assets = @{ $session->config->get(“assets”) };
This object provides methods for manipulating WebGUI's Data/Time format epoch (the number of seconds since January 1, 1970). As WebGUI 7.x development proceeds, this will become deprecated in favor of the WebGUI::DateTime object, which uses real dates (“2007-12-31 14:32:11”) instead of epochs. However, for at least the rest of 7.x development, this object will remain as is. For details on the methods available in this object see WebGUI::Session::DateTime.
my $epoch = $session->datetime->addToDate( $epoch, $years, $months, $days );
This is a reference to a WebGUI::SQL object. It is created by reading the “dsn”, “dbuser”, and “dbpass” directives from the $session->config object. Using this object, rather than recreating your connection to the WebGUI database when you need to query the database, performs better.
my @usernames = $session->db->buildArray(“select username from users”);
This is a reference to a WebGUI::SQL object. If “dbslave1”, “dbslave2”, and/or “dbslave3” are specified in the WebGUI config file, then one of them will be randomly instantiated upon call of this method. In this way the load is distributed across all available slaves. However, you can still safely call this method even if there is no slave, because it defaults to a reference to $session->db.
my @usernames = $session->dbSlave->buildArray(“select username from users”);
While you can always use Perl's %ENV to get at system environment variables, this is a reference to WebGUI::Session::Env, which is just a wrapper for %ENV. WebGUI uses this wrapper because it does some special magic handling of some elements in %ENV depending upon the environment it's in. That way it doesn't have to modify the actual %ENV, which might cause problems. When working with WebGUI code you should never use %ENV. Instead, always use this object.
my $remoteAddress = $session->env->get(“REMOTE_ADDR”);
WebGUI currently combines logging and error handling into one object. This may change in the future. For the time being, this is the object you should use. It is a reference to WebGUI::Session::ErrorHandler. The logging aspects of this are run by Log::Log4Perl, and there is a config file called log.conf in /data/WebGUI/etc which sets up the logging rules. There are other methods in this object for setting up debug, doing stack traces, and finally, if you call a fatal() using it, stopping the page request dead in its tracks. Fatal should only ever be called when it would be dangerous to continue. Otherwise you should call error().
$session->errorHandler->error(“The user did something that they weren't supposed to.”);
This is a reference to the WebGUI::Session::Form object, which in turn plugs in to the WebGUI::Form::* modules for input validation. Using this object you can pull form GET and POST variables with or without validation. WebGUI supports multiple levels of validation. Here's how it works. The following is grabbing the data raw with no validation:
my $value = $session->form->param(“emailAddy”);
This does the same thing, only with basic text field validation (which is almost exactly the same as above):
my $value = $session->form->process(“emailAddy”);
This is grabbing the value using validation from the proper form control:
my $value = $session->form->process(“emailAddy”, “email”);
This is grabbing the value using validation and a default:
my $value = $session->form->process(“emailAddy”, “email”, “noreply@example.com");
And this is grabbing the value using full validation, and a fully formed object:
my $value = $session->form->process(“emailAddy”, “email”, undef, \%formDefinition);
The http object will only work if there was a valid request object passed into the WebGUI::Session->open() call. See $session->request for details on the request object. See the WebGUI::Session API for details on calling open with the request object. The http object is a reference to WebGUI::Session::Http and is the interface for getting and setting HTTP options such as cache headers, mime types, and cookies.
$session->http->setCookie(“myCookie”, $value);
The icon object is used to generate toolbar icons in a standard way. It takes into account internationalization, accessibility compliance, and other things. See WebGUI::Session::Icon for API details.
$toolbar .= $session->icon->cut;
WebGUI uses a GUID (Global Unique ID) system rather than integers for all of its object and database table keys. It does this to make it easier to move and synchronize data between WebGUI sites. A GUID is a 22 character code consisting of a-z, A-Z, 0-9, and the “-” and “_” characters. It is generated taking into account the site name, the time and date, and a random number. Any time you need a new ID for something you'd use this object (WebGUI::Session::Id) like this:
my $id = $session->id->generate;
WebGUI's output handler processes macros on the output, and also allows you to redirect output for things other than HTTP. For example, you may want to output to a file handle if you're exporting content to static files. It is a reference to a WebGUI::Session::Output object.
$session->output->print($html);
If you ever need to detect what operating system WebGUI is running on you can use the WebGUI::Session::Os object to do so. It's rarely needed as WebGUI's internal subsystems automatically handle the operating system differences for you.
my $osName = $session->get(“name”);
The privilege object provides standard pages and HTTP codes for all common privilege related messages you might need to show a user. For example, if the user is not in the Admins group, but tries to access something that is admin only, you might call the adminOnly privilege message. See the WebGUI::Session::Privilege API for details.
my $html = $session->privilege->adminOnly;
The request object is a reference to an Apache2::Request object. This is created by the WebGUI Apache mod_Perl handler and passed into the WebGUI::Session->open() method at the beginning of the request cycle. Normally, you shouldn't ever need to access this object. It is mainly available to low level subsystems that need to interact directly with the request, like $session->http.
my $ifModifiedSince = $session->request->headers_in->{'If-Modified-Since'};
The scratch variable subsystem allows you to attach arbitrary data to the session. It will persist as long as the session exists. See WebGUI::Session::Scratch for API details. The scratch system uses only scalar data, but you can serialize complex data structures into JSON or some other serialized format and store it in the scratch variable.
$session->scratch->set(“favorite color”, “black”);
The server object is a reference to the Apache2::ServerUtil->server object. It is automatically attached to the session by the WebGUI Apache mod_Perl handler. Under normal circumstances it is only used by low level subsystems and should never be needed by you.
my $configFileName = $session->server->dir_config(“WebguiConfig”);
The setting object is similar to the config object, except its properties are stored in a settings table in the database rather than in a config file. The disadvantage of this is that it's only able to store scalar config data, or serialized structures (no hierarchy). The advantage of this is that it can be quickly read on every request for settings that might change without a server restart. The config file, on other other hand, is read only at server startup and never again, so if you change something in the config it will require a server restart. For more information see the WebGUI::Session::Setting API.
my $value = $session->setting->get(“foo”);
The stow object, affectionately called “Stowage” by the WebGUI dev team, is similar to the scratch object except that instead of attaching arbitrary data to the session, it's attaching it to the request. Therefore, as soon as $session->close is called, it goes out of existence. However, because it's stored in memory, it can handle any object or complex reference type without serialization. Despite it working like a global variable, it's a bad idea to use it like that. Globals are always a bad idea. Instead, think of it as a caching mechanism. See WebGUI::Session::Stow for details.
my $value = $session->stow->get(“foo”);
The style object, which is a reference to WebGUI::Session::Style, is used to manipulate the style wrapper for a page. It can be used to apply javascripts and cascading style sheets to the appropriate places in the document, and to load and execute the template used to generate the style.
$session->style->setScript(“/path/to/my.js”, { type=>”javascript” });
The URL object provides a series of utilities for generating WebGUI compliant URL's. It is a reference to WebGUI::Session::Url. It can help you generate extra URL's, make URL's asset compliant, add GET parameters to the end of a URL string, and generate fully qualified site URL's, among other things.
my $newUrl = $session->url->append($url, “foo=bar”);
The user object is a reference to a WebGUI::User object for the user that is currently attached to this session. By default this would be the Visitor user, but other users will be automatically attached if WebGUI detects that they've logged in. You can manipulate this yourself by providing the method with either a user id or a WebGUI::User object:
$session->user( { userId => $id } );
$session->user( { user => $user } );
You can use the object as a normal WebGUI::User object:
my $username = $session->user->username;
The var object controls the persistence of the session data. It stores things like the session id, the user id of the user attached to the session, the time this session expires, the IP address last used to access this session, and more. In most circumstances you won't ever have to use this object as it's used by lower level subsystems. However, there are two instances where you will use it.
The first is when you want to determine if admin mode is on or not. Or, for that matter, if you want to toggle admin mode. To do that, the methods you would use are these:
if ( $session->var->isAdminOn ) {
$session->var->switchAdminOff;
}
else {
$session->var->switchAdminOn;
}
The second is when you want to explicitly destroy a session. This is different than $session->close, which just disconnects you from a session, but the session itself is still there waiting to be reattached to. You'd want to destroy a session when you're not going to use it again. For example, if you write a command line script the $session->open statement will automatically create a new session for you, but since you're not going to use it again you'll want to explicitly destroy it to clean up after yourself.
To do this, you'd:
$session->var->end;
Note that even after you end the session, you must still do a $session->close to destroy the objects and close open connections. This is because the var object is only about the persistence of the session, not the live-in memory objects.
The session object is a collection of smaller objects, which are covered in detail in the previous sections. In order to improve performance these objects are not instantiated until they are used. Therefore, the smaller number of these objects you make use of during your request, the better your performance will be. However, once the objects are instantiated, you can safely reuse them over and over again, because they remain cached.
Keywords: