blob: 8b4b23f5be6b9d6ee4344979c46e87356ac44d00 [file] [log] [blame]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>API Concepts and Roles</title>
</head>
<body>
<h1>WTP Server Tools<br>
API Concepts and Roles</h1>
<p>Last modified Nov. 2, 2004</p>
<p>[<i>This document is a work in progress. The document is an attempt to
capture the key concepts required for understanding and working with the WTP
Server Core API. Note that the concepts may differ subtly from what is currently
found in the currently released <a href="http://dev.eclipse.org/viewcvs/index.cgi/wst/components/server/plugins/org.eclipse.wst.server.core/?cvsroot=WebTools_Project">org.eclipse.wst.server.core
plug-in</a>. Once this document is finalized, our intent is to bring the code
and specs into line with this document.]</i></p>
<p>The key concepts for understanding the API (and SPI) are servers and modules.
The notions of server runtimes and server configurations play an important, but
secondary role.</p>
<p>Not surprisingly, the notion of <b>server</b> is central in the web tools
server infrastructure. In this context we are to understand that the server is a
web server of some ilk (a more exact definition is not required for our
purposes). From a tool-centric point of view, a server is something that the
developer is writing &quot;content&quot; for. (In a sense, the server exists,
but lacks useful content. The development task is to provide that content.) The
content can include anything from simple, static HTML web pages to complex,
highly dynamic web applications. In the course of writing and debugging this
content, they will want to test their content on a web server, to see how it
gets served up. For this they will need to launch a server process running on
some host machine (often the local host on which the Eclipse IDE is running), or
attach to a server that's already running. And we must arrange that the newly
developed content sitting in the developer's workspace ends up in a location and
format that a running server can use for its serving purposes.</p>
<p>(The server objects in the API are in fact intermediary &quot;proxy&quot;
objects that mediate between the tools running in Eclipse and the real server. A
server proxy object has a somewhat independent life from that of a real server.
In cases where the server process must be launched, the proxy object exists in
advance of the server process, and lives past the termination of the server
process. The same server proxy may be serially reused to relaunch server
processes. In cases where we are connecting to a server process running on a
remote host, the server process may well outlive the proxy.)</p>
<p>Servers have a <b>server runtime</b>. The server runtime corresponds to the
installed code base for the server. The main role played by the server runtime
is in identifying code libraries to compile or build against. In the case of
local servers, the server runtime may play a secondary role of being used to
launch the server for testing. Having the server runtimes identified as an
entity separate from the server itself facilitates sharing server runtimes
between several servers.</p>
<p>Servers have an optional <b>server configuration</b>. The server
configuration is information used to configure a running server. Simple types of
servers might not require any configuration, whereas full-featured web server
have an extensive set of parameters for adjusting the server's behavior. Even
though server configuration information usually takes the form of one or more
files, configuration information is treated separately from actual content.
Actual web content can be deployed on different servers without change, whereas
server configuration information is usually highly dependent on the particulars
of the server. Having the server configuration identified as an entity separate
from the server itself facilitates switching an existing server between
configurations, and sharing server configurations between several servers (e.g.,
a local test server and a remote server running on another host).</p>
<p>The web content that is developed for a web server comes in <b>modules</b>. A
module usually consists of a tree of files; a static HTML web is one simple
example. Different types of modules consist of possibly constrained arrangements
files of certain file types. The files making up a module under development
reside in the Eclipse workspace. In order for a server to use access the content
within a module, the module in the workspace must be <b>published </b>to the
server (we use the term&nbsp; <i>publish</i> rather than <i>deploy</i> which is
overused in J2EE). The module is the unit of content that is published to a
server. In the case of J2EE servers, the notion of module aligns with the J2EE
notion of a module (a server concept).&nbsp; But that needn't be the case; some
types of servers, such as a simple HTTP server, don't have a notion of module.
Either way, publishing a module to the server entails whatever it takes to get
the publishable content from the workspace to the server in a form that the
server can access it. Different types of server runtimes are capable of support
various module types.</p>
<p>At any given time, the developer may be working with any number of servers.
Each server has a server configuration and a set of modules. From the complete
set of modules in the workspace, any particular server may see only a subset,
although it is also common for all servers to see all available modules. After
the developer makes changes to the modules in the workspace and now wants to
test their modification, they republish the modules to the server. Depending on
the type of server, republishing a module may entail stopping and restarting the
server.</p>
<p>Some types of modules can have other modules as children. The standard
example of this is a J2EE Enterprise Application (EA) module, whose children are
simple J2EE modules like Enterprise Java Beans and Web Applications. The
parent-child relationship is weak: two parent modules can share the same child
module, and the same child can be parented by several modules (on the same or on
different servers). The file trees for modules are normally mutually disjoint.
Module containment is not reflected by any sort of directory nesting. Parent and
child modules map to non-overlapping file trees.</p>
<p>Modules reside in the workspace. The typical arrangement is that each module
has its own project, termed a <b>module project</b>. The module content usually
corresponds to a particular folder within a project rather than the root of the
project; this allows the project to contain other files (e.g., .project, .classpath,
source code) that are not considered part of the module content proper. Each
different type of module has its own rules for how the content files within it
are laid out. For instance, a J2EE web module has the same structure as an
unzipped WAR file. (Note that the module structure rules are largely implicit
and not reflected directly in the APIs.) It is possible for a project to
contains more than one module (although this arrangement is less common, and not
as well supported).</p>
<p>During development, projects containing modules can be <b>targeted</b> to a
particular server runtime. Targeting allows the IDE to set up various
development time properties of the project (such as the backbone of the Java
build path) appropriately. The most common scenario is where the project is
targeted to the server runtime for the server to which the module is being
published. However, it is also possible to target one server runtime (e.g., a
generic J2EE 1.3 server runtime) while publishing to a server with a different
server runtime (e.g., a Tomcat v5.0 server). Targeting a project to a particular
server runtime typically establishes the Java build classpath of the project to
include the libraries containing the Java APIs for that server runtime (e.g.,
the appropriate J2EE class libraries). The Java build classpath also needs to
reflect inter-module dependencies; for J2EE module types, the appropriate
entries are typically derived from the module's manifest.</p>
<p>A <b>server project</b> is a project used to hold serialized server (server
runtime, server configuration) instances. The project is tagged with a special
Eclipse server nature. The main reason behind server projects was as an
efficient means of making these serialized files visible in the resource
navigator and monitoring changes to them.</p>
<p>The main goals of the Server Core client APIs are to allow clients to create,
configure, and launch instances of particular server types. Due to differences
in the behavior (and APIs) of different server types, a client must generally be
knowledgeable of rules for a particular server type. Clients that have no
knowledge of any specific server type are limited to doing things like starting,
stopping, and relaunching existing servers. In other words, the clients APIs are
generally server-type-specific, rather than sever-type-generic.</p>
<p>The web tools server architecture allows for an open-ended set of server
types, server runtime types, server configuration types, and module types. New
types are declared via extension points in the Server Core plug-in (org.eclipse.wtp.server.core).
Server types are declared by the serverTypes extension point; server runtime
types, by runtimeTypes; server configuration types, by serverConfigurationTypes;
and module types, by moduleKinds. (Additional extension points are discussed
below.) Associated with these extension points are code APIs designed for use by
clients contributing to the Server Core extension points; these are more
correctly called SPIs (service provider interfaces) to distinguish them from the
code designed to be used by other clients (which we refer to here as client
APIs).</p>
<p>Many of the extension points provide for a dynamic code component in addition
to the static information supplied in the extension declaration. These are
termed <i>delegates</i>. For instance, all communication with the running server
is handled by a <b>server delegate</b> contributed via the server type extension
point. Clients generally deal directly with a layer of objects exposed by the
API expressly for client use. In the case of server, clients deal with an
IServer. IServer has a fixed, hidden implementation (the internal class Server),
which hangs on to a lazily-created server delegate of type IServerDelegate. The
IServerDelegate implementation is a server-type-specific object. The more
interesting IServer methods (e.g., getServerState()) are handled by the
delegate. There are also getDelegate() methods that bridge API to SPI, allowing
clients to call methods on the delegate directly. Service providers may also
choose to expose their delegate implementation as API. This allows, for example,
the provider of a server type to offer additional API that is
server-type-specific.</p>
<p>A <b>module factory</b> is responsible for creating modules. There can be any
number of registered module factories, declared via the
org.eclipse.wtp.server.core.moduleFactory extension point. A module factory may
create one or more types of modules (also declared in the extension point). The
module factory API does not prescribe a way to create modules; it does, however,
provide methods for retrieving extant modules that it was responsible for
creating (IModuleFactoryDelegate.getModules() and
IModuleFactoryDelegate.getModule(String memento)).</p>
<p>A <b>publish manager</b> is responsible for deciding whether a file resource
will be published or not (note: publishing includes file deletions as well as
file creations and modifications). Publish managers are declared via the
org.eclipse.wtp.server.core.publish extension point.
ServerCore.getPublishManagers() returns list of know publish managers. There are
two build-in headless publish managers. The Full Publish Manager is dumb, and
publishes all of the module's resource from workspace to server. The Smart
Publish Manager only publishes module resources that have been created, changed,
or deleted in the workspace, or ones that have been changed (somehow) on the
server. A publish operation initiated by IServer.publish(IProgressMonitor
monitor) uses the system-wide default publish manager, which defaults to the
Smart Publish Manager. (There's also a Visual Publish Manager that lets the user
pick and choose which files to publish.)</p>
<p>A <b>publisher</b> (IPublisher) is an object that actually publishes the file
of a particular module to a particular server. Each server type implements its
own publishers. On a particular occasion, the IServerDelegate.getPublisher(List
parents, IModule module) returns the publisher to use to publish the files of
the given module. IPublisher.publish(IModuleResource[] resource,
IProgressMonitor monitor) and IPublisher.delete(IRemoteResource[] resource,
IProgressMonitor monitor) do the heavy lifting.</p>
<p>The client API exposes:</p>
<ul>
<li>Server runtime types as IRuntimeType. ServerCore.getRuntimeTypes() returns
all known server runtime types.</li>
<li>Server types as IServerType. ServerCore.getServerTypes() returns all known
server types.&nbsp;</li>
<li>Server configuration types as IServerConfigurationType.
ServerCore.getServerConfigurationTypes() returns all known server
configuration types.</li>
<li>Module types as IModuleKind. ServerCore.getModuleKinds() returns all known
module kinds.</li>
</ul>
<p>The type-level relationships are:</p>
<ul>
<li>a server type has a server runtime type; this is the type of server
runtime required to run the server; exposed as IServerType.getRuntimeType()</li>
<li>a server type has an optional server configuration type; this is the type
of server configuration required to configure the server; exposed as
IServerType.getServerConfigurationType()</li>
<li>a server runtime type supports 0 or more module types; exposed as
IRuntimeType.getModuleTypes()</li>
</ul>
<p>The API exposes server runtime instances as IRuntime.&nbsp;
ServerCore.getResourceManager().getRuntimes() returns all known server runtime
instances. Server runtime instances are created (only) from server runtime types
by IRuntimeType.createRuntime(String id), which returns an IRuntimeWorkingCopy.
Any number of aspects of the server runtime instance (including location in the
file system) can be established or adjusted from their defaults. When editing is
complete, IRuntimeWorkingCopy.save(IProgressMonitor monitor) creates, registers,
returns a server runtime instance (IRuntime) capturing the desired settings (the
working copy is disposed of).</p>
<p>The API exposes server configuration instances as IServerConfiguration.
ServerCore.getResourceManager().getServerConfigurations() returns all known
server configuration instances. Server configuration instances are created
(only) from server types by
IServerConfigurationType.createServerConfiguration(String id, IFile file,
IProgressMonitor monitor) or IServerConfigurationType.importFromPath(String id,
IFile file, IPath path, IProgressMonitor monitor) or
IServerConfigurationType.importFromRuntime(String id, IFile file, IRuntime
runtime, IProgressMonitor monitor). The file parameter is used to control where
the server configuration instance is serialized. All 3 return an
IServerConfigurationWorkingCopy. (There are no aspects of the server
configuration instance to adjust.)
IServerConfigurationWorkingCopy.save(IProgressMonitor monitor) creates,
registers, returns a server configuration instance (IServerConfiguration)
capturing the desired settings (the working copy is disposed of).&nbsp;</p>
<p>The API exposes server instances as IServer.
ServerCore.getResourceManager().getServers() returns all known server instances.
Server instances are created (only) from server types by
IServerType.createServer(String id, IFile file, IRuntime runtime,
IProgressMonitor monitor) or IServerType.createServer(String id, IFile file,
IRuntime runtime, IProgressMonitor monitor). The file parameter is used to
control where the server instance is serialized. Both return an
IServerWorkingCopy. Any number of aspects of the server instance (host name,
server runtime, server configuration, modules, ...) can be established or
adjusted from their defaults. When editing is complete,
IServerWorkingCopy.save(IProgressMonitor monitor) creates, registers, returns a
server instance (IServer) capturing the desired settings (the working copy is
disposed of).&nbsp;</p>
<p>The instance-level relationship between servers and server runtimes and
server configurations is exposed at the API: for a given server,
IServer.getRuntime() returns the server runtime (IRuntime),
IServer.getServerConfiguration() returns the server configuration (IServerConfiguration).</p>
<p>IServer.start(String mode, IProgressMonitor monitor), stop(), and
restart(String mode) are used to start, stop, and restart a server, respectively
(there are also synchronous methods for starting and stopping). The predicates
IServer.canStart(String mode), canRestart(String mode), and canStop() indicate
whether the server is receptive to being controlled. IServer.getServerState()
can be used to query the overall state of the server (one of starting, started,
stopping, stopped, or unknown), and IServer.getModuleState(IModule module) can
be used to query the state of any of its modules.</p>
</body>
</html>