From 195755e59b1ea06c399c232c7859aa5555b81274 Mon Sep 17 00:00:00 2001 From: nmihajlovski Date: Mon, 5 Dec 2016 20:54:53 +0100 Subject: [PATCH] Reactively applying API and Proxy configuration changes. --- .../org/rapidoid/config/ConfigChanges.java | 13 ++- .../src/main/resources/rapidoid-classes.txt | 2 + .../org/rapidoid/setup/APIConfigListener.java | 88 +++++++++++++++++++ .../src/main/java/org/rapidoid/setup/App.java | 65 +------------- .../rapidoid/setup/ProxyConfigListener.java | 52 +++++++++++ 5 files changed, 157 insertions(+), 63 deletions(-) create mode 100644 rapidoid-http-server/src/main/java/org/rapidoid/setup/APIConfigListener.java create mode 100644 rapidoid-http-server/src/main/java/org/rapidoid/setup/ProxyConfigListener.java diff --git a/rapidoid-commons/src/main/java/org/rapidoid/config/ConfigChanges.java b/rapidoid-commons/src/main/java/org/rapidoid/config/ConfigChanges.java index 4e4648cc68..08a9d0f397 100644 --- a/rapidoid-commons/src/main/java/org/rapidoid/config/ConfigChanges.java +++ b/rapidoid-commons/src/main/java/org/rapidoid/config/ConfigChanges.java @@ -86,14 +86,23 @@ public int count() { return added.size() + changed.size() + removed.size(); } - public Map added(Class type) { + public Map getAddedAs(Class type) { return Coll.toBeanMap(added, type); } - public Map changed(Class type) { + public Map getChangedAs(Class type) { return Coll.toBeanMap(changed, type); } + public Map getAddedOrChangedAs(Class type) { + Map addedOrChanged = U.map(); + + addedOrChanged.putAll(added); + addedOrChanged.putAll(changed); + + return Coll.toBeanMap(addedOrChanged, type); + } + @Override public String toString() { return "ConfigChanges{" + diff --git a/rapidoid-commons/src/main/resources/rapidoid-classes.txt b/rapidoid-commons/src/main/resources/rapidoid-classes.txt index e0aa304e9c..9cec8f0a5f 100644 --- a/rapidoid-commons/src/main/resources/rapidoid-classes.txt +++ b/rapidoid-commons/src/main/resources/rapidoid-classes.txt @@ -653,6 +653,7 @@ org.rapidoid.serialize.Serialize org.rapidoid.serialize.TypeSpecificDeserializer org.rapidoid.serialize.TypeSpecificSerializer org.rapidoid.setup.Admin +org.rapidoid.setup.APIConfigListener org.rapidoid.setup.App org.rapidoid.setup.AppBootstrap org.rapidoid.setup.AppRestartListener @@ -666,6 +667,7 @@ org.rapidoid.setup.OnChanges org.rapidoid.setup.OnError org.rapidoid.setup.OnRoute org.rapidoid.setup.PojoHandlersSetup +org.rapidoid.setup.ProxyConfigListener org.rapidoid.setup.ReloadUtil org.rapidoid.setup.ServiceActivator org.rapidoid.setup.ServiceBootstrap diff --git a/rapidoid-http-server/src/main/java/org/rapidoid/setup/APIConfigListener.java b/rapidoid-http-server/src/main/java/org/rapidoid/setup/APIConfigListener.java new file mode 100644 index 0000000000..4eb46e295b --- /dev/null +++ b/rapidoid-http-server/src/main/java/org/rapidoid/setup/APIConfigListener.java @@ -0,0 +1,88 @@ +package org.rapidoid.setup; + +/* + * #%L + * rapidoid-http-server + * %% + * Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.rapidoid.RapidoidThing; +import org.rapidoid.annotation.Authors; +import org.rapidoid.annotation.Since; +import org.rapidoid.config.ConfigChanges; +import org.rapidoid.config.bean.APIConfig; +import org.rapidoid.http.HttpVerb; +import org.rapidoid.http.Req; +import org.rapidoid.http.ReqRespHandler; +import org.rapidoid.http.Resp; +import org.rapidoid.jdbc.JDBC; +import org.rapidoid.lambda.Operation; +import org.rapidoid.u.U; + +import java.util.Map; + +@Authors("Nikolche Mihajlovski") +@Since("5.3.0") +public class APIConfigListener extends RapidoidThing implements Operation { + + @Override + public void execute(ConfigChanges changes) throws Exception { + for (Map.Entry e : changes.getAddedOrChangedAs(APIConfig.class).entrySet()) { + + String apiKey = e.getKey().trim(); + APIConfig api = e.getValue(); + + applyAPIEntry(apiKey, api); + } + } + + private void applyAPIEntry(String apiKey, final APIConfig api) { + String[] verbUri = apiKey.split("\\s+"); + + final HttpVerb verb; + String uri; + + if (verbUri.length == 1) { + verb = HttpVerb.GET; + uri = verbUri[0]; + + } else if (verbUri.length == 2) { + verb = HttpVerb.from(verbUri[0]); + uri = verbUri[1]; + + } else { + throw U.rte("Invalid route!"); + } + + addApiHandler(api, verb, uri); + } + + private void addApiHandler(final APIConfig api, final HttpVerb verb, String uri) { + On.route(verb.name(), uri).json(new ReqRespHandler() { + @Override + public Object execute(Req req, Resp resp) throws Exception { + if (verb == HttpVerb.GET) { + return JDBC.query(api.sql); + } else { + int changes = JDBC.execute(api.sql); + return U.map("success", true, "changes", changes); // FIXME improve + } + } + }); + } + +} diff --git a/rapidoid-http-server/src/main/java/org/rapidoid/setup/App.java b/rapidoid-http-server/src/main/java/org/rapidoid/setup/App.java index f124201e2d..70aa3b485f 100644 --- a/rapidoid-http-server/src/main/java/org/rapidoid/setup/App.java +++ b/rapidoid-http-server/src/main/java/org/rapidoid/setup/App.java @@ -27,19 +27,12 @@ import org.rapidoid.commons.Arr; import org.rapidoid.config.Conf; import org.rapidoid.config.ConfigHelp; -import org.rapidoid.config.bean.APIConfig; -import org.rapidoid.config.bean.ProxyConfig; import org.rapidoid.data.JSON; import org.rapidoid.env.Env; -import org.rapidoid.http.HttpVerb; -import org.rapidoid.http.Req; -import org.rapidoid.http.ReqRespHandler; -import org.rapidoid.http.Resp; import org.rapidoid.io.Res; import org.rapidoid.ioc.Beans; import org.rapidoid.ioc.IoC; import org.rapidoid.ioc.IoCContext; -import org.rapidoid.jdbc.JDBC; import org.rapidoid.job.Jobs; import org.rapidoid.log.Log; import org.rapidoid.render.Templates; @@ -51,7 +44,6 @@ import org.rapidoid.util.Msc; import java.util.List; -import java.util.Map; import java.util.Set; @Authors("Nikolche Mihajlovski") @@ -102,65 +94,16 @@ public static AppBootstrap run(String[] args, String... extraArgs) { public static AppBootstrap boot() { Jobs.initialize(); - bootstrapProxy(); - bootstrapAPI(); + registerConfigListeners(); AppBootstrap bootstrap = new AppBootstrap(); bootstrap.services(); return bootstrap; } - private static void bootstrapProxy() { - if (!Conf.PROXY.isEmpty()) { - for (Map.Entry e : Conf.PROXY.toMap(ProxyConfig.class).entrySet()) { - String uri = e.getKey(); - ProxyConfig proxy = e.getValue(); - Reverse.proxy().map(uri).to(proxy.upstream.split("\\s*\\,\\s*")); - } - } - } - - private static void bootstrapAPI() { - if (!Conf.API.isEmpty()) { - for (Map.Entry e : Conf.API.toMap(APIConfig.class).entrySet()) { - - String apiKey = e.getKey().trim(); - APIConfig api = e.getValue(); - - applyAPIEntry(apiKey, api); - } - } - } - - private static void applyAPIEntry(String apiKey, final APIConfig api) { - String[] verbUri = apiKey.split("\\s+"); - - final HttpVerb verb; - String uri; - - if (verbUri.length == 1) { - verb = HttpVerb.GET; - uri = verbUri[0]; - - } else if (verbUri.length == 2) { - verb = HttpVerb.from(verbUri[0]); - uri = verbUri[1]; - - } else { - throw U.rte("Invalid route!"); - } - - On.route(verb.name(), uri).json(new ReqRespHandler() { - @Override - public Object execute(Req req, Resp resp) throws Exception { - if (verb == HttpVerb.GET) { - return JDBC.query(api.sql); - } else { - int changes = JDBC.execute(api.sql); - return U.map("success", true, "changes", changes); // FIXME improve - } - } - }); + private static void registerConfigListeners() { + Conf.PROXY.addChangeListener(new ProxyConfigListener()); + Conf.API.addChangeListener(new APIConfigListener()); } public static void profiles(String... profiles) { diff --git a/rapidoid-http-server/src/main/java/org/rapidoid/setup/ProxyConfigListener.java b/rapidoid-http-server/src/main/java/org/rapidoid/setup/ProxyConfigListener.java new file mode 100644 index 0000000000..2620bec5f4 --- /dev/null +++ b/rapidoid-http-server/src/main/java/org/rapidoid/setup/ProxyConfigListener.java @@ -0,0 +1,52 @@ +package org.rapidoid.setup; + +/* + * #%L + * rapidoid-http-server + * %% + * Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.rapidoid.RapidoidThing; +import org.rapidoid.annotation.Authors; +import org.rapidoid.annotation.Since; +import org.rapidoid.config.ConfigChanges; +import org.rapidoid.config.bean.ProxyConfig; +import org.rapidoid.lambda.Operation; +import org.rapidoid.reverseproxy.Reverse; + +import java.util.Map; + +@Authors("Nikolche Mihajlovski") +@Since("5.3.0") +public class ProxyConfigListener extends RapidoidThing implements Operation { + + @Override + public void execute(ConfigChanges changes) throws Exception { + for (Map.Entry e : changes.getAddedOrChangedAs(ProxyConfig.class).entrySet()) { + + String uri = e.getKey().trim(); + ProxyConfig proxy = e.getValue(); + + applyProxyEntry(uri, proxy); + } + } + + private void applyProxyEntry(String uri, ProxyConfig proxy) { + Reverse.proxy().map(uri).to(proxy.upstream.split("\\s*\\,\\s*")); + } + +}