Contribute Glassfish Docs
Initial contribution of Glassfish docs source
Signed-off-by: Vinay Vishal <vinay.vishal@oracle.com>
diff --git a/docs/glassfish/add-on-component-development-guide/src/main/jbake/content/adding-container-capabilities.adoc b/docs/glassfish/add-on-component-development-guide/src/main/jbake/content/adding-container-capabilities.adoc
new file mode 100644
index 0000000..6301fc8
--- /dev/null
+++ b/docs/glassfish/add-on-component-development-guide/src/main/jbake/content/adding-container-capabilities.adoc
@@ -0,0 +1,863 @@
+type=page
+status=published
+title=Adding Container Capabilities
+next=session-persistence-modules.html
+prev=adding-configuration-data.html
+~~~~~~
+Adding Container Capabilities
+=============================
+
+[[GSACG00007]][[ghmon]]
+
+
+[[adding-container-capabilities]]
+7 Adding Container Capabilities
+-------------------------------
+
+Applications run on GlassFish Server in containers. GlassFish Server
+enables you to create containers that extend or replace the existing
+containers of GlassFish Server. Adding container capabilities enables
+you to run new types of applications and to deploy new archive types in
+GlassFish Server.
+
+The following topics are addressed here:
+
+* link:#ghpjl[Creating a `Container` Implementation]
+* link:#ghozu[Adding an Archive Type]
+* link:#ghphp[Creating Connector Modules]
+* link:#gkane[Example of Adding Container Capabilities]
+
+[[ghpjl]][[GSACG00132]][[creating-a-container-implementation]]
+
+Creating a `Container` Implementation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To implement a container that extends or replaces a service in GlassFish
+Server, you must create a Java programming language class that includes
+the following characteristics:
+
+* It is annotated with the `org.jvnet.hk2.annotations.Service`
+annotation.
+* It implements the `org.glassfish.api.container.Container` interface.
+
+You should also run the HK2 Inhabitants Generator utility on your class
+files, which adds classes marked with the `@Service` annotation to the
+`META-INF/hk2-locator/default` file in your JAR file. For more
+information about the HK2 Inhabitants Generator, see the
+https://hk2.java.net/inhabitant-generator.html[HK2 Inhabitants Generator
+page].
+
+[[ghogv]][[GSACG00234]][[marking-the-class-with-the-service-annotation]]
+
+Marking the Class With the `@Service` Annotation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Add a `com.jvnet.hk2.annotations.Service` annotation at the class
+definition level to identify your class as a service implementation.
+
+[source,oac_no_warn]
+----
+@Service
+public class MyContainer implements Container {
+...
+}
+----
+
+To avoid potential name collisions with other containers, use the fully
+qualified class name of your container class in the `@Service`
+annotation's `name` element:
+
+[source,oac_no_warn]
+----
+package com.example.containers;
+...
+
+@Service @javax.inject.Named("com.example.containers.MyContainer")
+public class MyContainer implements Container {
+...
+}
+----
+
+[[ghohg]][[GSACG00235]][[implementing-the-container-interface]]
+
+Implementing the `Container` Interface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The `org.glassfish.api.container.Container` interface is the contract
+that defines a container implementation. Classes that implement
+`Container` can extend or replace the functionality in GlassFish Server
+by allowing applications to be deployed and run within the GlassFish
+Server runtime.
+
+The `Container` interface consists of two methods, `getDeployer` and
+`getName`. The `getDeployer` method returns an implementation class of
+the `org.glassfish.api.deployment.Deployer` interface capable of
+managing applications that run within this container. The `getName`
+method returns a human-readable name for the container, and is typically
+used to display messages belonging to the container.
+
+The `Deployer` interface defines the contract for managing a particular
+application that runs in the container. It consists of the following
+methods:
+
+`getMetaData`::
+ Retrieves the metadata used by the `Deployer` instance, and returns an
+ `org.glassfish.api.deployment.MetaData` object.
+`loadMetaData`::
+ Loads the metadata associated with an application.
+`prepare`::
+ Prepares the application to run in GlassFish Server.
+`load`::
+ Loads a previously prepared application to the container.
+`unload`::
+ Unloads or stops a previously loaded application.
+`clean`::
+ Removes any artifacts generated by an application during the `prepare`
+ phase.
+
+The `DeploymentContext` is the usual context object passed around
+deployer instances during deployment.
+
+[[GSACG00064]][[ghojg]]
+
+
+Example 7-1 Example Implementation of `Container`
+
+This example shows a Java programming language class that implements the
+`Container` interface and is capable of extending the functionality of
+GlassFish Server.
+
+[source,oac_no_warn]
+----
+package com.example.containers;
+contains
+@Service(name="com.example.containers.MyContainer")
+public class MyContainer implements Container {
+ public String getName() {
+ return "MyContainer";
+ }
+
+ public Class<? extends org.glassfish.api.deployment.Deployer> getDeployer() {
+ return MyDeployer.class;
+ }
+}
+----
+
+[[GSACG00065]][[ghoiv]]
+
+
+Example 7-2 Example Implementation of `Deployer`
+
+[source,oac_no_warn]
+----
+package com.example.containers;
+
+@Service
+public class MyDeployer {
+
+ public MetaData getMetaData() {
+ return new MetaData(...);
+ }
+
+ public <V> v loadMetaData(Class<V> type, DeploymentContext dc) {
+ ...
+ }
+
+ public boolean prepare(DeploymentContext dc) {
+ // performs any actions needed to allow the application to run,
+ // such as generating artifacts
+ ...
+ }
+
+ public MyApplication load(MyContainer container, DeploymentContext dc) {
+ // creates a new instance of an application
+ MyApplication myApp = new MyApplication (...);
+ ...
+ // returns the application instance
+ return myApp;
+ }
+
+ public void unload(MyApplication myApp, DeploymentContext dc) {
+ // stops and removes the application
+ ...
+ }
+
+ public void clean (DeploymentContext dc) {
+ // cleans up any artifacts generated during prepare()
+ ...
+ }
+}
+----
+
+[[ghozu]][[GSACG00133]][[adding-an-archive-type]]
+
+Adding an Archive Type
+~~~~~~~~~~~~~~~~~~~~~~
+
+An archive type is an abstraction of the archive file format. An archive
+type can be implemented as a plain JAR file, as a directory layout, or a
+custom type. By default, GlassFish Server recognizes JAR based and
+directory based archive types. A new container might require a new
+archive type.
+
+There are two sub-interfaces of the
+`org.glassfish.api.deployment.archive.Archive` interface,
+`org.glassfish.api.deployment.archive.ReadableArchive` and
+`org.glassfish.api.deployment.archive.WritableArchive`. Typically
+developers of new archive types will provide separate implementations of
+`ReadableArchive` and `WritableArchive`, or a single implementation that
+implements both `ReadableArchive` and `WritableArchive`.
+
+Implementations of the `ReadableArchive` interface provide read access
+to an archive type. `ReadableArchive` defines the following methods:
+
+`getEntry(String name)`::
+ Returns a `java.io.InputStream` for the specified entry name, or null
+ if the entry doesn't exist.
+`exists(String name)`::
+ Returns a `boolean` value indicating whether the specified entry name
+ exists.
+`getEntrySize(String name)`::
+ Returns the size of the specified entry as a `long` value.
+`open(URI uri)`::
+ Returns an archive for the given `java.net.URI`.
+`getSubArchive(String name)`::
+ Returns an instance of `ReadableArchive` for the specified sub-archive
+ contained within the parent archive, or null if no such archive
+ exists.
+`exists()`::
+ Returns a `boolean` value indicating whether this archive exists.
+`delete()`::
+ Deletes the archive, and returns a `boolean` value indicating whether
+ the archive has been successfully deleted.
+`renameTo(String name)`::
+ Renames the archive to the specified name, and returns a `boolean`
+ value indicating whether the archive has been successfully renamed.
+
+Implementations of the `WritableArchive` interface provide write access
+to the archive type. `WritableArchive` defines the following methods:
+
+`create(URI uri)`::
+ Creates a new archive with the given path, specified as a
+ `java.net.URI`.
+`closeEntry(WritableArchive subArchive)`::
+ Closes the specified sub-archive contained within the parent archive.
+`closeEntry()`::
+ Closes the current entry.
+`createSubArchive(String name)`::
+ Creates a new sub-archive in the parent archive with the specified
+ name, and returns it as a `WritableArchive` instance.
+`putNextEntry(String name)`::
+ Creates a new entry in the archive with the specified name, and
+ returns it as a `java.io.OutputStream`.
+
+[[ghoyp]][[GSACG00236]][[implementing-the-archivehandler-interface]]
+
+Implementing the `ArchiveHandler` Interface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An archive handler is responsible for handling the particular layout of
+an archive. Java EE defines a set of archives (WAR, JAR, and RAR, for
+example), and each of these archives has an `ArchiveHandler` instance
+associated with the archive type.
+
+Each layout should have one handler associated with it. There is no
+extension point support at this level; the archive handler's
+responsibility is to give access to the classes and resources packaged
+in the archive, and it should not contain any container-specific code.
+The `java.lang.ClassLoader` returned by the handler is used by all the
+containers in which the application will be deployed.
+
+`ArchiveHandler` defines the following methods:
+
+`getArchiveType()`::
+ Returns the name of the archive type as a `String`. Typically, this is
+ the archive extension, such as `jar` or `war`.
+`getDefaultApplicationName(ReadableArchive archive)`::
+ Returns the default name of the specified archive as a `String`.
+ Typically this default name is the name part of the `URI` location of
+ the archive.
+`handles(ReadableArchive archive)`::
+ Returns a `boolean` value indicating whether this implementation of
+ `ArchiveHandler` can work with the specified archive.
+`getClassLoader(DeploymentContext dc)`::
+ Returns a `java.lang.ClassLoader` capable of loading all classes from
+ the archive passed in by the `DeploymentContext` instance. Typically
+ the `ClassLoader` will load classes in the scratch directory area,
+ returned by `DeploymentContext.getScratchDir()`, as stubs and other
+ artifacts are generated in the scratch directory.
+`expand(ReadableArchive source, WritableArchive target)`::
+ Prepares the `ReadableArchive`source archive for loading into the
+ container in a format the container accepts. Such preparation could be
+ to expand a compressed archive, or possibly nothing at all if the
+ source archive format is already in a state that the container can
+ handle. This method returns the archive as an instance of
+ `WritableArchive`.
+
+[[ghphp]][[GSACG00134]][[creating-connector-modules]]
+
+Creating Connector Modules
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Connector modules are small add-on modules that consist of application
+"sniffers" that associate application types with containers that can run
+the application type. GlassFish Server connector modules are separate
+from the associated add-on module that delivers the container
+implementation to allow GlassFish Server to dynamically install and
+configure containers on demand.
+
+When a deployment request is received by the GlassFish Server runtime:
+
+1. The current `Sniffer` implementations are used to determine the
+application type.
+2. Once an application type is found, the runtime looks for a running
+container associated with that application type. If no running container
+is found, the runtime attempts to install and configure the container
+associated with the application type as defined by the `Sniffer`
+implementation.
+3. The `Deployer` interface is used to prepare and load the
+implementation.
+
+[[ghozd]][[GSACG00237]][[associating-file-types-with-containers-by-using-the-sniffer-interface]]
+
+Associating File Types With Containers by Using the `Sniffer` Interface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Containers do not necessarily need to be installed on the local machine
+for GlassFish Server to recognize the container's application type.
+GlassFish Server uses a "sniffer" concept to study the artifacts in a
+deployment request and to choose the associated container that handles
+the application type that the user is trying to deploy. To create this
+association, create a Java programming language class that implements
+the `org.glassfish.api.container.Sniffer` interface. This implementation
+can be as simple as looking for a specific file in the application's
+archive (such as the presence of `WEB-INF/web.xml`), or as complicated
+as running an annotation scanner to determine an XML-less archive (such
+as enterprise bean annotations in a JAR file). A `Sniffer`
+implementation must be as small as possible and must not load any of the
+container's runtime classes.
+
+A simple version of a `Sniffer` implementation uses the `handles` method
+to check the existence of a file in the archive that denotes the
+application type (as `WEB-INF/web.xml` denotes a web application). Once
+a `Sniffer` implementation has detected that it can handle the
+deployment request artifact, GlassFish Server calls the `setUp` method.
+The `setUp` method is responsible for setting up the container, which
+can involve one or more of the following actions:
+
+* Downloading the container's runtime (the first time that a container
+is used)
+* Installing the container's runtime (the first time that a container is
+used)
+* Setting up one or more repositories to access the runtime's classes
+(these are implementations of the HK2
+`com.sun.enterprise.module.Repository` interface, such as the
+`com.sun.enterprise.module.impl.DirectoryBasedRepository` class)
+
+The `setUp` method returns an array of the
+`com.sun.enterprise.module.Module` objects required by the container.
+
+The `Sniffer` interface defines the following methods:
+
+`handles(ReadableArchive source, ClassLoader loader)`::
+ Returns a `boolean` value indicating whether this `Sniffer`
+ implementation can handle the specified archive.
+`getURLPatterns()`::
+ Returns a `String` array containing all URL patterns to apply against
+ the request URL. If a pattern matches, the service method of the
+ associated container is invoked.
+`getAnnotationTypes()`::
+ Returns a list of annotation types recognized by this `Sniffer`
+ implementation. If an application archive contains one of the returned
+ annotation types, the deployment process invokes the container's
+ deployers as if the `handles` method had returned true.
+`getModuleType()`::
+ Returns the module type associated with this `Sniffer` implementation
+ as a `String`.
+`setup(String containerHome, Logger logger)`::
+ Sets up the container libraries so that any dependent bundles from the
+ connector JAR file will be made available to the HK2 runtime. The
+ `setup` method returns an array of `com.sun.enterprise.module.Module`
+ classes, which are definitions of container implementations. GlassFish
+ Server can then load these modules so that it can create an instance
+ of the container's `Deployer` or `Container` implementations when it
+ needs to. The module is locked as long as at least one module is
+ loaded in the associated container.
+`teardown()`::
+ Removes a container and all associated modules in the HK2 modules
+ subsystem.
+`getContainerNames()`::
+ Returns a `String` array containing the `Container` implementations
+ that this `Sniffer` implementation enables.
+`isUserVisible()`::
+ Returns a `boolean` value indicating whether this `Sniffer`
+ implementation should be visible to end-users.
+`getDeploymentConfigurations(final ReadableArchive source)`::
+ Returns a `Map<String, String>` of deployment configuration names to
+ configurations from this `Sniffer` implementation for the specified
+ application (the archive source). The names are created by GlassFish
+ Server; the configurations are the names of the files that contain
+ configuration information (for example, `WEB-INF/web.xml` and possibly
+ `WEB-INF/sun-web.xml` for a web application). If the
+ `getDeploymentConfigurations` method encounters errors while searching
+ or reading the specified archive source, it throws a
+ `java.io.IOException`.
+
+[[ghpbx]][[GSACG00172]][[making-sniffer-implementations-available-to-the-glassfish-server]]
+
+Making `Sniffer` Implementations Available to the GlassFish Server
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Package `Sniffer` implementation code into modules and install the
+modules in the as-install`/modules` directory. GlassFish Server will
+automatically discover these modules. If an administrator installs
+connector modules that contain`Sniffer` implementations while GlassFish
+Server is running, GlassFish Server will pick them up at the next
+deployment request.
+
+[[gkane]][[GSACG00135]][[example-of-adding-container-capabilities]]
+
+Example of Adding Container Capabilities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This example shows a custom container and a web client of the container.
+The example is comprised of the following code:
+
+* Code for the container, which is shown in link:#gkbah[Container
+Component Code]
+* Code for a web client of the container, which is shown in
+link:#gkbcq[Web Client Code]
+
+Code that defines the configuration data for the container component is
+shown in link:adding-configuration-data.html#gkaal[Examples of Adding
+Configuration Data for a Component].
+
+Code for an `asadmin` subcommand that updates the configuration data in
+this example is shown in link:extending-asadmin.html#gkbdf[Example 4-7].
+
+[[gkbah]][[GSACG00238]][[container-component-code]]
+
+Container Component Code
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The container component code is comprised of the classes and interfaces
+that are listed in the following table. The table also provides a
+cross-reference to the listing of each class or interface.
+
+[width="100%",cols="<50%,<50%",options="header",]
+|==============================================
+|Class or Interface |Listing
+|`Greeter` |link:#gkamr[Example 7-3] +
+|`GreeterContainer` |link:#gkand[Example 7-4] +
+|`GreeterContainer` |link:#gkamm[Example 7-5] +
+|`GreeterDeployer` |link:#gkalo[Example 7-6] +
+|`GreeterSniffer` |link:#gkaks[Example 7-7] +
+|==============================================
+
+
+[[GSACG00066]][[gkamr]]
+
+
+Example 7-3 Annotation to Denote a Container's Component
+
+This example shows the code for defining a component of the `Greeter`
+container.
+
+[source,oac_no_warn]
+----
+package org.glassfish.examples.extension.greeter;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Simple annotation to denote Greeter's component
+ */
+@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+public @interface Greeter {
+
+ /**
+ * Name to uniquely identify different greeters
+ *
+ * @return a good greeter name
+ */
+ public String name();
+}
+----
+
+[[GSACG00067]][[gkand]]
+
+
+Example 7-4 Application Container Class
+
+This example shows the Java language class `GreeterAppContainer`, which
+implements the `ApplicationContainer` interface.
+
+[source,oac_no_warn]
+----
+package org.glassfish.examples.extension.greeter;
+
+import org.glassfish.api.deployment.ApplicationContainer;
+import org.glassfish.api.deployment.ApplicationContext;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class GreeterAppContainer implements ApplicationContainer {
+
+ final GreeterContainer ctr;
+ final List<Class> componentClasses = new ArrayList<Class>();
+
+ public GreeterAppContainer(GreeterContainer ctr) {
+ this.ctr = ctr;
+ }
+
+ void addComponent(Class componentClass) {
+ componentClasses.add(componentClass);
+ }
+
+ public Object getDescriptor() {
+ return null;
+ }
+
+ public boolean start(ApplicationContext startupContext) throws Exception {
+ for (Class componentClass : componentClasses) {
+ try {
+ Object component = componentClass.newInstance();
+ Greeter greeter = (Greeter)
+ componentClass.getAnnotation(Greeter.class);
+ ctr.habitat.addComponent(greeter.name(), component);
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return true;
+ }
+
+ public boolean stop(ApplicationContext stopContext) {
+ for (Class componentClass : componentClasses) {
+ ctr.habitat.removeAllByType(componentClass);
+ }
+ return true;
+ }
+
+ public boolean suspend() {
+ return false;
+ }
+
+ public boolean resume() throws Exception {
+ return false;
+ }
+
+ public ClassLoader getClassLoader() {
+ return null;
+ }
+}
+----
+
+[[GSACG00068]][[gkamm]]
+
+
+Example 7-5 Container Class
+
+This example shows the Java language class `GreeterContainer`, which
+implements the `Container` interface.
+
+[source,oac_no_warn]
+----
+package org.glassfish.examples.extension.greeter;
+
+import org.glassfish.api.container.Container;
+import org.glassfish.api.deployment.Deployer;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.annotations.Inject;
+import org.jvnet.hk2.component.Habitat;
+
+@Service(name="org.glassfish.examples.extension.GreeterContainer")
+public class GreeterContainer implements Container {
+
+ @Inject
+ Habitat habitat;
+
+ public Class<? extends Deployer> getDeployer() {
+ return GreeterDeployer.class;
+ }
+
+ public String getName() {
+ return "greeter";
+ }
+}
+----
+
+[[GSACG00069]][[gkalo]]
+
+
+Example 7-6 Deployer Class
+
+This example shows the Java language class `GreeterDeployer`, which
+implements the `Deployer` interface.
+
+[source,oac_no_warn]
+----
+package org.glassfish.examples.extension.greeter;
+
+import org.glassfish.api.deployment.Deployer;
+import org.glassfish.api.deployment.MetaData;
+import org.glassfish.api.deployment.DeploymentContext;
+import org.glassfish.api.deployment.ApplicationContainer;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.api.container.Container;
+import org.jvnet.hk2.annotations.Service;
+
+import java.util.Enumeration;
+
+@Service
+public class GreeterDeployer
+ implements Deployer<GreeterContainer, GreeterAppContainer> {
+
+ public MetaData getMetaData() {
+ return null;
+ }
+
+ public <V> V loadMetaData(Class<V> type, DeploymentContext context) {
+ return null;
+ }
+
+ public boolean prepare(DeploymentContext context) {
+ return false;
+ }
+
+ public GreeterAppContainer load(
+ GreeterContainer container, DeploymentContext context) {
+
+ GreeterAppContainer appCtr = new GreeterAppContainer(container);
+ ClassLoader cl = context.getClassLoader();
+
+ ReadableArchive ra = context.getOriginalSource();
+ Enumeration<String> entries = ra.entries();
+ while (entries.hasMoreElements()) {
+ String entry = entries.nextElement();
+ if (entry.endsWith(".class")) {
+ String className = entryToClass(entry);
+ try {
+ Class componentClass = cl.loadClass(className);
+ // ensure it is one of our component
+ if (componentClass.isAnnotationPresent(Greeter.class)) {
+ appCtr.addComponent(componentClass);
+ }
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+ }
+ return appCtr;
+ }
+
+ public void unload(GreeterAppContainer appContainer, DeploymentContext context) {
+
+ }
+
+ public void clean(DeploymentContext context) {
+
+ }
+
+ private String entryToClass(String entry) {
+ String str = entry.substring("WEB-INF/classes/".length(), entry.length()-6);
+ return str.replaceAll("/", ".");
+ }
+}
+----
+
+[[GSACG00070]][[gkaks]]
+
+
+Example 7-7 Sniffer Class
+
+This example shows the Java language class `GreeterSniffer`, which
+implements the `Sniffer` interface.
+
+[source,oac_no_warn]
+----
+package org.glassfish.examples.extension.greeter;
+
+import org.glassfish.api.container.Sniffer;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.api.admin.config.ConfigParser;
+import org.glassfish.examples.extension.greeter.config.GreeterContainerConfig;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.annotations.Inject;
+import org.jvnet.hk2.component.Habitat;
+import com.sun.enterprise.module.Module;
+
+import java.util.logging.Logger;
+import java.util.Map;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.net.URL;
+
+/**
+ * @author Jerome Dochez
+ */
+@Service(name="greeter")
+public class GreeterSniffer implements Sniffer {
+
+ @Inject(optional=true)
+ GreeterContainerConfig config=null;
+
+ @Inject
+ ConfigParser configParser;
+
+ @Inject
+ Habitat habitat;
+
+ public boolean handles(ReadableArchive source, ClassLoader loader) {
+ return false;
+ }
+
+ public String[] getURLPatterns() {
+ return new String[0];
+ }
+
+ public Class<? extends Annotation>[] getAnnotationTypes() {
+ Class<? extends Annotation>[] a = (Class<? extends Annotation>[]) Array.newInstance(Class.class, 1);
+ a[0] = Greeter.class;
+ return a;
+ }
+
+ public String getModuleType() {
+ return "greeter";
+ }
+
+ public Module[] setup(String containerHome, Logger logger) throws IOException {
+ if (config==null) {
+ URL url = this.getClass().getClassLoader().getResource("init.xml");
+ if (url!=null) {
+ configParser.parseContainerConfig(
+ habitat, url, GreeterContainerConfig.class);
+ }
+ }
+ return null;
+ }
+
+ public void tearDown() {
+
+ }
+
+ public String[] getContainersNames() {
+ String[] c = { GreeterContainer.class.getName() };
+ return c;
+ }
+
+ public boolean isUserVisible() {
+ return true;
+ }
+
+ public Map<String, String> getDeploymentConfigurations
+ (ReadableArchive source) throws IOException {
+ return null;
+ }
+
+ public String[] getIncompatibleSnifferTypes() {
+ return new String[0];
+ }
+}
+----
+
+[[gkbcq]][[GSACG00239]][[web-client-code]]
+
+Web Client Code
+^^^^^^^^^^^^^^^
+
+The web client code is comprised of the classes and resources that are
+listed in the following table. The table also provides a cross-reference
+to the listing of each class or resource.
+
+[width="100%",cols="<50%,<50%",options="header",]
+|==================================================
+|Class or Resource |Listing
+|`HelloWorld` |link:#gkaki[Example 7-8] +
+|`SimpleGreeter` |link:#gkalf[Example 7-9] +
+|Deployment descriptor |link:#gkaly[Example 7-10] +
+|==================================================
+
+
+[[GSACG00071]][[gkaki]]
+
+
+Example 7-8 Container Client Class
+
+[source,oac_no_warn]
+----
+import components.SimpleGreeter;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import javax.annotation.Resource;
+
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorld extends HttpServlet {
+
+ @Resource(name="Simple")
+ SimpleGreeter greeter;
+
+ public void doGet(HttpServletRequest req, HttpServletResponse res)
+ throws IOException, ServletException {
+
+
+ PrintWriter pw = res.getWriter();
+ try {
+ pw.println("Injected service is " + greeter);
+ if (greeter!=null) {
+ pw.println("SimpleService says " + greeter.saySomething());
+ pw.println("<br>");
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+----
+
+[[GSACG00072]][[gkalf]]
+
+
+Example 7-9 Component for Container Client
+
+[source,oac_no_warn]
+----
+package components;
+
+import org.glassfish.examples.extension.greeter.Greeter;
+
+@Greeter(name="simple")
+public class SimpleGreeter {
+
+ public String saySomething() {
+ return "Bonjour";
+ }
+}
+----
+
+[[GSACG00073]][[gkaly]]
+
+
+Example 7-10 Deployment Descriptor for Container Client
+
+[source,oac_no_warn]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=
+ "http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+</web-app>
+----