Java tutorial
/* * Copyright (c) 2016. The original author or authors * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 * which accompanies this distribution. * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under the above mentioned license. */ package org.mustertech.webapp.vertxutils; import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.Iterator; import org.apache.commons.io.IOUtils; import org.jdeferred.Deferred; import org.jdeferred.DeferredManager; import org.jdeferred.DoneCallback; import org.jdeferred.FailCallback; import org.jdeferred.Promise; import org.jdeferred.impl.DefaultDeferredManager; import org.jdeferred.impl.DeferredObject; import org.jdeferred.multiple.MultipleResults; import org.jdeferred.multiple.OneReject; import org.jdeferred.multiple.OneResult; import io.vertx.core.json.JsonArray; import io.vertx.core.AsyncResult; import io.vertx.core.DeploymentOptions; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.json.JsonObject; /* * Represents verticle deployment helper class. * <p> * Any vert.x based projects using verticles, can import this module. Typical and recommended usage is, * to create a verticle named "AppVerticle" for your project and use this class to deploy rest of * the verticles using a deployment specification json file. The json file can be passed as command line * argument with the vert.x's -conf option. * <p> * The required format of json deployment configuration file follows json-schema as defined in deploy-schema.json */ public final class VerticleDeployer { private static Vertx vertx = null; /* * Create an AsyncResult object and return it, for a generic type T * * @param cause An object of type Throwable * @param result A generic type object * @return AsyncResult object */ private static <T> AsyncResult<T> makeAsyncResult(Throwable cause, T result) { AsyncResult<T> ar; if (null != cause) { ar = new AsyncResult<T>() { public Throwable cause() { return cause; } public boolean failed() { return true; } public T result() { return null; } public boolean succeeded() { return false; } }; } else { ar = new AsyncResult<T>() { public Throwable cause() { return null; } public boolean failed() { return false; } public T result() { return result; } public boolean succeeded() { return true; } }; } return ar; } /* * Deploy a verticle with given deployment configuration * * @param opt Json object representing the verticle deployment configuration * @return Promise object * */ private static Promise<JsonObject, Exception, Double> deployWithOpts(JsonObject opt) { Deferred<JsonObject, Exception, Double> deffered = new DeferredObject<JsonObject, Exception, Double>(); DeploymentOptions deployOpts = new DeploymentOptions(); // Check and set Config option if (opt.containsKey("config")) { JsonObject vertCfg = opt.getJsonObject("config"); deployOpts.setConfig(vertCfg); } // Check and set ExtraClasspath option if (opt.containsKey("extCps")) { JsonArray extCps = opt.getJsonArray("extCps"); Iterator<Object> cpIter = extCps.iterator(); ArrayList<String> extCpsList = new ArrayList<String>(); while (cpIter.hasNext()) { extCpsList.add((String) cpIter.next()); } deployOpts.setExtraClasspath(extCpsList); } // Check and set Isolated-Group option if (opt.containsKey("isolatedGrp")) { deployOpts.setIsolationGroup(opt.getString("isolatedGrp")); } // Check and set Isolated-Classes option if (opt.containsKey("isolatedCls")) { JsonArray isoCls = opt.getJsonArray("isolatedCls"); Iterator<Object> clsIter = isoCls.iterator(); ArrayList<String> isoClsList = new ArrayList<String>(); while (clsIter.hasNext()) { isoClsList.add((String) clsIter.next()); } deployOpts.setIsolatedClasses(isoClsList); } // Check and set HA option deployOpts.setHa(opt.containsKey("isHa") && opt.getBoolean("isHa")); // Check and set instances option deployOpts.setInstances(opt.containsKey("nInst") ? opt.getInteger("nInst").intValue() : 1); // Check and set Worker/MT option Boolean isWorker = (opt.containsKey("isWorker") && opt.getBoolean("isWorker")); if (isWorker) { deployOpts.setWorker(true); deployOpts.setMultiThreaded(opt.containsKey("isMt") && opt.getBoolean("isMt")); } String vertName = opt.getString("name"); // Finally, deploy the verticle vertx.deployVerticle(vertName, deployOpts, ar -> { if (ar.succeeded()) { JsonObject resObj = new JsonObject(); resObj.put("verticleName", vertName).put("deployId", ar.result()); deffered.resolve(resObj); } else { Throwable thr = ar.cause(); String defErr = vertName + " => Could not be deployed!"; deffered.reject( (null != thr.getMessage()) ? new Exception(thr.getMessage()) : new Exception(defErr)); } }); return deffered.promise(); } /* * Method to deploy a set of verticles based on deployment configuration file * * @param vertx Vertx instance being used to deploy the verticle(s) * @param cfgJson String representation of the Json object defining the deployment configuration * @param handler AsyncResult handler which can be called to indicate the completion of deployment */ public static void deploy(final Vertx vertx, final String cfgJson, Handler<AsyncResult<JsonObject>> handler) { if (null == vertx) { NullPointerException e = new NullPointerException("NULL vertxutils instance is passed!"); handler.handle(makeAsyncResult(e, null)); return; } // Store the vertx instance VerticleDeployer.vertx = vertx; try { InputStream schStream = VerticleDeployer.class.getResourceAsStream("/schema/deploy-schema.json"); StringWriter strWriter = new StringWriter(); IOUtils.copy(schStream, strWriter, "UTF-8"); JsonValidator.validateJson(strWriter.toString(), cfgJson); IOUtils.closeQuietly(schStream); JsonObject cfgObj = new JsonObject(cfgJson); JsonObject globalCfg = null; JsonObject optObj = null, optCfg = null; JsonArray deployOpts = cfgObj.getJsonArray("deployOpts"); int optsLen = deployOpts.size(); ArrayList<Promise<JsonObject, Exception, Double>> promises = new ArrayList<Promise<JsonObject, Exception, Double>>(); if (cfgObj.containsKey("globalConf")) { globalCfg = cfgObj.getJsonObject("globalConf"); } for (int idx = 0; idx < optsLen; idx++) { optObj = (JsonObject) deployOpts.getJsonObject(idx); if (cfgObj.containsKey("appendGlobal") && cfgObj.getBoolean("appendGlobal")) { if (optObj.containsKey("config")) { optCfg = optObj.getJsonObject("config"); if (!optCfg.containsKey("global")) { optCfg.put("global", globalCfg); } } else { optCfg = new JsonObject(); optCfg.put("global", globalCfg); optObj.put("config", optCfg); } } promises.add(deployWithOpts(optObj)); } DeferredManager defMgr = new DefaultDeferredManager(); defMgr.when(promises.toArray(new Promise[] {})).done(new DoneCallback<MultipleResults>() { public void onDone(MultipleResults results) { JsonArray resArr = new JsonArray(); Iterator<OneResult> oneResIter = results.iterator(); while (oneResIter.hasNext()) { resArr.add(oneResIter.next().getResult()); } JsonObject resObj = new JsonObject(); resObj.put("deployInfo", resArr); handler.handle(makeAsyncResult(null, resObj)); } }).fail(new FailCallback<OneReject>() { public void onFail(OneReject err) { handler.handle(makeAsyncResult((Throwable) err.getReject(), null)); } }); } catch (Exception e) { handler.handle(makeAsyncResult(e, null)); } } }