Skip to content

Commit

Permalink
Merge pull request #113 from tmohme/issue-104
Browse files Browse the repository at this point in the history
Fix issue #104 - Bug: HotReload Exception with Composite
  • Loading branch information
boris-petrov authored Sep 16, 2020
2 parents 3a72984 + 1a0dedc commit 9670c83
Show file tree
Hide file tree
Showing 15 changed files with 279 additions and 3 deletions.
36 changes: 36 additions & 0 deletions integrationTests/helloGrettyMultiproject/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# helloGrettyMultiproject

Multiproject gretty example.

## How to run

```bash
cd examples/helloGrettyMultiproject
gradle appRun
```

## How to test

```bash
cd examples/helloGrettyMultiproject
gradle integrationTest
```

Unfortunately there's no automated test for the reload mechanism, because the `AppBeforeIntegrationTestTask` task
delibrately disables scanning on integration tests.
The existing automated test verifies only that gretty is usable for multiproject builds.

Verifying the hot-reload behavior has to be done manually:
1. start the server with `gradle appRun` in one terminal
2. use another terminal to `touch subproject/src/main/java/org/akhikhl/examples/gretty/helloGrettyMultiproject/subproject/SomeClass.java`
3. verify in the first terminal that gretty recompiled the project and reloaded the app
4. verify the page is still usable in a browser

## How to build a product


```bash
cd examples/helloGrettyMultiproject
gradle buildProduct
```

31 changes: 31 additions & 0 deletions integrationTests/helloGrettyMultiproject/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apply plugin: 'war'
apply plugin: 'org.gretty'
apply plugin: 'org.gretty.internal.integrationTests.IntegrationTestPlugin'

dependencies {
implementation(project(":helloGrettyMultiproject:subproject"))
compile 'org.webjars:bootstrap:3.2.0'
compile 'org.webjars:jquery:2.1.1'
// We use Velocity for example of template processing within the webapp.
compile 'org.apache.velocity:velocity:1.7'
}

gretty {
scanDependencies = true // undocumented

recompileOnSourceChange = true
reloadOnClassChange = true
reloadOnConfigChange = true
reloadOnLibChange = true
}

test {
testLogging.showStandardStreams = true
}

war {
archiveName 'helloGrettyMultiproject.war'
}

defineIntegrationTest()
testAll.dependsOn defineIntegrationTestAllContainers(), 'buildProduct'
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.examples.gretty.hellogrettyMultiproject

import geb.spock.GebReportingSpec

