openwebbeans-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1797174 - in /openwebbeans/meecrowave/trunk: meecrowave-core/src/main/java/org/apache/catalina/startup/ meecrowave-core/src/main/java/org/apache/meecrowave/ meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/ meecrowave-core/...
Date Thu, 01 Jun 2017 10:01:22 GMT
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;
 



Mime
View raw message