| <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 "content" 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 "proxy" | |
| 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 <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). 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. </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. | |
| 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). </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). </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> |