Author: rmannibucau
Date: Thu Jun 1 10:01:22 2017
New Revision: 1797174
URL: http://svn.apache.org/viewvc?rev=1797174&view=rev
Log:
MEECROWAVE-31 basic reload controller
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/ReloadOnChangeController.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/WatcherTest.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/superbiz/app/Bounced.java
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/startup/MeecrowaveContextConfig.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveExtension.java
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveTask.java
openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/startup/MeecrowaveContextConfig.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/startup/MeecrowaveContextConfig.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/startup/MeecrowaveContextConfig.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/startup/MeecrowaveContextConfig.java
Thu Jun 1 10:01:22 2017
@@ -18,10 +18,13 @@
*/
package org.apache.catalina.startup;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.WebResource;
import org.apache.meecrowave.Meecrowave;
import org.apache.meecrowave.logging.tomcat.LogFacade;
import org.apache.meecrowave.openwebbeans.OWBTomcatWebScannerService;
+import org.apache.meecrowave.watching.ReloadOnChangeController;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.descriptor.web.WebXml;
import org.apache.webbeans.config.WebBeansContext;
@@ -48,6 +51,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
+import static java.util.Collections.emptySet;
import static java.util.Optional.ofNullable;
public class MeecrowaveContextConfig extends ContextConfig {
@@ -56,11 +60,14 @@ public class MeecrowaveContextConfig ext
private final Meecrowave.Builder configuration;
private final Map<String, Collection<Class<?>>> webClasses = new
HashMap<>();
private final boolean fixDocBase;
+ private final ServletContainerInitializer intializer;
private OwbAnnotationFinder finder;
+ private ReloadOnChangeController watcher;
- public MeecrowaveContextConfig(final Meecrowave.Builder configuration,
final boolean fixDocBase) {
+ public MeecrowaveContextConfig(final Meecrowave.Builder configuration,
final boolean fixDocBase, final ServletContainerInitializer intializer) {
this.configuration = configuration;
this.fixDocBase = fixDocBase;
+ this.intializer= intializer;
}
@Override
@@ -73,6 +80,11 @@ public class MeecrowaveContextConfig ext
@Override
protected void webConfig() {
+ if
(context.getServletContext().getAttribute("meecrowave.configuration") == null)
{ // redeploy
+
context.getServletContext().setAttribute("meecrowave.configuration",
configuration);
+ context.addServletContainerInitializer(intializer, emptySet());
+ }
+
if (!configuration.isTomcatScanning()) {
super.webConfig();
return;
@@ -88,6 +100,10 @@ public class MeecrowaveContextConfig ext
scannerService.setFilter(ofNullable(context.getJarScanner()).map(JarScanner::getJarScanFilter).orElse(null),
context.getServletContext());
scannerService.setDocBase(context.getDocBase());
scannerService.setShared(configuration.getSharedLibraries());
+ if (configuration.getWatcherBouncing() > 0) { // note that caching
should be disabled with this config in most of the times
+ watcher = new ReloadOnChangeController(context,
configuration.getWatcherBouncing());
+ scannerService.setFileVisitor(f -> watcher.register(f));
+ }
scannerService.scan();
finder = scannerService.getFinder();
finder.link();
@@ -111,6 +127,18 @@ public class MeecrowaveContextConfig ext
}
}
+ @Override
+ public void lifecycleEvent(final LifecycleEvent event) {
+ super.lifecycleEvent(event);
+ if (watcher != null && watcher.shouldRun()) {
+ if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+ watcher.start();
+ } else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
+ watcher.close();
+ }
+ }
+ }
+
@Override // just to avoid an info log pretty useless for us
protected InputSource getGlobalWebXmlSource() {
return ofNullable(super.getGlobalWebXmlSource()).orElse(new
InputSource(new ByteArrayInputStream(DEFAULT_WEB_XML)));
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
Thu Jun 1 10:01:22 2017
@@ -248,32 +248,9 @@ public class Meecrowave implements AutoC
throw new IllegalArgumentException(e);
}
});
- ctx.addLifecycleListener(new MeecrowaveContextConfig(configuration,
meta.docBase != null));
- ctx.addLifecycleListener(event -> {
- switch (event.getType()) {
- case Lifecycle.AFTER_START_EVENT:
-
ctx.getResources().setCachingAllowed(configuration.webResourceCached);
- break;
- case Lifecycle.BEFORE_INIT_EVENT:
-
ctx.getServletContext().setAttribute("meecrowave.configuration", configuration);
- if (configuration.loginConfig != null) {
- ctx.setLoginConfig(configuration.loginConfig.build());
- }
- for (final SecurityConstaintBuilder sc :
configuration.securityConstraints) {
- ctx.addConstraint(sc.build());
- }
- if (configuration.webXml != null) {
-
ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.webXml);
- }
- break;
- default:
- }
-
- });
- ctx.addLifecycleListener(new Tomcat.FixContextListener()); // after
having configured the security!!!
final AtomicReference<Runnable> releaseSCI = new AtomicReference<>();
- ctx.addServletContainerInitializer((c, ctx1) -> {
+ final ServletContainerInitializer meecrowaveInitializer = (c, ctx1) ->
{
new OWBAutoSetup().onStartup(c, ctx1);
new CxfCdiAutoSetup().onStartup(c, ctx1);
new TomcatAutoInitializer().onStartup(c, ctx1);
@@ -313,7 +290,33 @@ public class Meecrowave implements AutoC
}
}));
}
- }, emptySet());
+ };
+
+ ctx.addLifecycleListener(new MeecrowaveContextConfig(configuration,
meta.docBase != null, meecrowaveInitializer));
+ ctx.addLifecycleListener(event -> {
+ switch (event.getType()) {
+ case Lifecycle.AFTER_START_EVENT:
+
ctx.getResources().setCachingAllowed(configuration.webResourceCached);
+ break;
+ case Lifecycle.BEFORE_INIT_EVENT:
+
ctx.getServletContext().setAttribute("meecrowave.configuration", configuration);
+ if (configuration.loginConfig != null) {
+ ctx.setLoginConfig(configuration.loginConfig.build());
+ }
+ for (final SecurityConstaintBuilder sc :
configuration.securityConstraints) {
+ ctx.addConstraint(sc.build());
+ }
+ if (configuration.webXml != null) {
+
ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.webXml);
+ }
+ break;
+ default:
+ }
+
+ });
+ ctx.addLifecycleListener(new Tomcat.FixContextListener()); // after
having configured the security!!!
+
+ ctx.addServletContainerInitializer(meecrowaveInitializer, emptySet());
if (configuration.isUseTomcatDefaults()) {
ctx.setSessionTimeout(30);
@@ -836,6 +839,9 @@ public class Meecrowave implements AutoC
@CliOption(name = "java9-skip-workarounds", description = "Should the
java9 workarounds be skipped, default to false if on java 9")
private boolean java9SkipWorkarounds = true;
+ @CliOption(name = "watcher-bouncing", description = "Activate
redeployment on directories update using this bouncing.")
+ private int watcherBouncing = 500;
+
@CliOption(name = "http", description = "HTTP port")
private int httpPort = 8080;
@@ -1061,6 +1067,14 @@ public class Meecrowave implements AutoC
}));
}
+ public int getWatcherBouncing() {
+ return watcherBouncing;
+ }
+
+ public void setWatcherBouncing(final int watcherBouncing) {
+ this.watcherBouncing = watcherBouncing;
+ }
+
public String getTomcatAccessLogPattern() {
return tomcatAccessLogPattern;
}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
Thu Jun 1 10:01:22 2017
@@ -29,7 +29,9 @@ import org.apache.xbean.finder.Annotatio
import org.apache.xbean.finder.filter.Filter;
import javax.servlet.ServletContext;
+import java.io.Closeable;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -39,6 +41,7 @@ import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.stream.Stream;
import static java.util.Optional.of;
@@ -46,7 +49,7 @@ import static java.util.Optional.ofNulla
import static java.util.stream.Collectors.toSet;
import static org.apache.tomcat.JarScanType.PLUGGABILITY;
-public class OWBTomcatWebScannerService extends WebScannerService {
+public class OWBTomcatWebScannerService extends WebScannerService implements
Closeable {
private final LogFacade logger = new
LogFacade(OWBTomcatWebScannerService.class.getName());
private JarScanFilter filter;
@@ -56,6 +59,7 @@ public class OWBTomcatWebScannerService
private final Set<String> urls = new HashSet<>();
private String docBase;
private String shared;
+ private Consumer<File> fileVisitor;
@Override
public void init(final Object context) {
@@ -103,6 +107,14 @@ public class OWBTomcatWebScannerService
return shownValue;
}).sorted().forEach(v -> logger.info(" " + v));
+
+ if (fileVisitor != null) {
+ urls.stream()
+ .filter(this::isFile)
+ .map(this::toFile)
+ .filter(File::isDirectory)
+ .forEach(fileVisitor);
+ }
}
urls.clear(); // no more needed
filter = null;
@@ -110,6 +122,18 @@ public class OWBTomcatWebScannerService
shared = null;
}
+ private File toFile(final String url) {
+ try {
+ return new File(new URL(url).getFile());
+ } catch (final MalformedURLException e) {
+ return new File(url.substring("file://".length(), url.length()));
+ }
+ }
+
+ private boolean isFile(final String url) {
+ return url.startsWith("file:") && !url.endsWith("!/") &&
!url.endsWith("!/META-INF/beans.xml");
+ }
+
private void scanGroovy(final ClassLoader currentClassLoader) {
if (currentClassLoader == null ||
!currentClassLoader.getClass().getName().equals("groovy.lang.GroovyClassLoader"))
{
return;
@@ -243,4 +267,13 @@ public class OWBTomcatWebScannerService
public void setDocBase(final String docBase) {
this.docBase = docBase;
}
+
+ @Override
+ public void close() throws IOException {
+
+ }
+
+ public void setFileVisitor(final Consumer<File> fileVisitor) {
+ this.fileVisitor = fileVisitor;
+ }
}
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/ReloadOnChangeController.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/ReloadOnChangeController.java?rev=1797174&view=auto
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/ReloadOnChangeController.java
(added)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/watching/ReloadOnChangeController.java
Thu Jun 1 10:01:22 2017
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.meecrowave.watching;
+
+import org.apache.catalina.Context;
+import org.apache.meecrowave.logging.tomcat.LogFacade;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Arrays.asList;
+
+public class ReloadOnChangeController implements AutoCloseable, Runnable {
+ private final Context context;
+ private final long bouncing;
+ private final Collection<Path> paths = new ArrayList<>();
+ private WatchService watchService;
+ private Thread bouncer;
+ private Thread watcher;
+ private volatile boolean running = true;
+ private volatile long redeployMarker = System.currentTimeMillis();
+
+ public ReloadOnChangeController(final Context context, final int
watcherBouncing) {
+ this.context = context;
+ this.bouncing = (long) watcherBouncing;
+ }
+
+ public void register(final File folder) {
+ paths.add(folder.toPath());
+ }
+
+ public void start() {
+ if (paths.isEmpty()) {
+ return;
+ }
+ try {
+ watchService =
paths.iterator().next().getFileSystem().newWatchService(); // assuming all
share the same FS
+ for (final Path p : paths) {
+ p.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
+ StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);
+ }
+ } catch (final IOException ex) {
+ new LogFacade(ReloadOnChangeController.class.getName())
+ .warn("Hot reloading will not be available", ex);
+ }
+
+ watcher = new Thread(this);
+ watcher.setName("meecrowave-watcher-controller");
+ watcher.start();
+ }
+
+ protected synchronized void redeploy() {
+ context.reload();
+ }
+
+ @Override
+ public void close() {
+ running = false;
+ final long waitMs = bouncing * 2 + 5000 /*margin if redeploying, we
can make it configurable later*/;
+ try {
+ bouncer.join(waitMs);
+ } catch (final InterruptedException e) {
+ Thread.interrupted();
+ }
+ try {
+ watcher.join(waitMs);
+ } catch (final InterruptedException e) {
+ Thread.interrupted();
+ }
+ }
+
+ public boolean shouldRun() {
+ return !paths.isEmpty();
+ }
+
+ @Override
+ public void run() {
+ if (watchService == null) {
+ return;
+ }
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ bouncer = new Thread(() -> { // simple bouncing impl
+ long last = redeployMarker;
+ latch.countDown();
+
+ boolean needsRedeploy = false;
+ long antepenultiem = -1;
+ while (running) {
+ if (redeployMarker > last) {
+ antepenultiem = last;
+ last = redeployMarker;
+ needsRedeploy = true;
+ } else if (needsRedeploy) {
+ antepenultiem = last;
+ }
+
+ try {
+ Thread.sleep(bouncing);
+ } catch (final InterruptedException e) {
+ Thread.interrupted();
+ break;
+ }
+
+ if (needsRedeploy && last == antepenultiem) {
+ redeploy();
+ }
+ }
+ });
+ bouncer.setName("meecrowave-watcher-redeployer");
+ bouncer.start();
+ try {
+ latch.await(1, TimeUnit.MINUTES);
+ } catch (final InterruptedException e) {
+ Thread.interrupted();
+ return;
+ }
+
+ paths.forEach(p -> {
+ try {
+ Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs) throws IOException {
+ dir.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (final IOException e) {
+ new
LogFacade(ReloadOnChangeController.class.getName()).warn(e.getMessage());
+ }
+ });
+
+ try {
+ while (running) {
+ final WatchKey watchKey = watchService.poll(bouncing,
TimeUnit.MILLISECONDS);
+ if (watchKey == null) {
+ Thread.sleep(bouncing);
+ continue;
+ }
+
+ boolean foundNew = false;
+ for (final WatchEvent<?> event : watchKey.pollEvents()) {
+ final Path path = Path.class.cast(event.context());
+ final WatchEvent.Kind<?> kind = event.kind();
+ if (!isIgnored(kind, path)) {
+ foundNew = true;
+
+ final File file = path.toAbsolutePath().toFile();
+ if (file.isDirectory()) {
+ if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
+ try {
+ path.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
+
StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
+ } catch (final IOException e) {
+ new
LogFacade(ReloadOnChangeController.class.getName()).warn(e.getMessage());
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (foundNew) {
+ redeployMarker = System.nanoTime();
+ }
+
+ if (!watchKey.reset()) { // deletion
+ watchKey.cancel();
+ }
+ }
+ } catch (final InterruptedException ie) {
+ Thread.interrupted();
+ }
+ }
+
+ private boolean isIgnored(final WatchEvent.Kind<?> kind, final Path path) {
+ final String pathStr = path.toString();
+ return pathStr.endsWith("___jb_tmp___") ||
pathStr.endsWith("___jb_old___") || pathStr.endsWith("~") ||
isResource(pathStr);
+ }
+
+ private boolean isResource(final String pathStr) {
+ final int idx = pathStr.lastIndexOf('.');
+ return idx > 0 && asList(".html", ".xhtml", ".js", ".ts", ".css",
".png", ".svg", ".jpg", ".jpeg").contains(pathStr.substring(idx));
+ }
+}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
Thu Jun 1 10:01:22 2017
@@ -22,6 +22,7 @@ import org.apache.cxf.helpers.FileUtils;
import org.apache.meecrowave.io.IO;
import org.apache.meecrowave.runner.cli.CliOption;
import org.junit.Test;
+import org.superbiz.app.Bounced;
import org.superbiz.app.Endpoint;
import org.superbiz.app.RsApp;
@@ -116,7 +117,7 @@ public class MeecrowaveTest {
assertEquals("simple", slurp(new URL("http://localhost:" +
meecrowave.getConfiguration().getHttpPort() + "/api/test")));
assertEquals("simplefiltertrue", slurp(new URL("http://localhost:"
+ meecrowave.getConfiguration().getHttpPort() + "/filter")));
assertEquals(
- "sci:" + Endpoint.class.getName() + RsApp.class.getName(),
+ "sci:" + Bounced.class.getName() +
Endpoint.class.getName() + RsApp.class.getName(),
slurp(new URL("http://localhost:" +
meecrowave.getConfiguration().getHttpPort() + "/sci")));
} catch (final IOException e) {
fail(e.getMessage());
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/WatcherTest.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/WatcherTest.java?rev=1797174&view=auto
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/WatcherTest.java
(added)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/WatcherTest.java
Thu Jun 1 10:01:22 2017
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.meecrowave;
+
+import org.junit.Test;
+import org.superbiz.app.Bounced;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import java.io.File;
+import java.io.IOException;
+
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN_TYPE;
+import static org.junit.Assert.fail;
+
+// you can need to mvn test-compile before running this test if it was
executed once already
+public class WatcherTest {
+ @Test
+ public void watch() throws IOException {
+ final String bouncedFile = "target/test-classes/" +
Bounced.class.getName().replace(".", "/") + ".class";
+ final Meecrowave.Builder builder = new Meecrowave.Builder() {{
+ setWatcherBouncing(250);
+
}}.randomHttpPort().includePackages(Bounced.class.getPackage().getName());
+ try (final Meecrowave meecrowave = new Meecrowave(builder).bake()) {
+ final String endpoint =
String.format("http://localhost:%d/api/bounced", builder.getHttpPort());
+
+ final Client client = ClientBuilder.newClient();
+ try {
+ final String original = client.target(endpoint)
+ .request(TEXT_PLAIN_TYPE)
+ .get(String.class);
+
+ try {
+ Thread.sleep(1000);
+ } catch (final InterruptedException e) {
+ fail(e.getMessage());
+ }
+
+ // now replace it by "replaced", not we don't reload classes
yet so we just check we redeployed, should we integ with fakereplace?
+ new
File(bouncedFile).setLastModified(System.currentTimeMillis());
+
+ long max = 5000 /* deployment max */ + 250 /* bouncing */ * 4
/* wait in watcher + 3 loops in bouncer */;
+ while (max > 0) {
+ try {
+ Thread.sleep(1000);
+ } catch (final InterruptedException e) {
+ fail(e.getMessage());
+ }
+ max -= 1000;
+
+ try {
+ final String reloaded = client.target(endpoint)
+ .request(TEXT_PLAIN_TYPE)
+ .get(String.class);
+ if (!original.equals(reloaded)) {
+ return;
+ }
+ System.out.println("Got " + reloaded + " instead of
something more recent.");
+ } catch (final WebApplicationException |
ProcessingException e) {
+ // redeploying pby
+ }
+ }
+ fail("didn't see Bounced endpoint reloaded");
+ } finally {
+ client.close();
+ }
+ }
+ }
+}
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/superbiz/app/Bounced.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/superbiz/app/Bounced.java?rev=1797174&view=auto
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/superbiz/app/Bounced.java
(added)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/superbiz/app/Bounced.java
Thu Jun 1 10:01:22 2017
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.superbiz.app;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("bounced")
+@ApplicationScoped
+public class Bounced {
+ private String time;
+
+ @PostConstruct
+ private void init() {
+ time = Long.toString(System.nanoTime());
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String app() {
+ return time;
+ }
+}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveExtension.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveExtension.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveExtension.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveExtension.java
Thu Jun 1 10:01:22 2017
@@ -28,6 +28,7 @@ public class MeecrowaveExtension {
private String context = "";
private File webapp;
+ private int watcherBouncing;
private int httpPort = 8080;
private int httpsPort = 8443;
private int stopPort = -1;
@@ -646,4 +647,12 @@ public class MeecrowaveExtension {
public void setJaxrsAutoActivateBeanValidation(final boolean
jaxrsAutoActivateBeanValidation) {
this.jaxrsAutoActivateBeanValidation = jaxrsAutoActivateBeanValidation;
}
+
+ public int getWatcherBouncing() {
+ return watcherBouncing;
+ }
+
+ public void setWatcherBouncing(final int watcherBouncing) {
+ this.watcherBouncing = watcherBouncing;
+ }
}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveTask.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveTask.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveTask.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/src/main/java/org/apache/meecrowave/gradle/MeecrowaveTask.java
Thu Jun 1 10:01:22 2017
@@ -54,6 +54,10 @@ public class MeecrowaveTask extends Defa
@Input
@Optional
+ private int watcherBouncing;
+
+ @Input
+ @Optional
private int httpPort = 8080;
@Input
@@ -1160,4 +1164,12 @@ public class MeecrowaveTask extends Defa
public void setMeecrowaveProperties(final String meecrowaveProperties) {
this.meecrowaveProperties = meecrowaveProperties;
}
+
+ public int getWatcherBouncing() {
+ return watcherBouncing;
+ }
+
+ public void setWatcherBouncing(final int watcherBouncing) {
+ this.watcherBouncing = watcherBouncing;
+ }
}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java?rev=1797174&r1=1797173&r2=1797174&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
Thu Jun 1 10:01:22 2017
@@ -55,6 +55,9 @@ import static org.apache.maven.plugins.a
@Mojo(name = "run", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM)
public class MeecrowaveRunMojo extends AbstractMojo {
+ @Parameter(property = "meecrowave.watcher-bounding", defaultValue = "0")
+ private int watcherBouncing;
+
@Parameter(property = "meecrowave.http", defaultValue = "8080")
private int httpPort;