Preloader image

A API Server.Builder permite que você construa uma instância embutida(embedded) ou sem servidor(serverless) de Tomcat/TomEE dentro da sua JVM, efetivamente executando Tomcat/TomEE como uma biblioteca simples.

import org.apache.tomee.bootstrap.Server;

public class Main {
    public static void main(String[] args) {
        final Server server = Server.builder().build();

        System.out.println("Listening for requests at " + server.getURI());
    }
}

O design da API pode ser melhor descrito como uma API de construtor funcional (FBA) e permite efetivamente fornecer funções e referências de método que realmente auxiliam no processo de construção do servidor. É por meio dessas funções que você pode implantar aplicativos, modificar configurações e executar com eficácia qualquer código de que você precisa para ajudar a preparar a instância do servidor.

Uma visão geral de alto nível dos métodos builder disponíveis após chamar Server.builder () são os seguintes:

public static class Builder
    public Builder httpPort(final int port)
    public Builder ajpPort(final int port)
    public Builder add(final String name, final byte[] bytes)
    public Builder add(final String name, final Supplier<byte[]> content)
    public Builder add(final String name, final String content)
    public Builder add(final String name, final File content)
    public Builder add(final String name, final Archive contents)
    public Builder home(final Consumer<File> customization)
    public Builder and(final Consumer<Builder> consumer)
    public Server build()

Para realmente saber como usar a API, primeiramente devemos entender os conceitos catalina.home e catalina.base do Tomcat e o que realmente acontece quando chamamos Server.builder().Build().

Compreendendo a home e base do Tomcat

É um fato pouco conhecido que por décadas o Tomcat teve a capacidade de executar várias instâncias a partir de um único zip do Tomcat. O Tomcat usa uma variável catalina.home para identificar a localização do zip extraído onde as bibliotecas do servidor podem ser encontradas e um catalina.base por instância para definir a localização dos arquivos de configuração, arquivos de log e aplicativos da web dessa instância.

Em nossa situação, seu classpath JVM é efetivamente o catalina.home e quando usamos a API do Server estamos criando um catalina.base muito fino que contém os arquivos de configuração, arquivos de log e webapps para essa instância de servidor construído (Tomcat). Se você usar a API Server dez vezes na mesma JVM, terá 10 diretórios ` catalina.base`. No entanto, eles são considerados locais de trabalho temporários e serão excluídos na saída da JVM.

Chamando o Server.builder().build()

Quando o método build() do Server.Builder é chamado, as seguintes ações são realizadas nesta ordem:

  1. Quaisquer funções adicionadas via and(final Consumer<Builder> consumer) são executadas. Isso permite que seja fornecida uma função que modifique ainda mais o construtor antes de qualquer construção ser executada. Várias modificações do construtor podem ser agrupadas em uma função que as instala todas.

  2. É criado um diretório temporário que servirá como catalina.home e catalina.base e as configurações padrão como server.xml,logging.properties e tomee.xml são copiadas.

  3. AQuaisquer funções adicionadas por meio de add(final String destinationPath, final Supplier<byte[]> content) são executadas e quaisquer bytes fornecidos, Strings ou Arquivos são gravados em destinationPath dentro do diretório temporário. Isso permite que as configurações padrão como server.xml sejam sobrescritas ou aplicativos sejam escritos no diretório webapps/.

  4. As portas são definidas modificando-se conf/server.xml. Se httpPort não foi definido, as portas serão aleatórias.

  5. Todas as funções adicionadas via home(final Consumer<File> customization) são executadas. O diretório temporário será fornecido como o valor de File.

  6. A instância Tomcat/TomEE é iniciada e retornada como uma instância de Server.

Vendo o resultado de Server.builder().Build()

Ajuda muito poder ver o que foi construído. Podemos fazer isso instalando uma referência de função ou método como mostrada abaixo.

import org.apache.tomee.bootstrap.Server;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

public class Main {