class PageSpec extends GebReportingSpec {

private static String baseURI

void setupSpec() {
baseURI = System.getProperty('gretty.baseURI')
}

def 'should get expected static page'() {
when:
go "${baseURI}/index.html"
then:
$('h1').text() == 'Hello, world!'
$('p', 0).text() == /This is static HTML page./
}

def 'should get expected response from servlet'() {
when:
go "${baseURI}/dynamic"
then:
$('h1').text() == 'Hello, world!'
$('p', 0).text() == /This is dynamic HTML page generated by servlet./
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.examples.gretty.hellogrettyMultiproject;

import org.akhikhl.examples.gretty.hellogrettyMultiproject.subproject.SomeClass;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


public class ExampleServlet extends HttpServlet {

private static final long serialVersionUID = -6506276378398106663L;

private VelocityEngine ve = new VelocityEngine();

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Template template = ve.getTemplate("/org/akhikhl/examples/gretty/hellogretty/templates/servletpage.html", "UTF-8");
VelocityContext context = new VelocityContext();
context.put("contextPath", request.getContextPath());
context.put("today", new java.util.Date());
PrintWriter out = response.getWriter();
SomeClass.doNothing();
try {
template.merge(context, out);
out.flush();
} finally {
out.close();
}
}

@Override
public void init() throws ServletException {
super.init();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Hello-world page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<link href="$contextPath/webjars/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="$contextPath/webjars/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="$contextPath/webjars/jquery/2.1.1/jquery.min.js"></script>
<link href="$contextPath/css/default.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="margin-base-vertical">Hello, world!</h1>
<p>This is dynamic HTML page generated by servlet.</p>
<p>Today is $today.</p>
<p><a href="index.html">Click here</a> to see static page.</p>
</div>
</div>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
filter relPath: '/', {
redirect 'index.html'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<filter>
<filter-name>RedirectFilter</filter-name>
<filter-class>org.akhikhl.gretty.RedirectFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RedirectFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

<servlet>
<display-name>ExampleServlet</display-name>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>org.akhikhl.examples.gretty.hellogrettyMultiproject.ExampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/dynamic</url-pattern>
</servlet-mapping>
</web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
body {
padding-top: 20px;
font-family: 'Open Sans', sans-serif;
font-size: 18px;
}

h1 {
font-weight: 400;
font-size: 40px;
}

.margin-base-vertical {
margin: 40px 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Hello-world page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<link href="${pageContext.request.contextPath}/webjars/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/webjars/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/webjars/jquery/2.1.1/jquery.min.js"></script>
<link href="${pageContext.request.contextPath}/css/default.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="margin-base-vertical">Hello, world!</h1>
<p>This is static HTML page.</p>
<p><a href="dynamic">Click here</a> to see dynamic page generated by servlet.</p>
</div>
</div>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
apply plugin: 'java'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.akhikhl.examples.gretty.hellogrettyMultiproject.subproject;

public class SomeClass {
public static void doNothing() {}
}
2 changes: 2 additions & 0 deletions integrationTests/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
rootProject.name = rootProjectName
include 'helloGretty'
include 'helloGrettyMultiproject'
include 'helloGrettyMultiproject:subproject'
include 'helloGrettySecure'
include 'helloGrettyOverlay'
include 'helloJersey'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ final class Runner {
}
else if(data == 'restartWithEvent') {
serverManager.stopServer()
serverManager.startServer(new ServerStartEventImpl())
serverManager.startServer(new ServerStartEventImpl(writer))
}
else if (data.startsWith('redeploy ')) {
List<String> webappList = data.replace('redeploy ', '').split(' ').toList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,14 @@ final class ProjectUtils {
wconfig.contextConfigFile = null
}

static List<Project> getDependencyProjects(Project project, List<String> configurationNames) {
def result = [] as Set
configurationNames.each {
result += getDependencyProjects(project, it)
}
return result as List
}

static List<Project> getDependencyProjects(Project project, String configurationName) {
project.configurations[configurationName].dependencies.withType(ProjectDependency).collect{ it.dependencyProject }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ abstract class BaseScannerManager implements ScannerManager {
}

protected static void collectDependenciesSourceSets(Collection<File> scanDirs, Project p) {
List<Project> dependencyProjects = ProjectUtils.getDependencyProjects(p, 'implementation')
// collect project dependencies of _all_ configurations that the build author _might_ have used
// and that are relevant at runtime
List<Project> dependencyProjects =
ProjectUtils.getDependencyProjects(p, ['compile', 'implementation', 'runtime', 'runtimeOnly'])
for(Project project: dependencyProjects) {
// adding sourceSets of dependecy project
scanDirs.addAll(project.sourceSets.main.allSource.srcDirs)
Expand Down Expand Up @@ -162,7 +165,7 @@ abstract class BaseScannerManager implements ScannerManager {
for(String f in changedFiles) {
if(f.endsWith('.jar')) {
List<WebAppConfig> dependantWebAppProjects = webapps.findAll {
it.projectPath && project.project(it.projectPath).configurations.implementation.resolvedConfiguration.resolvedArtifacts.find {
it.projectPath && project.project(it.projectPath).configurations.runtimeClasspath.resolvedConfiguration.resolvedArtifacts.find {
it.file.absolutePath == f }
}
if(dependantWebAppProjects) {
Expand Down

0 comments on commit 9670c83

Please sign in to comment.