<?xml version="1.0"?>
<!--

    Copyright (c) 2013, 2017 Oracle and/or its affiliates. All rights reserved.

    This program and the accompanying materials are made available under the
    terms of the Eclipse Public License v. 2.0, which is available at
    http://www.eclipse.org/legal/epl-2.0.

    This Source Code may also be made available under the following Secondary
    Licenses when the conditions for such availability set forth in the
    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
    version 2 with the GNU Classpath Exception, which is available at
    https://www.gnu.org/software/classpath/license.html.

    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0

-->

<!DOCTYPE chapter [<!ENTITY % ents SYSTEM "tyrus.ent" > %ents; ]>
<chapter xmlns="http://docbook.org/ns/docbook"
         version="5.0"
         xml:lang="en"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd
                             http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd"
         xml:id="deployment">
    <title>Deploying WebSocket Endpoints</title>
    <para>
        Deploying WebSocket endpoints can be done in two ways. Either deploying via putting the endpoint in the WAR
    file, or using the ServerContainer methods to deploy the programmatic endpoint in the deployment phase.
    </para>

    <section>
        <title>Deploying Endpoints as a WAR file</title>
        <para>
            The classes that are scanned for in WAR are the following ones:
            <itemizedlist mark='opencircle'>
                <listitem>
                    <para>
                        Classes that implement the <code>jakarta.websocket.ServerApplicationConfig</code>.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Classes annotated with <code>jakarta.websocket.server.ServerEndpoint</code>.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Classes that extend <code>jakarta.websocket.Endpoint</code>.
                    </para>
                </listitem>
            </itemizedlist>
        </para>


        <section>
            <title>Deployment Algorithm</title>
            <para>
                <orderedlist numeration="arabic">
                    <listitem>
                        If one or more classes implementing ServerApplicationConfiguration are present in the WAR file, Tyrus deploys endpoints
                        provided by all of these classes. Tyrus doesn't deploy any other classes present in the WAR (annotated by
                        <code>jakarta.websocket.server.ServerEndpoint</code> or extending <code>jakarta.websocket.Endpoint</code>).
                    </listitem>
                    <listitem>
                        If no class implementing ServerApplicationConfiguration is present, Tyrus deploys all classes annotated
                        with @ServerEndpoint or extending Endpoint present in the WAR.
                    </listitem>
                </orderedlist>
            </para>
        </section>

        <para>
            Let's have the following classes in the WAR:
            <example xml:id="deployment-serverapplicationconfig">
                <title>Deployment of WAR containing several classes extending <code>jakarta.websocket.server.ServerApplicationConfig</code></title>
<programlisting language="java" linenumbering="numbered">public class MyApplicationConfigOne implements ServerApplicationConfig {
    public Set&lt;ServerEndpointConfig&gt; getEndpointConfigs(Set&lt;Class&lt;? extends Endpoint&gt;&gt; endpointClasses);
        Set&lt;Class&lt;? extends Endpoint&gt;&gt; s = new HashSet&lt;Class&lt;? extends Endpoint&gt;&gt;;
        s.add(ProgrammaticEndpointOne.class);
        return s;
    }

    public Set&lt;Class&gt; getAnnotatedEndpointClasses(Set&lt;Class&lt;?&gt;&gt; scanned);
       Set&lt;Class&lt;?&gt;&gt; s = new HashSet&lt;Class&lt;?&gt;&gt;;
        s.add(AnnotatedEndpointOne.class);
        return s;
    }
}

public class MyApplicationConfigTwo implements ServerApplicationConfig {
    public Set&lt;ServerEndpointConfig&gt; getEndpointConfigs(Set&lt;Class&lt;? extends Endpoint&gt;&gt; endpointClasses);
        Set&lt;Class&lt;? extends Endpoint&gt;&gt; s = new HashSet&lt;Class&lt;? extends Endpoint&gt;&gt;;
        s.add(ProgrammaticEndpointTwo.class);
    return s;
}

public Set&lt;Class&gt; getAnnotatedEndpointClasses(Set&lt;Class&lt;?&gt;&gt; scanned);
    Set&lt;Class&lt;?&gt;&gt; s = new HashSet&lt;Class&lt;?&gt;&gt;;
        s.add(AnnotatedEndpointTwo.class);
        return s;
    }
}

@ServerEndpoint(value = "/annotatedone")
public class AnnotatedEndpointOne {
    ...
}

@ServerEndpoint(value = "/annotatedtwo")
    public class AnnotatedEndpointTwo {
    ...
}

@ServerEndpoint(value = "/annotatedthree")
public class AnnotatedEndpointThree {
    ...
}

public class ProgrammaticEndpointOne extends Endpoint {
    ...
}

public class ProgrammaticEndpointTwo extends Endpoint {
    ...
}

public class ProgrammaticEndpointThree extends Endpoint {
    ...
}</programlisting>
            </example>
            According to the deployment algorithm classes <code>AnnotatedEndpointOne</code>, <code>AnnotatedEndpointTwo</code>,
            <code>ProgrammaticEndpointOne</code> and <code>ProgrammaticEndpointTwo</code> will be deployed.
            <code>AnnotatedEndpointThree</code> and <code>ProgrammaticEndpointThree</code> will not be
            deployed, as these are not returned by the respective
            methods of <code>MyApplicationConfigOne</code> nor <code>MyApplicationConfigTwo</code>.
        </para>

    </section>

    <section>
        <title>Deploying endpoints via <code>jakarta.websocket.server.ServerContainer</code></title>
        <para>
            Endpoints may be deployed using <code>jakarta.websocket.server.ServerContainer</code> during the application initialization phase.
            For websocket enabled web containers, developers may obtain a reference to the ServerContainer instance by
            retrieving it as an attribute named <code>jakarta.websocket.server.ServerContainer</code> on the ServletContext, see
            the following example for annotated endpoint:
            <example xml:id="deployment-servercontainer">
                <title>Deployment of Annotated Endpoint Using ServerContainer</title>
<programlisting language="java" linenumbering="numbered">@WebListener
@ServerEndpoint("/annotated")
public class MyServletContextListenerAnnotated implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        final ServerContainer serverContainer = (ServerContainer) servletContextEvent.getServletContext()
                                                    .getAttribute("jakarta.websocket.server.ServerContainer");

        try {
            serverContainer.addEndpoint(MyServletContextListenerAnnotated.class);
        } catch (DeploymentException e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public String onMessage(String message) {
        return message;
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}</programlisting>
            </example>
        </para>
    </section>
</chapter>
