Saturday, February 4, 2017

Deploy application on Wildfly using Java and REST

Prerequisite

  • Download Wildfly 10.1.0
  • Add management user
  • Run Wildfly
  • Download sample appliaction hellojee.war
First let's create shell script which redeploys application on Wildfly
#!/bin/bash
echo "Undeploy old war"
curl -k -S -H "content-Type: application/json" -d '{"operation":"undeploy", "address":[{"deployment":"hellojee.war"}]}' --digest http://admin:admin@localhost:9990/management
echo ""

echo "Remove old war"
curl -k -S -H "content-Type: application/json" -d '{"operation":"remove", "address":[{"deployment":"hellojee.war"}]}' --digest http://admin:admin@localhost:9990/management
echo ""

echo "Upload new war"
bytes_value=`curl -k -F "file=@hellojee.war" --digest http://admin:admin@localhost:9990/management/add-content | perl -pe 's/^.*"BYTES_VALUE"\s*:\s*"(.*)".*$/$1/'`
echo $bytes_value

json_string_start='{"content":[{"hash": {"BYTES_VALUE" : "'
json_string_end='"}}], "address": [{"deployment":"hellojee.war"}], "operation":"add", "enabled":"true"}'
json_string="$json_string_start$bytes_value$json_string_end"

echo "Deploy new war"
result=`curl -k -S -H "Content-Type: application/json" -d "$json_string" --digest http://admin:admin@localhost:9990/management | perl -pe 's/^.*"outcome"\s*:\s*"(.*)".*$/$1/'`
echo $result

if [ "$result" != "success" ]; then
  exit -1
fi
Now let's do it in Java. Create maven project and add jersey dependencies
<?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">
 <modelVersion>4.0.0</modelVersion>

 <groupId>pl.andrzejszywala</groupId>
 <artifactId>wfdep</artifactId>
 <version>0.0.1-SNAPSHOT</version>

 <packaging>jar</packaging>

 <name>wfdep</name>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
  </dependency>

  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-client</artifactId>
   <version>2.23</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.json</artifactId>
   <version>1.0.4</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-json-processing</artifactId>
   <version>2.23</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-multipart</artifactId>
   <version>2.23</version>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>
Create new rest client
package pl.andrzejszywala.wfdep;

import static javax.json.Json.createArrayBuilder;
import static javax.json.Json.createObjectBuilder;
import static javax.ws.rs.client.Entity.json;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Logger;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;

public class DeploymentEngine {
  private static final Logger logger = Logger.getLogger(DeploymentEngine.class.getName());
  private String host;
  private String path;
  private String user;
  private String password;
  private String file;

  public DeploymentEngine(String host, String path, String user, String password) {
    super();
    this.host = host;
    this.path = path;
    this.file = new File(this.path).getName();
    this.user = user;
    this.password = password;
  }
  
  public String deploy() throws IOException  {
    undeploy();
    remove();
    return enable(add());
  }
  
  private String enable(JsonValue hash)  {
    String result = null;
    logger.info("Starting");
    Response post = newClient()
        .target(host + "/management")
        .request()
          .post(json(createObjectBuilder()
              .add("operation", "add")
              .add("enabled", "true")
              .add("content", createArrayBuilder()
                        .add(createObjectBuilder()
                            .add("hash", createObjectBuilder().add("BYTES_VALUE", hash))))
              .add("address", createArrayBuilder()
                              .add(createObjectBuilder().add("deployment", file))).build()));
    result = post.readEntity(String.class);
    logger.info(result);
    return result;
  }

  private  void undeploy() {
    logger.info("Undeploying");
    Response post = newClient()
      .target(host + "/management")
      .request()
        .post(json(createObjectBuilder()
            .add("operation", "undeploy")
            .add("address", createArrayBuilder()
                .add(createObjectBuilder().add("deployment", file))).build()));
    logger.info(post.readEntity(String.class));
  }
  
  private  void remove() {
    logger.info("Removeing");
    Response post = newClient()
      .target(host + "/management")
      .request()
        .post(json(createObjectBuilder()
            .add("operation", "remove")
            .add("address", createArrayBuilder()
                .add(createObjectBuilder().add("deployment", file))).build()));
    logger.info(post.readEntity(String.class));
  }
  
  private JsonValue add() throws IOException  {
    logger.info("Adding");
    final FileDataBodyPart filePart = new FileDataBodyPart("file", new File(path));
     
    try (MultiPart multiPart = new FormDataMultiPart()) {
      multiPart.bodyPart(filePart);
      Response post = newClient()
        .target(host + "/management/add-content")
        .request(APPLICATION_JSON_TYPE)
          .post(Entity.entity(multiPart, multiPart.getMediaType()));
      String entity = post.readEntity(String.class);
      logger.info(entity);
      JsonReader reader = Json.createReader(new StringReader(entity));
      JsonObject jo = (JsonObject) reader.read();
      logger.info("" + jo);
      return ((JsonObject)jo.get("result")).get("BYTES_VALUE");
    }
  }

  public Client newClient()  {    
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.register(HttpAuthenticationFeature.digest(user, password.getBytes()));
    clientConfig.register(MultiPartFeature.class);
    return ClientBuilder.newBuilder().withConfig(clientConfig).build();
  }
}
Source code for this blog post is available on github