> For the complete documentation index, see [llms.txt](https://abhishek-gupta.gitbook.io/java-websocket-api-handbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://abhishek-gupta.gitbook.io/java-websocket-api-handbook/deployment.md).

# Deployment

A WebSocket container implementation has to detect and deploy both annotated and programmatic server endpoints. This chapter gives an overview of how WebSocket endpoints are deployed in Java EE (which includes a Servlet container)

## Deploying annotated server endpoints

This is the easy part. Once you implement your annotated (decorated with `@ServerEndpoint`) WebSocket server endpoint, the Servlet runtime weaves it **scanning** magic and extracts all such annotated classes from the WAR (and JARs within), deploys them and ensures they are ready for action

## Deploying programmatic server endpoints

Things are different in case of programmatic server endpoints (which extend `javax.websocket.Endpoint`) - they are not deployed automatically by the container unless we utilize the `javax.websocket.server.ServerApplicationConfig` class

Let's look at an example

```
//A 'chat' club using programmatic web socket endpoint style

public class ChatClub extends Endpoint {
....
@Override
public void onOpen(Session joinee, EndpointConfig config) {
    System.out.println("Peer " + joinee.getId() + " connected");
    joinee.getRemoteBasic().sendText("Welcome to the Chat Club. The first rule of Chat Club is ..... don't talk, just type");
    joinee.addMessageHandler(new MessageHandler.Whole<String>() {
        @Override
        public void onMessage(String message) {
            try {
            joinee.getBasicRemote().sendText("You sent \n"+message+"\nRead the rulez.. again!");
            } catch (IOException ex) {
            throw new RuntimeException(ex);
            }
          }
        });
    }
    ....
}
```

Assuming this is the only (programmatic) endpoint we want to deploy, this is how you would do it

```
//custom implementation to guide the deployment of our programmatic endpoint

public class CustomServerAppConfigProvider implements ServerApplicationConfig {

    @Override
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {
        Set<ServerEndpointConfig> result = new HashSet<>();
        for (Class epClass : endpointClasses) {
            if (epClass.equals(ChatClub.class)) {
            ServerEndpointConfig sec = ServerEndpointConfig.Builder.create(epClass, "/chatclub").build();
            result.add(sec);
           }
        }
        return result;
    }

    @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
        // we do not have annotated endpoints. if we did, they will not be deployed !
        return Collections.emptySet();
    }
}
```

Once the WebSocket container detects an implementation of `ServerApplicationConfig`, it invokes it.

**Things to note**

* Using `ServerApplicationConfig` is **compulsory** in order to deploy programmatic endpoints
* `getEndpointConfigs` method is for deploying programmatic endpoints
* `getAnnotatedEndpointClasses` method is for annotated endpoints
* `Collections.emptySet()` is returned from `getAnnotatedEndpointClasses` since it is assumed that there are no annotated endpoints

> But why do we even need this for annotated endpoints ? Our annotated endpoints get deployed automagically... correct ? Well its **partially correct** since it's applicable to a scenario where we deploy annotated endpoints **only** The next section provides more details...

## Deploying annotated & programmatic server endpoints together

When you have a combination of programmatic and annotated endpoints in your application, then you **have** to make use of a custom subclass of `ServerApplicationConfig` and explicitly return set of all annotated endpoints from the `getAnnotatedEndpointClasses` method

```
//return ALL the auto-detected (scanned) annotated endpoints which the container will deploy

....
@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
    return scanned;
}
....
```

Please note that, using this method, you can choose to **restrict** the endpoints (annotated and programmatic) being deployed i.e. not all the detected endpoints need to be (will be) deployed

> Going back to the question which was posed above.. here is the answer

### This is how it works..

If the WebSocket container finds implementation of the `ServerApplicationConfig` class, it uses the same to deploy **both** programmatic and annotated endpoints. The result of the WAR scanning process (by the Servlet container) is passed on the methods of this class

* For `getEndpointConfigs`, the **set** (`java.util.Set`) of detected programmatic endpoints are passed as the method parameter
* For `getAnnotatedEndpointClasses` method, the **set** (`java.util.Set`) of detected annotated endpoints are passed as the method parameter

## Summary of deployment scenarios

| Annotated Endpoint | Programmatic Endpoint | Behavior                                                                                                                                                                 |
| ------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Yes                | No                    | Automatic detection of annotated endpoint. No custom code needed                                                                                                         |
| No                 | Yes                   | Custom implementation of `ServerApplicationConfig` is compulsory. Progr endpoints are not auto-detected and deployed                                                     |
| Yes                | Yes                   | Custom implementation of `ServerApplicationConfig` is compulsory. Need to explicitly return set of all annotated endpoints from the `getAnnotatedEndpointClasses` method |

## Programmatic API for deploying endpoints

In addition to the above, WebSocket specification also provides a Programmatic API (not to be confused with programmatic endpoints) to deploy endpoints.

> #### Why is it needed ?
>
> The above mentioned deployment strategies rely on the `Servlet` scanning mechanism for endpoint discovery. The programmatic APIs provides an alternative route and can be used in web (Servlet) container without the automatic scanning as well as in case WebSocket endpoints are deployed in standalone mode

The API to be used in this case is `javax.websocket.server.ServerContainer` - it has separate methods for annotated (`void addEndpoint(Class<?> endpointClass)`) and programmatic endpoints (`void addEndpoint(ServerEndpointConfig serverConfig)`)

The instance of `ServerContainer` is obtained in different ways depending on whether the application is executing in a Servlet (web container) or standalone mode

### Usage in a Servlet container

Reference to an instance of the `ServerContainer` interface is made available by using the `javax.websocket.server.ServerContainer` attribute in `javax.servlet.ServletContext`

```
@WebListener
public class ServletCtxBasedDeploymentStrategy implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce){
        //obtain the instance
        ServerContainer sc = (ServerContainer) sce.getServletContext().getAttribute("javax.websocket.server.ServerContainer"); 

        //trigger endpoint deployment
        deployAnnotatedEndpoint(sc);
        deployProgEndpoint(sc);
    }

    private void deployAnnotatedEndpoint(ServerContainer container) {
        container.addEndpoint(StockTicker.class);
        container.addEndpoint(WeatherTracker.class);
    }

    private void deployProgEndpoint(ServerContainer container) {
        container.addEndpoint(ServerEndpointConfig.Builder.create(ChatClub.class, "/chatclub").build());
        container.addEndpoint(ServerEndpointConfig.Builder.create(RealTimeLocationTracker.class, "/location").build());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce){}
}
```

> #### Additional notes
>
> * Standalone usage of `ServerContainer` is depended upon how a specific runtime allows the developer to obtain its instance
> * This is not be mixed with the above mentioned deployment strategy which uses `ServerApplicationConfig`. The implementation will ignore duplicate endpoints (submitted by the separate deployment techniques) since this is mandated by the specification

## In the next chapter ...

... we will look at how the WebSocket components work in concert with the other Java EE APIs from a platform context
