In this chapter and the one that follows, we’ll explore the Spring MVC web
framework. In this chapter, we’ll focus on the parts of Spring MVC that process
requests. You’ll see how to extend Spring’s rich set of controller objects to handle
virtually any web functionality required in your application. You’ll also see how
Spring’s handler mapping makes easy work of associating URL patterns with specific
controller implementations. Chapter 14 will pick up where this chapter
leaves off by showing you how to use Spring MVC views to send a response back to
the user.
As a JEE developer, you have more than likely developed a web-based application.
In fact, for many Java developers, web-based applications are their primary focus.
If you do have this type of experience, you are well aware of the challenges that
come with these systems. Specifically, state management, workflow, and validation
are all important features that need to be addressed. None of these is made any
easier given the HTTP protocol’s stateless nature.
Spring’s web framework is designed to help you address these concerns. Based
on the Model-View-Controller (MVC) pattern, Spring MVC helps you build webbased
applications that are as flexible and as loosely coupled as the Spring Framework
itself.
In this chapter and the one that follows, we’ll explore the Spring MVC web
framework. In this chapter, we’ll focus on the parts of Spring MVC that process
requests. You’ll see how to extend Spring’s rich set of controller objects to handle
virtually any web functionality required in your application. You’ll also see how
Spring’s handler mapping makes easy work of associating URL patterns with specific
controller implementations. Chapter 14 will pick up where this chapter
leaves off by showing you how to use Spring MVC views to send a response back to
the user.
Before we go too deep with the specifics of Spring MVC’s controllers and handler
mappings, let’s start with a high-level view of Spring MVC and build our first
complete bit of web functionality.
13.1 GETTING STARTED WITH SPRING MVC
Have you ever seen the children’s game Mousetrap? It’s a crazy game. The goal is
to send a small steel ball over a series of wacky contraptions in order to trigger a
mousetrap. The ball goes over all kinds of intricate gadgets, from rolling down a
curvy ramp to getting sprung off a teeter-totter to spinning on a miniature Ferris
wheel to being kicked out of a bucket by a rubber boot. It goes through of all of
this to spring a trap on a poor, unsuspecting plastic mouse.
At first glance, you may think that Spring’s MVC framework is a lot like Mousetrap.
Instead of moving a ball around through various ramps, teeter-totters, and
wheels, Spring moves requests around between a dispatcher servlet, handler mappings,
controllers, and view resolvers.
But don’t draw too strong of a comparison between Spring MVC and the Rube
Goldberg-esque game of Mousetrap. Each of the components in Spring MVC performs
a specific purpose. Let’s start the exploration of Spring MVC by examining
the lifecycle of a typical request.
13.1.1 A day in the life of a request
Every time that a user clicks a link or submits a form in their web browser, a
request goes to work. A request’s job description is that of a courier. Just like a
postal carrier or a Federal Express delivery person, a request lives to carry information
from one place to another.
The request is a busy fellow. From the time that it leaves the browser until the
time that it returns a response, it will make several stops, each time dropping off a
bit of information and picking up some more. Figure 13.1 shows all the stops that
the request makes.
When the request leaves the browser, it carries information about what the
user is asking for. At very least, the request will be carrying the requested URL. But
it may also carry additional data such as the information submitted in a form by
the user.
The first stop in the request’s travels is Spring’s DispatcherServlet B. Like
most Java-based MVC frameworks, Spring MVC funnels requests through a single
front controller servlet. A front controller is a common web-application pattern
where a single servlet delegates responsibility for a request to other components
of an application to perform the actual processing. In the case of Spring MVC,
DispatcherServlet is the front controller.
The DispatcherServlet’s job is to send the request on to a Spring MVC controller.
A controller is a Spring component that processes the request. But a typical
application may have several controllers and DispatcherServlet needs help
deciding which controller to send the request to. So, the DispatcherServlet
consults one or more handler mappings C to figure out where the request’s next
stop will be. The handler mapping will pay particular attention to the URL carried
by the request when making its decision.
Once an appropriate controller has been chosen, DispatcherServlet sends the
request on its merry way to the chosen controller. D At the controller, the request
will drop off its payload (the information submitted by the user) and patiently wait
for the controller to process that information. (Actually, a well-designed Controller
performs little or no processing itself and instead delegates responsibility for the
business logic to one or more service objects.)
The logic performed by a controller often results in some information that
needs to be carried back to the user and displayed in the browser. This information
is referred to as themodel. But sending raw information back to the user isn’t
sufficient—it needs to be formatted in a user-friendly format, typically HTML. For
that the information needs to be given to aview, typically a JSP.
So, the last thing that the controller will do is package up the model data and the
name of a view into a ModelAndView object. E It then sends the request, along with
its new ModelAndView parcel, back to the DispatcherServlet. As its name implies,
the ModelAndView object contains both the model data as well as a hint to what view
should render the results.
So that the controller isn’t coupled to a particular view, the ModelAndView
doesn’t carry a reference to the actual JSP. Instead it only carries a logical name that
will be used to look up the actual view that will produce the resulting HTML. Once
the ModelAndView is delivered to the DispatcherServlet, the DispatcherServlet
asks a view resolver to help find the actual JSP.
Now that the DispatcherServlet knows which view will render the results, the
request’s job is almost over. Its final stop is at the view implementation (probably a
JSP) where it delivers the model data. G With the model data delivered to the view,
the request’s job is done. The view will use the model data to render a page that will
be carried back to the browser by the (not-so-hard-working) response object.
We’ll discuss each of these steps in more detail throughout this and the next
chapter. But first things first—you’ll need to configure DispatcherServlet to use
Spring MVC.
13.1.2 Configuring DispatcherServlet
At the heart of Spring MVC is DispatcherServlet, a servlet that functions as
Spring MVC’s front controller. Like any servlet, DispatcherServlet must be configured
in your web application’s web.xml file. Place the following <servlet> declaration
in your application’s web.xml file:
The <servlet-name> given to the servlet is significant. By default, when DispatcherServlet
is loaded, it will load the Spring application context from an
XML file whose name is based on the name of the servlet. In this case, because the
servlet is named roadrantz, DispatcherServlet will try to load the application
context from a file named roadrantz-servlet.xml.
Next you must indicate what URLs will be handled by the DispatcherServlet.
Add the following <servlet-mapping> to web.xml to let DispatcherServlet handle
all URLs that end in .htm:
So, you’re probably wondering why we chose this particular URL pattern. It
could be because all of the content produced by our application is HTML. It
could also be because we want to fool our friends into thinking that our entire
application is composed of static HTML files. And it could be that we think .do is
a silly extension.
But the truth of the matter is that the URL pattern is somewhat arbitrary and
we could’ve chosen any URL pattern for DispatcherServlet. Our main reason
for choosing *.htm is that this pattern is the one used by convention in most
Spring MVC applications that produce HTML content. The reasoning behind this
convention is that the content being produced is HTML and so the URL should
reflect that fact.
Now that DispatcherServlet is configured in web.xml and given a URL mapping,
you are ready to start writing the web layer of your application. However,
there’s still one more thing that we recommend you add to web.xml.
Breaking up the application context
As we mentioned earlier, DispatcherServlet will load the Spring application
context from a single XML file whose name is based on its <servlet-name>. But
this doesn’t mean that you can’t split your application context across multiple
XML files. In fact, we recommend that you split your application context across
application layers, as shown in Figure 13.2.
As configured, DispatcherServlet already loads roadrantz-servlet.xml. You could
put all of your application’s <bean> definitions in roadrantz-servlet.xml, but eventually
that file would become quite unwieldy. Splitting it into logical pieces across
application layers can make maintenance easier by keeping each of the Spring
configuration files focused on a single layer of the application. It also makes it
easy to swap out a layer configuration without affecting other layers (swapping out
a roadrantz-data.xml file that uses Hibernate with one that uses iBATIS, for example).
Because DispatcherServlet’s configuration file is roadrantz-servlet.xml, it
makes sense for this file to contain <bean> definitions pertaining to controllers
and other Spring MVC components. As for beans in the service and data layers,
we’d like those beans to be placed in roadrantz-service.xml and roadrantzdata.
xml, respectively.
Configuring a context loader
To ensure that all of these configuration files are loaded, you’ll need to configure
a context loader in your web.xml file. A context loader loads context configuration
files in addition to the one that DispatcherServlet loads. The most commonly
used context loader is a servlet listener called ContextLoaderListener that
is configured in web.xml as follows:
NOTE: Some web containers do not initialize servlet listeners before servlets—
which is important when loading Spring context definitions. If your
application is going to be deployed to an older web container that
that does not initialize listeners before servlets, you’ll want to use ContextLoaderServlet
instead of ContextLoaderListener.
With ContextLoaderListener configured, you’ll need to tell it the location of the
Spring configuration file(s) to load. If not specified otherwise, the context
loader will look for a Spring configuration file at /WEB-INF/applicationContext.
xml. But this location doesn’t lend itself to breaking up the application context
across application layers, so you’ll probably want to override this default.
You can specify one or more Spring configuration files for the context loader
to load by setting the contextConfigLocation parameter in the servlet context:
The contextConfigLocation parameter is specified as a list of paths (relative to
the web application root). As configured here, the context loader will use contextConfigLocation
to load three context configuration files—one for the security
layer, one for the service layer, and one for the data layer.
DispatcherServlet is now configured and ready to dispatch requests to the
web layer of your application. But the web layer hasn’t been built yet! Don’t fret.
We’ll build much of the web layer in this chapter. Let’s start by getting an overview
of how all the pieces of Spring MVC are assembled to produce web functionality.
13.1.3 Spring MVC in a nutshell
Every web application has a homepage. It’s necessary to have a starting point in
the application. It gives the user a place to launch from and a familiar place to
return when they get lost. Otherwise, they would flail around, clicking links, getting
frustrated, and probably ending up leaving and going to some other website.
The RoadRantz application is no exception to the homepage phenomenon.
There’s no better place to start developing the web layer of our application than
with the homepage. In building the homepage, we get a quick introduction to the
nuts and bolts of Spring MVC.
As you’ll recall from the requirements for RoadRantz, the homepage should
display a list of the most recently entered rants. The following list of steps defines
the bare minimum that you must do to build the homepage in Spring MVC:
Write the controller class that performs the logic behind the homepage.
The logic involves using a RantService to retrieve the list of recent rants.
Configure the controller in the DispatcherServlet’s context configuration
file (roadrantz-servlet.xml).
Configure a view resolver to tie the controller to the JSP.
Write the JSP that will render the homepage to the user.
The first step is to build a controller object that will handle the homepage
request. So with no further delay, let’s write our first Spring MVC controller.
Building the controller
When you go out to eat at a nice restaurant, the person you’ll interact with the
most is the waiter or waitress. They’ll take your order, hand it off to the cooks in
the kitchen to prepare, and ultimately bring out your meal. And if they want a
decent tip, they’ll offer a friendly smile and keep the drinks filled. Although you
know that other people are involved in making your meal a pleasant experience,
the waiter or waitress is your interface to the kitchen.
Similarly, in Spring MVC, a controller is a class that is your interface to the
application’s functionality. As shown in Figure 13.3, a controller receives the
request, hands it off to service classes for processing, then ultimately collect the
results in a page that is returned to you in your web browser. In this respect, a controller
isn’t much different than an HttpServlet or a Struts Action.
The homepage controller of the RoadRantz application is relatively simple. It
takes no request parameters and simply produces a list of recently entered rants
for display on the homepage. Listing 13.1 shows HomePageController, a Spring
MVC controller that implements the homepage functionality.
Where a Spring MVC controller differs from a servlet or a Struts Action is that it is
configured as just another JavaBean in the Spring application context. This
means you can take full advantage of dependency injection (DI) and Spring AOP
with a controller class just as you would with any other bean.
In the case of HomePageController, DI is used to wire in a RantService. Home-PageController delegates responsibility for retrieving the list of recent rants to
the RantService.
Introducing ModelAndView
After the chef has prepared your meal, the waiter/waitress will pick it up and
bring it to your table. On the way out, the last thing that they may do is add some
final garnishments—perhaps a sprig of parsley.
Once the business logic has been completed by the service objects, it’s time for
the controller to send the results back to the browser. The last thing that handle-RequestInternal() does is to return a ModelAndView object. The ModelAndView
class represents an important concept in Spring MVC. In fact, every controller
execution method must return a ModelAndView. So, let’s take a moment to understand
how this important class works.
A ModelAndView object, as its name implies, fully encapsulates the view and
model data that is to be displayed by the view. In the case of HomePageController,
the ModelAndView object is constructed as follows:
new ModelAndView("home", "rants", recentRants);
The first parameter of this ModelAndView constructor is the logical name of a view
component that will be used to display the output from this controller. Here the
logical name of the view is home. A view resolver will use this name to look up the
actual View object (you’ll learn more about Views and view resolvers later in chapter
14).
The next two parameters represent the model object that will be passed to the
view. These two parameters act as a name-value pair. The second parameter is the
name of the model object given as the third parameter. In this case, the list of
rants in the recentRants variable will be passed to the view with a name of rants.
Configuring the controller bean
Now that HomePageController has been written, it is time to configure it in the
DispatcherServlet’s context configuration file (which is roadrantz-servlet.xml
for the RoadRantz application). The following chunk of XML declares the Home-PageController:
As mentioned before, the rantService property is to be injected with an implementation
of the RantService interface. In this <bean> declaration, we’ve wired
the rantService property with a reference to another bean named rantService.
The rantService bean itself is declared elsewhere (in roadrantz-service.xml, to
be precise).
One thing that may have struck you as odd is that instead of specifying a
bean id for the HomePageController bean, we’ve specified a name. And to make
things even weirder, instead of giving it a real name, we’ve given it a URL pattern
of /home.htm. Here the name attribute is serving double duty as both the
name of the bean and a URL pattern for requests that should be handled by this
controller. Because the URL pattern has special characters that are not valid in
an XML id attribute—specifically, the slash (/) character—the name attribute
had to be used instead of id.
When a request comes to DispatcherServlet with a URL that ends with
/home.htm, DispatcherServlet will dispatch the request to HomePageController
for handling. Note, however, that the only reason that the bean’s name
attribute is used as the URL pattern is because we haven’t configured a handlermapping
bean. The default handler mapping used by DispatcherServlet is
BeanNameUrlHandlerMapping, which uses the base name as the URL pattern.
Later (in section 13.2), you’ll see how to use some of Spring’s other handler mappings
that let you decouple a controller’s bean name from its URL pattern.
Declaring a view resolver
On the way back to the web browser, the results of the web operation need to be
presented in a human-friendly format. Just like a waiter may place a sprig of parsley
on a plate to make it more presentable, the resulting list of rants needs to be
dressed up a bit before presenting it to the client. For that, we’ll use a JSP page
that will render the results in a user-friendly format.
But how does Spring know which JSP to use for rendering the results? As you’ll
recall, one of the values returned in the ModelAndView object is a logical view
name. While the logical view name doesn’t directly reference a specific JSP, it can
be used to indirectly deduce which JSP to use.
To help Spring MVC figure out which JSP to use, you’ll need to declare one
more bean in roadrantz-servlet.xml: a view resolver. Put simply, a view resolver’s job
is to take the view name returned in the ModelAndView and map it to a view. In the
case of HomePageController, we need a view resolver to resolve home (the logical
view name returned in the ModelAndView) to a JSP file that renders the homepage.
As you’ll see in section 13.4, Spring MVC comes with several view resolvers from
which to choose. But for views that are rendered by JSP, there’s none simpler than
InternalResourceViewResolver:
InternalResourceViewResolver prefixes the view name returned in the ModelAndView
with the value of its prefix property and suffixes it with the value from
its suffix property. Since HomePageController returns a view name of home in
the ModelAndView, InternalResourceViewResolver will find the view at /WEBINF/
jsp/home.jsp.
Creating the JSP
We’ve written a controller that will handle the homepage request and have configured
it in the Spring application context. It will consult with a RantService bean
to look up the most recently added rants. And when it’s done, it will send the
results on to a JSP. So now we only have to create the JSP that renders the homepage.
The JSP in Listing 13.2 iterates over the list of rants and displays them on the
home page.
Although we’ve left out any aesthetic elements in home.jsp for brevity’s sake, it
still serves to illustrate how the model data returned in ModelAndView can be used
in the view. In HomePageController, we placed the list of rants in a model property
named rants. When home.jsp is rendering the homepage, it references the
list of rants as ${rants}.
Be sure to name this JSP home.jsp and to place it in the /WEB-INF/jsp folder in
your web application. That’s where InternalResourceViewResolver will try to
find it.
Putting it all together
The homepage is now complete. You’ve written a controller to handle requests
for the homepage, configured it to rely on BeanNameUrlHandlerMapping to have a
URL pattern of /home.htm, written a simple JSP that represents the homepage,
and configured a view resolver to find the JSP. Now, how does this all fit together?
Figure 13.4 shows the steps that a request for /home.htm will go through given
the work done so far.
To recap this process:
DispatcherServlet receives a request whose URL pattern is /home.htm.
DispatcherServlet consults BeanNameUrlHandlerMapping to find a controller
whose bean name is /home.htm; it finds the HomePageController bean.
DispatcherServlet dispatches the request to HomePageController for processing.
HomePageController returns a ModelAndView object with a logical view
name of home and a list of rants in a property called rants.
DispatcherServlet consults its view resolver (configured as InternalResourceViewResolver)
to find a view whose logical name is home. Internal-ResourceViewResolver returns the path to /WEB-INF/jsp/home.jsp.
DispatcherServlet forwards the request to the JSP at /WEB-INF/jsp/
home.jsp to render the homepage to the user.
Now that you’ve seen the big picture of Spring MVC, let’s slow down a bit and take
a closer look at each of the moving parts involved in servicing a request. We’ll start
where it all begins—with handler mappings.
13.2 MAPPING REQUESTS TO CONTROLLERS
When a courier has a package that is to be delivered to a particular office within a
large office building, they’ll need to know how to find the office. In a large office
building with many tenants, this would be tricky if it weren’t for a building directory.
The building directory is often located near the elevators and helps anyone
unfamiliar with the building locate the floor and suite number of the office
they’re looking for.
In the same way, when a request arrives at the DispatcherServlet, there
needs to be some directory to help figure out how the request should be dispatched.
Handler mappings help DispatcherServlet figure out which controller
the request should be sent to. Handler mappings typically map a specific controller
bean to a URL pattern. This is similar to how URLs are mapped to servlets
using a <servlet-mapping> element in a web application’s web.xml file or how
Actions in Jakarta Struts are mapped to URLs using the path attribute of
<action> in struts-config.xml.
In the previous section, we relied on the fact that DispatcherServlet defaults
to use BeanNameUrlHandlerMapping. BeanNameUrlHandlerMapping was fine to get
started, but it may not be suitable in all cases. Fortunately, Spring MVC offers several
handler-mapping implementations to choose from.
All of Spring MVC’s handler mappings implement the org.springframework.web.servlet.HandlerMapping interface. Spring comes prepackaged with
four useful implementations of HandlerMapping, as listed in Table 13.1.
You’ve already seen an example of how BeanNameUrlHandlerMapping works (as
the default handler mapping used by DispatcherServlet). Let’s look at how to
use each of the other handler mappings, starting with SimpleUrlHandlerMapping.
13.2.1 Using SimpleUrlHandlerMapping
SimpleUrlHandlerMapping is probably one of the most straightforward of
Spring’s handler mappings. It lets you map URL patterns directly to controllers
without having to name your beans in a special way.
For example, consider the following declaration of SimpleUrlHandlerMapping
that associates several of the RoadRantz application’s controllers with their URL
patterns:
SimpleUrlHandlerMapping’s mappings property is wired with a java.util.Properties
using <props>. The key attribute of each <prop> element is a URL pattern.
Just as with BeanNameUrlHandlerMapping, all URL patterns are relative to DispatcherServlet’s
<servlet-mapping>. URL. The value of each <prop> is the
bean name of a controller that will handle requests to the URL pattern.
In case you’re wondering where all of those other controllers came from, just
hang tight. By the time this chapter is done, we’ll have seen most of them. But
first, let’s explore another way to declare controller mappings using the class
names of the controllers.
13.2.2 Using ControllerClassNameHandlerMapping
Oftentimes you’ll find yourself mapping your controllers to URL patterns that are
quite similar to the class names of the controllers. For example, in the RoadRantz
application, we’re mapping rantsForVehicle.htm to RantsForVehicleController
and rantsForDay.htm to RantsForDayController.
Notice a pattern? In those cases, the URL pattern is the same as the name of
the controller class, dropping the Controller portion and adding .htm. It seems
that with a pattern like that it would be possible to assume a certain default for the
mappings and not require explicit mappings.
In fact, that’s roughly what ControllerClassNameHandlerMapping does:
By configuring ControllerClassNameHandlerMapping, you are telling Spring’s
DispatcherServlet to map URL patterns to controllers following a simple convention.
Instead of explicitly mapping each controller to a URL pattern, Spring
will automatically map controllers to URL patterns that are based on the controller’s
class name. Figure 13.5 illustrates how RantsForVehicleController will
be mapped.
Put simply, to produce the URL pattern, the Controller portion of the controller’s
class name is removed (if it exists), the remaining text is lowercased, a
slash (/) is added to the beginning, and ".htm" is added to the end to produce the
URL pattern. Consequently, a controller bean whose class is RantsForVehicle-Controller will be mapped to /rantsforvehicle.htm. Notice that the entire
URL pattern is lowercased, which is slightly different from the convention we were
following with SimpleUrlHandlerMapping.
13.2.3 Using metadata to map controllers
The final handler mapping we’ll look at is CommonsPathMapHandlerMapping.
This handler mapping considers source-level metadata placed in a controller’s
source code to determine the URL mapping. In particular, the metadata is
expected to be an org.springframework.web.servlet.handler.commonsattribute.PathMap attribute compiled into the controller using the Jakarta Commons
Attributes compiler.
To use CommonsPathMapHandlerMapping, simply declare it as a <bean> in your
context configuration file as follows:
Then tag each of your controllers with a PathMap attribute to declare the URL pattern
for the controller. For example, to map HomePageController to /home.htm,
tag HomePageController as follows:
/**
* @@org.springframework.web.servlet.handler.
=> commonsattributes.PathMap("/home.htm")
*/
public class HomePageController
extends AbstractController {
...
}
Finally, you’ll need to set up your build to include the Commons Attributes compiler
so that the attributes will be compiled into your application code. We refer
you to the Commons Attributes homepage (http://jakarta.apache.org/commons/
attributes) for details on how to set up the Commons Attributes compiler
in either Ant or Maven.
13.2.4 Working with multiple handler mappings
As you’ve seen, Spring comes with several useful handler mappings. But what if
you can’t decide which to use? For instance, suppose your application has been
simple and you’ve been using BeanNameUrlHandlerMapping. But it is starting to
grow and you’d like to start using SimpleUrlHandlerMapping going forward. How
can you mix-’n’-match handler mappings during the transition?
As it turns out, all of the handler mapping classes implement Spring’s Ordered
interface. This means that you can declare multiple handler mappings in your
application and set their order properties to indicate which has precedence with
relation to the others.
For example, suppose you want to use both BeanNameUrlHandlerMapping and
SimpleUrlHandlerMapping alongside each other in the same application. You’d
need to declare the handler mapping beans as follows:
Note that the lower the value of the order property, the higher the priority. In this
case, SimpleUrlHandlerMapping’s order is lower than that of BeanNameUrlHandlerMapping.
This means that DispatcherServlet will consult SimpleUrlHandlerMapping
first when trying to map a URL to a controller.
BeanNameUrlHandlerMapping will only be consulted if SimpleUrlHandlerMapping
turns up no results.
Spring’s handler mappings help DispatcherServlet know which controller a
request should be directed to. After DispatcherServlet has figured out where to
send the request, it’s up to a controller to process it. Next up, let’s have a look at
how to create controllers in Spring MVC.
WinConnections Conference Fall 2008 Don’t miss the premier event for Microsoft IT Professionals in Las Vegas, November 10-13. Register and book your room by August 25 and receive a FREE room night (based on a three night minimum stay).
Master SharePoint with 3 eLearning Seminars Learn how to build a better SharePoint infrastructure and enable powerful collaboration with MVPs Dan Holme and Michael Noel. Register today!
SharePointConnections Conference Fall 2008 Don’t miss the premier event for Microsoft IT Professionals in Las Vegas, November 10-13. Register and book your room by August 25 and receive a FREE room night (based on a three night minimum stay).
VMworld 2008 - Sign Up Today! Join your peers on September 15-18 at The Venetian Hotel in Las Vegas as VMware hosts VMworld 2008, the leading Virtualization event.
Microsoft® Tech•Ed EMEA 2008 IT Professionals Advance your thinking with new ideas and practical real-world solutions at Microsoft’s FIVE day technical infrastructure conference 3-7 Nov., 2008. Register before 26 September 2008 to save €300.
Order Your Fundamentals CD Today! Gain an introduction to Exchange, learn server security requirements, and understand how unified communications can play a role in your messaging strategies with this free Exchange CD.
Are You Really Compliant with Software Regulations? View this web seminar that will help you with compliance best practices and check out a management solution to assure that you won’t be in jeopardy of an audit.
Virtualization Congress Oct. 14-16 in London Don't miss Virtualization Congress, the premiere EMEA conference dedicated to hardware, OS and application virtualization. Oct. 14-16 in London.