    public static void main(String[] args) {
        Server.builder()
                .home(Main::list)
                .build();
    }

    private static void list(final File home) {
        try {
            Files.walk(home.toPath())
                    .sorted()
                    .forEach(System.out::println);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

Quando o executamos, devemos ver uma saída semelhante a esta:

/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/catalina.policy
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/catalina.properties
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/context.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/jaspic-providers.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/jaspic-providers.xsd
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/logging.properties
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/server.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/system.properties
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomcat-users.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomcat-users.xsd
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomee.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/web.xml
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/logs
/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/webapps

O acima representa o que sai da caixa ao chamar Server.builder().Build() sem modificações.

Criação de aplicativos com Archive

A segunda classe a aprender é Archive e é essencialmente um construtor de aplicativos simples. Com essa abordagem, todas as suas classes já estão efetivamente no classpath e visíveis, portanto, em última análise, as únicas classes que precisam ser incluídas são Servlets anotados, EJBs, CDI Beans, classes JAX-RS, etc.

public class Archive
    public static Archive archive()
    public Archive manifest(final String key, final Object value)
    public Archive manifest(final String key, final Class value)
    public Archive add(final String name, final byte[] bytes)
    public Archive add(final String name, final Supplier<byte[]> content)
    public Archive add(final String name, final String content)
    public Archive add(final String name, final File content)
    public Archive add(final String name, final Archive archive)
    public Archive add(final String name, final URL content)
    public Archive add(final Class<?> clazz)
    public Archive addDir(final File dir)
    public Archive addJar(final File file)
    public File toJar()
    public File toJar(final File file)
    public File toDir()
    public void toDir(final File dir)
Você pode usar APIs como ShrinkWrap para construir os jars e arquivos war como uma alternativa para Archive. Qualquer coisa que possa produzir um arquivo jar, um arquivo war ou uma estrutura de diretório war explodida (descompactada) funcionará.

Creating a ROOT war

Neste exemplo, estamos efetivamente adicionando três classes a um Archive que é adicionado a um novo diretório webapps/ROOT/WEB-INF/classes.

import org.apache.tomee.bootstrap.Archive;
import org.apache.tomee.bootstrap.Server;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;

public class Main {

    public static void main(String[] args) {

        final Server server = Server.builder()
                .add("webapps/ROOT/WEB-INF/classes", Archive.archive()
                        .add(Api.class)
                        .add(Movie.class)
                        .add(MovieService.class))
                .home(Main::list)
                .build();

        System.out.println("Listening for requests at " + server.getURI());
    }

    private static void list(final File home) {
        try {
            Files.walk(home.toPath())
                    .map(Path::toFile)
                    .filter(File::isFile)
                    .map(File::getAbsolutePath)
                    .map(s -> "..." + s.substring(49))
                    .sorted()
                    .forEach(System.out::println);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

Quando isso for executado, veremos o método Main.list, que é executado logo antes do início do servidor, imprimirá o seguinte:

...temp710654453954858189dir/apache-tomee/conf/catalina.policy
...temp710654453954858189dir/apache-tomee/conf/catalina.properties
...temp710654453954858189dir/apache-tomee/conf/context.xml
...temp710654453954858189dir/apache-tomee/conf/jaspic-providers.xml
...temp710654453954858189dir/apache-tomee/conf/jaspic-providers.xsd
...temp710654453954858189dir/apache-tomee/conf/logging.properties
...temp710654453954858189dir/apache-tomee/conf/server.xml
...temp710654453954858189dir/apache-tomee/conf/system.properties
...temp710654453954858189dir/apache-tomee/conf/tomcat-users.xml
...temp710654453954858189dir/apache-tomee/conf/tomcat-users.xsd
...temp710654453954858189dir/apache-tomee/conf/tomee.xml
...temp710654453954858189dir/apache-tomee/conf/web.xml
...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/Api.class
...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/Movie.class
...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/MovieService.class