Nesta publicação vamos mostrar como criar um servidor web standalone, ou seja, vamos compilar o projeto como um jar e executa-lo pelo terminal sem a necessidade de precisar dar deploy em um container java (exemplo: glassfish, toncat, etc). Para isso vamos criar um projeto java com o maven para incluir as seguintes dependências:
javax: javaee-web-api
org.glassfish.grizzly: grizzly-http-server, grizzly-framework
org.glassfish.jersey.core: jersey-server, jersey-common, jersey-client
org.glassfish.jersey.media: jersey-media-sse, jersey-media-json-processing
org.glassfish.jersey.containers: jersey-container-grizzly2-http, jersey-container-servlet
Essas dependências permitem criar um web server e subir sua aplicação em um container próprio. As dependências do javax nos permite criar o serviço web REST, a grizzly fica responsável pelo servidor web e a jersy pelo container. Nesse projeto não vamos chegar a usar todas essas dependências porem vamos deixar no projeto.
Iniciaremos o projeto configurando o pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <name>WebServerStandalone</name> <modelVersion>4.0.0</modelVersion> <groupId>br.com.helpdev</groupId> <artifactId>WebServerStandalone</artifactId> <version>1.0-SNAPSHOT</version> <!-- packaging: jar ou war --> <packaging>jar</packaging> <properties> <!-- endorsed.dir: utilizado para projetos WEB/Glassfish --> <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- Versões utilizadas para as dependencias jersey e grizzly para rodar o server standalone --> <version.jersey>2.25.1</version.jersey> <version.grizzly>2.3.31</version.grizzly> <!--Versão java source e target--> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!-- java.mainClass: Java main Class --> <java.mainClass>br.com.helpdev.webserver.Main</java.mainClass> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <!-- ABAIXO DEPENDENCIAS PARA SERVIDOR STANDALONE: --> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-common</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-sse</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-http</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-processing</artifactId> <version>${version.jersey}</version> </dependency> <dependency> <groupId>org.glassfish.grizzly</groupId> <artifactId>grizzly-http-server</artifactId> <version>${version.grizzly}</version> </dependency> <dependency> <groupId>org.glassfish.grizzly</groupId> <artifactId>grizzly-framework</artifactId> <version>${version.grizzly}</version> </dependency> <!-- ACIMA DEPENDENCIAS PARA SERVIDOR STANDALONE --> </dependencies> <build> <plugins> <!-- FAT-JAR --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4.1</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>libs/</classpathPrefix> <mainClass>${java.mainClass}</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> <!-- JAR EXTERNAL LIBS --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>libs/</classpathPrefix> <mainClass>${java.mainClass}</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>copy</id> <phase>install</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/libs </outputDirectory> </configuration> </execution> </executions> </plugin> <!-- ABAIXO PLUGINS PARA GERAR WAR --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <compilerArguments> <endorseddirs>${endorsed.dir}</endorseddirs> </compilerArguments> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.6</version> <executions> <execution> <phase>validate</phase> <goals> <goal>copy</goal> </goals> <configuration> <outputDirectory>${endorsed.dir}</outputDirectory> <silent>true</silent> <artifactItems> <artifactItem> <groupId>javax</groupId> <artifactId>javaee-endorsed-api</artifactId> <version>7.0</version> <type>jar</type> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
O arquivo pom.xml acima está bem completo, com ele podemos até gerar um war caso posteriormente fosse necessário subir sua aplicação em um container como o glassfish. Basta apenas trocar a tag “packaging” com o valor de jar para war.
Com todas as dependências configuradas vamos iniciar um servidor e já criar nossa Main.java:
/** * * @author helpdev.com.br */ public class Main { //Endereço para rodar o serviço: public static final URI SERVER_URL = URI.create("http://127.0.0.1:8080/myserver"); public static void main(String[] args) throws IOException { //Iniciando o servidor Main main = new Main(); HttpServer server = main.newServer(); server.start(); //Aguardando qualquer entrada no terminal para finalizar o servidor: System.in.read(); server.shutdownNow(); } public HttpServer newServer() { //Configura o package dos serviços WEB ResourceConfig resourceConfig = new ResourceConfig() .packages("br.com.helpdev.webserver.rest"); //Cria o serviço HTTP HttpServer server = GrizzlyHttpServerFactory .createHttpServer(SERVER_URL, resourceConfig); return server; } }
Pronto. Temos um servidor http rodando e escutando em “http://127.0.0.1:8080/myserver” (localhost). Deixamos configurado o package “br.com.helpdev.webserver.rest” para inserir nossos serviços. Agora vamos criar um serviço REST simples para testarmos:
package br.com.helpdev.webserver.rest; [...] /** * * @author helpdev.com.br */ @Path("teste") public class WebRestTest { @Context private UriInfo context; @Context private HttpHeaders headers; @GET @Produces(MediaType.TEXT_PLAIN) public String getXml() { return "</xml>"; } @POST @Path("{codOp}") @Consumes(MediaType.TEXT_PLAIN) public Response postXml(@PathParam("codOp") int codOp, String content) throws Exception { return Response.ok().build(); } }
A classe WebRestTest é um serviço REST simples com um GET e um POST o serviço está rodando no path /teste, o get vai nos retornar um texto qualquer e no post em /teste/{codOp} vamos passar um conteudo do tipo text.
Para testarmos nossa aplicação basta rodar o Main.java e executar a classe de teste:
/** * Classe para testar o web server standalone * * @author helpdev.com.br */ public class ClientTest implements AutoCloseable { private final WebTarget webTarget; private final Client client; private static final String BASE_URI = "http://127.0.0.1:8080/myserver"; public static void main(String[] args) { try (ClientTest clientTest = new ClientTest()) { System.out.println("getXml: {" + clientTest.getXml() + "}"); System.out.println("postXml: {" + clientTest.postXml("abc", "1") + "}"); } } public ClientTest() { client = javax.ws.rs.client.ClientBuilder.newClient(); webTarget = client.target(BASE_URI).path("teste"); } public String getXml() throws ClientErrorException { WebTarget resource = webTarget; return resource.request(javax.ws.rs.core.MediaType.TEXT_PLAIN).get(String.class); } public Response postXml(Object requestEntity, String codOp) throws ClientErrorException { return webTarget.path(java.text.MessageFormat.format("{0}", new Object[]{codOp})).request(javax.ws.rs.core.MediaType.TEXT_PLAIN).post(javax.ws.rs.client.Entity.entity(requestEntity, javax.ws.rs.core.MediaType.TEXT_PLAIN), Response.class); } public void close() { client.close(); }
Para mais informações o projeto se encontra no nosso GITHUB: https://github.com/gbzarelli/JavaSample-WebServerStandalone