You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by dm...@apache.org on 2019/08/26 22:56:54 UTC

[tapestry-5] branch TAP5-2613 created (now 8135af4)

This is an automated email from the ASF dual-hosted git repository.

dmitrygusev pushed a change to branch TAP5-2613
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git.


      at 8135af4  TAP5-2613: Upgrade tapestry build to Java 11

This branch includes the following new commits:

     new 8135af4  TAP5-2613: Upgrade tapestry build to Java 11

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tapestry-5] 01/01: TAP5-2613: Upgrade tapestry build to Java 11

Posted by dm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dmitrygusev pushed a commit to branch TAP5-2613
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 8135af4187aa17acf7e94aeb384d7456a733e8b4
Author: Dmitry Gusev <dm...@gmail.com>
AuthorDate: Tue Aug 27 01:56:32 2019 +0300

    TAP5-2613: Upgrade tapestry build to Java 11
---
 .../services/PropertyConduitSourceImpl.java        |   1 -
 build.gradle                                       |  33 +-
 .../internal/services/DefaultDataTypeAnalyzer.java |   1 -
 gradle/wrapper/gradle-wrapper.jar                  | Bin 54727 -> 56177 bytes
 gradle/wrapper/gradle-wrapper.properties           |   2 +-
 plastic/build.gradle                               |   5 +
 .../internal/plastic/asm/tree/package.html         |   4 +-
 .../{LocalVariable.java => LocalVariableImpl.java} |   0
 quickstart/build.gradle                            |   2 +-
 src/javadoc/stylesheet7.css                        |  40 ++-
 .../src/main/java/org/apache/tapestry5/Link.java   |   4 +-
 .../integration/app1/pages/TimeIntervalDemo.groovy |   6 +-
 .../ioc/internal/services/cron/CronExpression.java |  66 ++--
 tapestry-javadoc/build.gradle                      |  21 +-
 .../apache/tapestry5/javadoc/ClassDescription.java | 161 ++++++----
 .../tapestry5/javadoc/DocCommentTreeProvider.java  |  10 +
 .../tapestry5/javadoc/ParameterDescription.java    |  61 ++--
 .../tapestry5/javadoc/TapestryDocTaglet.java       | 132 ++++----
 .../javadoc/ParameterDescriptionSpec.groovy        | 352 ++++++++++++++-------
 tapestry-jpa/build.gradle                          |   2 +-
 .../java/org/apache/tapestry5/json/JSONObject.java |   2 +-
 tapestry-spring/build.gradle                       |   3 +-
 .../standard/TapestrySpringIntegrationTest.java    |   2 +-
 .../apache/tapestry5/test/SeleniumTestCase.java    |   2 +-
 24 files changed, 542 insertions(+), 370 deletions(-)

diff --git a/beanmodel/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java b/beanmodel/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
index 58820db..dea2052 100644
--- a/beanmodel/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
+++ b/beanmodel/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
@@ -30,7 +30,6 @@ import org.apache.tapestry5.ioc.internal.NullAnnotationProvider;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.GenericsUtils;
 import org.apache.tapestry5.ioc.internal.util.InternalCommonsUtils;
-import org.apache.tapestry5.ioc.internal.util.InternalCommonsUtils;
 import org.apache.tapestry5.ioc.services.*;
 import org.apache.tapestry5.ioc.util.AvailableValues;
 import org.apache.tapestry5.ioc.util.ExceptionUtils;
diff --git a/build.gradle b/build.gradle
index 35bd659..c468453 100755
--- a/build.gradle
+++ b/build.gradle
@@ -14,11 +14,11 @@ project.ext.versions = [
     testng: "6.8.21",
     easymock: "3.3.1",
     servletapi: "3.0.1",
-    spock: "1.1-groovy-2.4",
+    spock: "1.3-groovy-2.5",
     hibernate: "5.1.1.Final",
     slf4j: "1.7.25",
     geb: "2.0",
-    selenium: "3.12.0"
+    selenium: "3.141.59"
 ]
 
 ext.continuousIntegrationBuild = Boolean.getBoolean("ci")
@@ -201,10 +201,6 @@ subprojects {
         systemProperties["java.io.tmpdir"] = temporaryDir.absolutePath
 
         jvmArgs("-Dfile.encoding=UTF-8")
-        if (jdkMajorVersion != "1"){
-          // TODO: make these regular dependencies instead
-          jvmArgs += ["--add-modules", "java.xml.ws.annotation,java.xml.bind"]
-        }
 
         environment.LANG = 'en_US.UTF-8'
         
@@ -328,27 +324,31 @@ task aggregateJavadoc(type: Javadoc) {
 
     def tapestryStylesheet = file("src/javadoc/stylesheet7.css")
 
-    configure(options) {
+    def allMainSourceSets = subprojects*.sourceSets*.main.flatten()
+    def allMainJavaFiles = allMainSourceSets*.java
+    def allMainJavaSrcDirs = allMainJavaFiles*.srcDirs
+
+    options {
         splitIndex true
         linkSource true
         stylesheetFile tapestryStylesheet
         windowTitle "Tapestry API - ${project.version}"
         header "Tapestry API - ${project.version}"
         docTitle "Tapestry API - ($project.version)"
-        bottom '${project.version} - Copyright &copy; 2003-2015 <a href="http://tapestry.apache.org">The Apache Software Foundation</a>.'
+        bottom 'Copyright &copy; 2003-2019 <a href="http://tapestry.apache.org">The Apache Software Foundation</a>.'
         use = true // 'use' seems to be a reserved word for the DSL
         links "https://docs.oracle.com/javase/8/docs/api/"
         links "https://docs.oracle.com/javaee/7/api/"
-        addStringOption "tagletpath", configurations.javadoc.asPath
-        addStringOption "taglet", "org.apache.tapestry5.javadoc.TapestryDocTaglet"
+        tagletPath List.copyOf((Set) configurations.javadoc.files)
+        //  Uncomment jFlags to debug `./gradlew aggregateJavadoc`
+//        jFlags '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'
+        addStringOption '-source-path', files(allMainJavaSrcDirs.flatten()).asPath
+        addStringOption 'source', '8'
+        taglets "org.apache.tapestry5.javadoc.TapestryDocTaglet"
         exclude "org/apache/tapestry5/internal/plastic/asm/**"
         exclude "org/apache/tapestry5/internal/webresources/**"
     }
 
-    def allMainSourceSets = subprojects*.sourceSets*.main.flatten()
-    def allMainJavaFiles = allMainSourceSets*.java
-    def allMainJavaSrcDirs = allMainJavaFiles*.srcDirs
-
     source allMainJavaFiles
 
     classpath += files(allMainSourceSets*.compileClasspath)
@@ -437,11 +437,6 @@ task continuousIntegration {
     description "Task executed on Jenkins CI server after SVN commits"
 }
 
-task wrapper(type: Wrapper) {
-    gradleVersion = '4.3.1'
-    description "Regenerates the Gradle Wrapper files"
-}
-
 task zippedSources(type: Zip) {
     description "Creates a combined Zip file of all sub-project's sources"
     group "Release artifact"
diff --git a/commons/src/main/java/org/apache/tapestry5/internal/services/DefaultDataTypeAnalyzer.java b/commons/src/main/java/org/apache/tapestry5/internal/services/DefaultDataTypeAnalyzer.java
index cdf98e5..5447a14 100644
--- a/commons/src/main/java/org/apache/tapestry5/internal/services/DefaultDataTypeAnalyzer.java
+++ b/commons/src/main/java/org/apache/tapestry5/internal/services/DefaultDataTypeAnalyzer.java
@@ -17,7 +17,6 @@ package org.apache.tapestry5.internal.services;
 import org.apache.tapestry5.ioc.services.PropertyAdapter;
 import org.apache.tapestry5.ioc.util.StrategyRegistry;
 import org.apache.tapestry5.services.DataTypeAnalyzer;
-import org.apache.tapestry5.services.InvalidationListener;
 
 import java.util.Map;
 
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 27768f1..29953ea 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fb7ef98..8d58bda 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
diff --git a/plastic/build.gradle b/plastic/build.gradle
index d292efa..a5ff4d0 100644
--- a/plastic/build.gradle
+++ b/plastic/build.gradle
@@ -3,6 +3,11 @@ description = "High-level runtime transformations of Java classes"
 dependencies {
     compile "org.slf4j:slf4j-api:${versions.slf4j}"
 
+    compile 'jakarta.annotation:jakarta.annotation-api:1.3.4'
+    compile 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2'
+    compile 'org.glassfish.jaxb:jaxb-runtime:2.3.2'
+    compile "com.sun.xml.ws:jaxws-ri:2.3.2"
+    compile 'javax.xml.ws:jaxws-api:2.3.1'
 }
 
 test { 
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
index ab295ac..e530df1 100755
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
@@ -45,8 +45,8 @@ transform a class by almost two (it is almost two times faster to read, "modify"
 and write a class with a ClassVisitor than with a ClassNode). This is why
 this package is bundled in an optional <code>asm-tree.jar</code> library that
 is separated from (but requires) the <code>asm.jar</code> library, which contains
-the core ASM framework. This is also why <i><font color="red">it is recommended
-not to use this class adapter when it is possible</font></i>.
+the core ASM framework. This is also why <i><span class="t5-danger">it is recommended
+not to use this class adapter when it is possible</span></i>.
 </p>
 
 <p>
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariableImpl.java
similarity index 100%
rename from plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java
rename to plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariableImpl.java
diff --git a/quickstart/build.gradle b/quickstart/build.gradle
index 1a34cf6..a2d6393 100644
--- a/quickstart/build.gradle
+++ b/quickstart/build.gradle
@@ -59,7 +59,7 @@ task processFiltered(type: Copy) {
         jsonVersion: '1.1.2',
         seleniumVersion: '3.141.59',
         servletApiVersion: '3.0.1',
-        spockVersion: '1.3-RC1-groovy-2.5',
+        spockVersion: '1.3-groovy-2.5',
         springBootVersion: '2.1.3.RELEASE',
         yassonVersion: '1.0.1'
     ])
diff --git a/src/javadoc/stylesheet7.css b/src/javadoc/stylesheet7.css
index c84f9b2..aedfa5b 100644
--- a/src/javadoc/stylesheet7.css
+++ b/src/javadoc/stylesheet7.css
@@ -351,7 +351,7 @@ Table styles
 .contentContainer .description table, .contentContainer .details table {
     border-bottom:none;
 }
-.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{
+.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table tr:nth-child(1)>th.colSecond, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colSecond, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer  [...]
     vertical-align:top;
     padding-right:20px;
 }
@@ -361,7 +361,7 @@ Table styles
 .contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne {
     padding-right:3px;
 }
-.overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption {
+.overviewSummary caption, .packageSummary caption, .memberSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption {
     position:relative;
     text-align:left;
     background-repeat:no-repeat;
@@ -375,7 +375,7 @@ Table styles
 caption a:link, caption a:hover, caption a:active, caption a:visited {
     color:#FFFFFF;
 }
-.overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span {
+.overviewSummary caption span, .packageSummary caption span, .memberSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span {
     white-space:nowrap;
     padding-top:8px;
     padding-left:8px;
@@ -384,7 +384,7 @@ caption a:link, caption a:hover, caption a:active, caption a:visited {
     background-image:url(titlebar_green.gif);
     height:18px;
 }
-.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd {
+.overviewSummary .tabEnd, .packageSummary .tabEnd, .memberSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd {
     width:10px;
     background-image:url(titlebar_green_end.gif);
     background-repeat:no-repeat;
@@ -405,21 +405,25 @@ ul.blockList ul.blockList li.blockList table {
 .rowColor {
     background-color:#ffffff;
 }
-.overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td {
+.overviewSummary td, .packageSummary td, .memberSummary td, .memberSummary th:nth-child(1), .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td {
     text-align:left;
     padding:3px 3px 3px 7px;
 }
-th.colFirst, th.colLast, th.colOne, .constantValuesContainer th, .parameters th {
+th.colFirst, th.colLast, th.colOne, .constantValuesContainer th, .parameters th,
+/* javadoc bug? it emits tr>th even for non-header cells */
+tr:nth-child(1)>th.colSecond {
     background:#dee3e9;
     border-top:1px solid #9eadc0;
     border-bottom:1px solid #9eadc0;
     text-align:left;
     padding:3px 3px 3px 7px;
 }
-td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colSecond a:link, td.colFirst a:active, td.colSecond a:active, td.colFirst a:visited, td.colSecond a:visited, td.colFirst a:hover, td.colSecond a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
     font-weight:bold;
 }
-td.colFirst, th.colFirst {
+td.colFirst, th.colFirst,
+/* colFirst is not always emitted, i.e. for constructor names */
+th:nth-child(1) {
     border-left:1px solid #9eadc0;
     white-space:nowrap;
 }
@@ -435,14 +439,26 @@ table.overviewSummary  {
     margin-left:0px;
 }
 table.overviewSummary td.colFirst, table.overviewSummary th.colFirst,
+table.overviewSummary td:nth-child(1), table.overviewSummary th:nth-child(1),
 table.overviewSummary td.colOne, table.overviewSummary th.colOne {
     width:25%;
     vertical-align:middle;
 }
-table.packageSummary td.colFirst, table.overviewSummary th.colFirst {
+table.packageSummary td.colFirst, table.packageSummary th.colFirst,
+table.packageSummary td:nth-child(1), table.packageSummary th:nth-child(1) {
     width:25%;
     vertical-align:middle;
 }
+table.memberSummary td.colFirst, table.memberSummary th.colFirst,
+table.memberSummary td:nth-child(1), table.memberSummary th:nth-child(1) {
+    width:25%;
+    vertical-align:middle;
+}
+
+table.memberSummary {
+    border-spacing: 0;
+    border-collapse: collapse;
+}
 /*
 Content styles
 */
@@ -497,3 +513,9 @@ div.description table.parameters td.colFirst {
 table.parameters td.description {
     border-top: none;
 }
+.t5-danger {
+    color: red;
+}
+.t5-left {
+    text-align: left;
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
index 19e8185..c9437e7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java
@@ -40,7 +40,7 @@ public interface Link
     List<String> getParameterNames();
 
     /**
-     * Returns the value of a specifically named query parameter, or <tt>null</tt> if no such query parameter is stored
+     * Returns the value of a specifically named query parameter, or <code>null</code> if no such query parameter is stored
      * in the link.
      *
      * Use this method only when you are sure the parameter has only one value. If the parameter might have more than
@@ -116,7 +116,7 @@ public interface Link
     String toRedirectURI();
 
     /**
-     * Returns the link anchor. If this link does not have an anchor, this method returns <tt>null</tt>.
+     * Returns the link anchor. If this link does not have an anchor, this method returns <code>null</code>.
      *
      * @return the link anchor
      */
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
index 4495db3..007feb8 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
@@ -3,6 +3,10 @@ package org.apache.tapestry5.integration.app1.pages
 import org.apache.tapestry5.annotations.Persist
 import org.apache.tapestry5.annotations.Property
 
+import java.time.LocalDateTime
+import java.time.temporal.ChronoUnit
+import java.time.temporal.TemporalUnit
+
 
 class TimeIntervalDemo extends LocalDateDemo {
 
@@ -12,7 +16,7 @@ class TimeIntervalDemo extends LocalDateDemo {
 
     void setupRender() {
         if (previousRender == null)
-            previousRender = new Date().clearTime()
+            previousRender = new Date(LocalDateTime.now().toLocalDate().toEpochDay())
     }
 
     void afterRender() {
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/CronExpression.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/CronExpression.java
index 82a0bff..6f77a0d 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/CronExpression.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/CronExpression.java
@@ -25,54 +25,54 @@ import java.util.*;
  * Cron expressions are comprised of 6 required fields and one optional field
  * separated by white space. The fields respectively are described as follows:
  *
- * <table cellspacing="8">
+ * <table style="border-spacing: 8px; border-collapse: separate;">
  * <tr>
- * <th align="left">Field Name</th>
- * <th align="left">&nbsp;</th>
- * <th align="left">Allowed Values</th>
- * <th align="left">Allowed Special Characters</th>
+ * <th class="t5-left">Field Name</th>
+ * <th class="t5-left">&nbsp;</th>
+ * <th class="t5-left">Allowed Values</th>
+ * <th class="t5-left">Allowed Special Characters</th>
  * </tr>
  * <tr>
- * <td align="left"><code>Seconds</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>0-59</code></td>
- * <td align="left"><code>, - * /</code></td>
+ * <td class="t5-left"><code>Seconds</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>0-59</code></td>
+ * <td class="t5-left"><code>, - * /</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Minutes</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>0-59</code></td>
- * <td align="left"><code>, - * /</code></td>
+ * <td class="t5-left"><code>Minutes</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>0-59</code></td>
+ * <td class="t5-left"><code>, - * /</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Hours</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>0-23</code></td>
- * <td align="left"><code>, - * /</code></td>
+ * <td class="t5-left"><code>Hours</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>0-23</code></td>
+ * <td class="t5-left"><code>, - * /</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Day-of-month</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>1-31</code></td>
- * <td align="left"><code>, - * ? / L W</code></td>
+ * <td class="t5-left"><code>Day-of-month</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>1-31</code></td>
+ * <td class="t5-left"><code>, - * ? / L W</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Month</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>1-12 or JAN-DEC</code></td>
- * <td align="left"><code>, - * /</code></td>
+ * <td class="t5-left"><code>Month</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>1-12 or JAN-DEC</code></td>
+ * <td class="t5-left"><code>, - * /</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Day-of-Week</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>1-7 or SUN-SAT</code></td>
- * <td align="left"><code>, - * ? / L #</code></td>
+ * <td class="t5-left"><code>Day-of-Week</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>1-7 or SUN-SAT</code></td>
+ * <td class="t5-left"><code>, - * ? / L #</code></td>
  * </tr>
  * <tr>
- * <td align="left"><code>Year (Optional)</code></td>
- * <td align="left">&nbsp;</td>
- * <td align="left"><code>empty, 1970-2199</code></td>
- * <td align="left"><code>, - * /</code></td>
+ * <td class="t5-left"><code>Year (Optional)</code></td>
+ * <td class="t5-left">&nbsp;</td>
+ * <td class="t5-left"><code>empty, 1970-2199</code></td>
+ * <td class="t5-left"><code>, - * /</code></td>
  * </tr>
  * <caption>Cron Expressions</caption>
  * </table>
diff --git a/tapestry-javadoc/build.gradle b/tapestry-javadoc/build.gradle
index 412bf8e..6e06ca6 100644
--- a/tapestry-javadoc/build.gradle
+++ b/tapestry-javadoc/build.gradle
@@ -1,24 +1,13 @@
 description = "JavaDoc Plugin for Tapestry that generates component reference documentation for component classes"
 
+sourceCompatibility = "11"
+targetCompatibility = "11"
+
 dependencies {
   compile project(':tapestry-core')
   compile "commons-lang:commons-lang:2.6"
-  compile files(getTools())
-  
-}
-
-/** Returns the tools.jar/classes.jar of the Java runtime. */
-File getTools() {
-  def jreRelpath = isMacOSX_1_6() ? "../classes/classes.jar" : "../lib/tools.jar"
-  def jdkRelpath = isMacOSX_1_6() ? "classes/classes.jar" : "lib/tools.jar"
-  
-  def javaHome = System.properties['java.home']
-
-  return new File(javaHome, jdkRelpath).exists() ? new File(javaHome, jdkRelpath) : new File(javaHome, jreRelpath)
 }
 
-boolean isMacOSX_1_6() {
-  System.properties['os.name'].toLowerCase().contains('mac os') &&
-      System.properties['java.version'].startsWith("1.6.")
+test {
+  useJUnit()
 }
-  
diff --git a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ClassDescription.java b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ClassDescription.java
index 1bf7cc2..36f5cbe 100644
--- a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ClassDescription.java
+++ b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ClassDescription.java
@@ -14,8 +14,12 @@
 
 package org.apache.tapestry5.javadoc;
 
-import java.util.Map;
-
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.SinceTree;
+import com.sun.source.util.SimpleDocTreeVisitor;
+import jdk.javadoc.doclet.DocletEnvironment;
+import org.apache.commons.lang.StringUtils;
 import org.apache.tapestry5.BindingConstants;
 import org.apache.tapestry5.annotations.Component;
 import org.apache.tapestry5.annotations.Events;
@@ -23,18 +27,20 @@ import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 
-import com.sun.javadoc.AnnotationDesc;
-import com.sun.javadoc.AnnotationDesc.ElementValuePair;
-import com.sun.javadoc.AnnotationValue;
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.Doc;
-import com.sun.javadoc.FieldDoc;
-import com.sun.javadoc.ProgramElementDoc;
-import com.sun.javadoc.Tag;
+import javax.lang.model.element.*;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.SimpleAnnotationValueVisitor9;
+import javax.lang.model.util.SimpleTypeVisitor9;
+import java.util.List;
+import java.util.Map;
 
 public class ClassDescription
 {
-    public final ClassDoc classDoc;
+    public final DocletEnvironment env;
+
+    public final TypeElement classDoc;
 
     public final Map<String, ParameterDescription> parameters = CollectionFactory.newCaseInsensitiveMap();
 
@@ -43,23 +49,35 @@ public class ClassDescription
      */
     public final Map<String, String> events = CollectionFactory.newCaseInsensitiveMap();
 
-    public ClassDescription()
+    public ClassDescription(DocletEnvironment env)
     {
+        this.env = env;
         this.classDoc = null;
     }
 
-    public ClassDescription(ClassDoc classDoc, ClassDescriptionSource source)
+    public ClassDescription(TypeElement classDoc, ClassDescriptionSource source, DocletEnvironment env)
     {
         this.classDoc = classDoc;
+        this.env = env;
 
         loadEvents();
         loadParameters(source);
 
-        ClassDoc parentDoc = classDoc.superclass();
+        TypeMirror parentDoc = classDoc.getSuperclass();
 
-        if (parentDoc != null)
+        if (parentDoc != null
+                && !StringUtils.equals(Object.class.getName(), classDoc.toString()))
         {
-            ClassDescription parentDescription = source.getDescription(classDoc.superclass().qualifiedName());
+            String className = parentDoc.accept(new SimpleTypeVisitor9<String, Object>()
+            {
+                @Override
+                public String visitDeclared(DeclaredType t, Object o)
+                {
+                    return t.asElement().asType().toString();
+                }
+            }, null);
+
+            ClassDescription parentDescription = source.getDescription(className);
 
             mergeInto(events, parentDescription.events);
             mergeInto(parameters, parentDescription.parameters);
@@ -68,7 +86,7 @@ public class ClassDescription
 
     private void loadEvents()
     {
-        AnnotationDesc eventsAnnotation = getAnnotation(classDoc, Events.class);
+        AnnotationMirror eventsAnnotation = getAnnotation(classDoc, Events.class);
 
         if (eventsAnnotation == null)
             return;
@@ -76,21 +94,26 @@ public class ClassDescription
         // Events has only a single attribute: value(), so we know its the first element
         // in the array.
 
-        ElementValuePair pair = eventsAnnotation.elementValues()[0];
-
-        AnnotationValue annotationValue = pair.value();
-        AnnotationValue[] values = (AnnotationValue[]) annotationValue.value();
+        AnnotationValue annotationValue = eventsAnnotation.getElementValues().values().iterator().next();
 
-        for (AnnotationValue eventValue : values)
+        annotationValue.accept(new SimpleAnnotationValueVisitor9<Void, Void>()
         {
-            String event = (String) eventValue.value();
-            int ws = event.indexOf(' ');
+            @Override
+            public Void visitArray(List<? extends AnnotationValue> values, Void aVoid)
+            {
+                for (AnnotationValue eventValue : values)
+                {
+                    String event = (String) eventValue.getValue();
+                    int ws = event.indexOf(' ');
 
-            String name = ws < 0 ? event : event.substring(0, ws);
-            String description = ws < 0 ? "" : event.substring(ws + 1).trim();
+                    String name = ws < 0 ? event : event.substring(0, ws);
+                    String description = ws < 0 ? "" : event.substring(ws + 1).trim();
 
-            events.put(name, description);
-        }
+                    events.put(name, description);
+                }
+                return null;
+            }
+        }, null);
     }
 
     private static <K, V> void mergeInto(Map<K, V> target, Map<K, V> source)
@@ -107,12 +130,12 @@ public class ClassDescription
 
     private void loadParameters(ClassDescriptionSource source)
     {
-        for (FieldDoc fd : classDoc.fields(false))
+        for (VariableElement fd : ElementFilter.fieldsIn(classDoc.getEnclosedElements()))
         {
-            if (fd.isStatic())
+            if (fd.getModifiers().contains(Modifier.STATIC))
                 continue;
 
-            if (!fd.isPrivate())
+            if (!fd.getModifiers().contains(Modifier.PRIVATE))
                 continue;
 
             Map<String, String> values = getAnnotationValues(fd, Parameter.class);
@@ -122,12 +145,20 @@ public class ClassDescription
                 String name = values.get("name");
 
                 if (name == null)
-                    name = fd.name().replaceAll("^[$_]*", "");
-
-                ParameterDescription pd = new ParameterDescription(fd, name, fd.type().qualifiedTypeName(), get(values,
-                        "value", ""), get(values, "defaultPrefix", BindingConstants.PROP), getBoolean(values,
-                        "required", false), getBoolean(values, "allowNull", true), getBoolean(values, "cache", true),
-                        getSinceTagValue(fd), isDeprecated(fd));
+                    name = fd.getSimpleName().toString().replaceAll("^[$_]*", "");
+
+                ParameterDescription pd = new ParameterDescription(
+                        fd,
+                        name,
+                        fd.asType().toString(),
+                        get(values, "value", ""),
+                        get(values, "defaultPrefix", BindingConstants.PROP),
+                        getBoolean(values, "required", false),
+                        getBoolean(values, "allowNull", true),
+                        getBoolean(values, "cache", true),
+                        getSinceTagValue(fd),
+                        env.getElementUtils().isDeprecated(fd),
+                        e -> env.getDocTrees().getDocCommentTree(e));
 
                 parameters.put(name, pd);
 
@@ -154,40 +185,48 @@ public class ClassDescription
         }
     }
 
-    private ParameterDescription getPublishedParameterDescription(ClassDescriptionSource source, FieldDoc fd,
-            String name)
+    private ParameterDescription getPublishedParameterDescription(
+            ClassDescriptionSource source, VariableElement fd, String name)
     {
-        String currentClassName = fd.type().qualifiedTypeName();
+        String currentClassName = fd.asType().toString();
 
         while (true)
         {
             ClassDescription componentCD = source.getDescription(currentClassName);
 
             if (componentCD.classDoc == null)
-                throw new IllegalArgumentException(String.format("Published parameter '%s' from %s not found.", name,
-                        fd.qualifiedName()));
+                //  TODO FQN for fd
+                throw new IllegalArgumentException(
+                        String.format("Published parameter '%s' from %s not found.", name, fd.getSimpleName()));
 
             if (componentCD.parameters.containsKey(name)) { return componentCD.parameters.get(name); }
 
-            currentClassName = componentCD.classDoc.superclass().typeName();
+            currentClassName = componentCD.classDoc.getSuperclass().toString();
         }
     }
 
-    private static boolean isDeprecated(ProgramElementDoc doc)
+    private String getSinceTagValue(Element doc)
     {
-        return (getAnnotation(doc, Deprecated.class) != null) || (doc.tags("deprecated").length != 0);
-    }
+        final DocCommentTree tree = env.getDocTrees().getDocCommentTree(doc);
 
-    private static String getSinceTagValue(Doc doc)
-    {
-        return getTagValue(doc, "since");
-    }
+        if (tree == null)
+        {
+            return "";
+        }
 
-    private static String getTagValue(Doc doc, String tagName)
-    {
-        Tag[] tags = doc.tags(tagName);
+        for (DocTree tag : tree.getBlockTags())
+        {
+            return tag.accept(new SimpleDocTreeVisitor<String, Void>("")
+            {
+                @Override
+                public String visitSince(SinceTree node, Void aVoid)
+                {
+                    return node.getBody().toString();
+                }
+            }, null);
+        }
 
-        return 0 < tags.length ? tags[0].text() : "";
+        return "";
     }
 
     private static boolean getBoolean(Map<String, String> map, String key, boolean defaultValue)
@@ -206,30 +245,30 @@ public class ClassDescription
         return defaultValue;
     }
 
-    private static AnnotationDesc getAnnotation(ProgramElementDoc source, Class annotationType)
+    private static AnnotationMirror getAnnotation(Element source, Class annotationType)
     {
         String name = annotationType.getName();
 
-        for (AnnotationDesc ad : source.annotations())
+        for (AnnotationMirror ad : source.getAnnotationMirrors())
         {
-            if (ad.annotationType().qualifiedTypeName().equals(name)) { return ad; }
+            if (ad.getAnnotationType().toString().equals(name)) { return ad; }
         }
 
         return null;
     }
 
-    private static Map<String, String> getAnnotationValues(ProgramElementDoc source, Class annotationType)
+    private static Map<String, String> getAnnotationValues(Element source, Class annotationType)
     {
-        AnnotationDesc annotation = getAnnotation(source, annotationType);
+        AnnotationMirror annotation = getAnnotation(source, annotationType);
 
         if (annotation == null)
             return null;
 
         Map<String, String> result = CollectionFactory.newMap();
 
-        for (ElementValuePair pair : annotation.elementValues())
+        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> pair : annotation.getElementValues().entrySet())
         {
-            result.put(pair.element().name(), pair.value().value().toString());
+            result.put(pair.getKey().getSimpleName().toString(), pair.getValue().getValue().toString());
         }
 
         return result;
diff --git a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/DocCommentTreeProvider.java b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/DocCommentTreeProvider.java
new file mode 100644
index 0000000..ef72dd0
--- /dev/null
+++ b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/DocCommentTreeProvider.java
@@ -0,0 +1,10 @@
+package org.apache.tapestry5.javadoc;
+
+import com.sun.source.doctree.DocCommentTree;
+
+import javax.lang.model.element.Element;
+
+public interface DocCommentTreeProvider
+{
+    DocCommentTree getDocCommentTree(Element e);
+}
diff --git a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
index 8ff25fc..13198bb 100644
--- a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
+++ b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
@@ -14,22 +14,21 @@
 
 package org.apache.tapestry5.javadoc;
 
+import com.sun.source.doctree.*;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+import javax.lang.model.element.VariableElement;
 import java.io.IOException;
 import java.util.Locale;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-
-import com.sun.javadoc.FieldDoc;
-import com.sun.javadoc.SeeTag;
-import com.sun.javadoc.Tag;
-
 public class ParameterDescription
 {
-    public final FieldDoc field;
+    public final VariableElement field;
 
     public final String name;
 
@@ -49,12 +48,15 @@ public class ParameterDescription
 
     public final boolean deprecated;
 
+    private final DocCommentTreeProvider docCommentTreeProvider;
+
     private static final Pattern SPECIAL_CONTENT = Pattern.compile("(?:</?(\\p{Alpha}+)>)|(?:&\\p{Alpha}+;)");
     private static final Set<String> PASS_THROUGH_TAGS = CollectionFactory.newSet("b", "em", "i", "code", "strong");
 
 
-    public ParameterDescription(final FieldDoc fieldDoc, final String name, final String type, final String defaultValue, final String defaultPrefix,
-            final boolean required, final boolean allowNull, final boolean cache, final String since, final boolean deprecated)
+    public ParameterDescription(final VariableElement fieldDoc, final String name, final String type, final String defaultValue, final String defaultPrefix,
+                                final boolean required, final boolean allowNull, final boolean cache, final String since, final boolean deprecated,
+                                final DocCommentTreeProvider docCommentTreeProvider)
     {
         this.field = fieldDoc;
         this.name = name;
@@ -66,6 +68,7 @@ public class ParameterDescription
         this.cache = cache;
         this.since = since;
         this.deprecated = deprecated;
+        this.docCommentTreeProvider = docCommentTreeProvider;
     }
 
     /**
@@ -76,40 +79,42 @@ public class ParameterDescription
      */
     public String extractDescription() throws IOException
     {
+        final DocCommentTree tree = docCommentTreeProvider.getDocCommentTree(field);
+
+        if (tree == null)
+        {
+            return "";
+        }
+
         StringBuilder builder = new StringBuilder();
 
-        for (Tag tag : field.inlineTags())
+        for (com.sun.source.doctree.DocTree tag : tree.getFullBody())
         {
-            if (tag.name().equals("Text"))
+            if (tag.getKind() == DocTree.Kind.TEXT)
             {
-                appendContentSafe(builder, tag.text());
+                TextTree textTree = (TextTree) tag;
+                appendContentSafe(builder, textTree.getBody());
                 continue;
             }
 
-            if (tag.name().equals("@link"))
+            if (tag.getKind() == DocTree.Kind.LINK)
             {
-                SeeTag seeTag = (SeeTag) tag;
-
-                String label = seeTag.label();
-                if (label != null && !label.equals(""))
+                LinkTree seeTag = (LinkTree) tag;
+                String label = seeTag.getLabel().toString();
+                if (StringUtils.isNotEmpty(label))
                 {
                     builder.append(StringEscapeUtils.escapeHtml(label));
                     continue;
                 }
 
-                if (seeTag.referencedClassName() != null)
-                    builder.append(StringEscapeUtils.escapeHtml(seeTag.referencedClassName()));
-
-                if (seeTag.referencedMemberName() != null)
-                {
-                    builder.append('#');
-                    builder.append(StringEscapeUtils.escapeHtml(seeTag.referencedMemberName()));
-                }
+                if (seeTag.getReference() != null)
+                    builder.append(StringEscapeUtils.escapeHtml(seeTag.getReference().getSignature()));
             }
-            else if (tag.name().equals("@code"))
+            else if (tag.getKind() == DocTree.Kind.CODE)
             {
+                LiteralTree codeTag = (LiteralTree) tag;
                 builder.append("<code>");
-                builder.append(StringEscapeUtils.escapeHtml(tag.text()));
+                builder.append(StringEscapeUtils.escapeHtml(codeTag.getBody().getBody()));
                 builder.append("</code>");
             }
         }
diff --git a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/TapestryDocTaglet.java b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/TapestryDocTaglet.java
index c086280..2fe92ef 100644
--- a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/TapestryDocTaglet.java
+++ b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/TapestryDocTaglet.java
@@ -14,73 +14,62 @@
 
 package org.apache.tapestry5.javadoc;
 
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.Tag;
-import com.sun.tools.doclets.Taglet;
+import com.sun.source.doctree.DocTree;
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Taglet;
+import org.apache.commons.lang.StringUtils;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
 import java.io.File;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * An inline tag allowed inside a type; it produces Tapestry component reference and other information.
  */
 public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
 {
+    private DocletEnvironment env;
+    private Doclet doclet;
+
     /**
      * Map from class name to class description.
      */
     private final Map<String, ClassDescription> classDescriptions = CollectionFactory.newMap();
 
-    private ClassDoc firstSeen;
+    private final Set<Location> allowedLocations = CollectionFactory.newSet(Location.TYPE);
+
+    private Element firstSeen;
 
     private static final String NAME = "tapestrydoc";
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unused", "unchecked"})
     public static void register(Map paramMap)
     {
         paramMap.put(NAME, new TapestryDocTaglet());
     }
 
     @Override
-    public boolean inField()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean inConstructor()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean inMethod()
+    public void init(DocletEnvironment env, Doclet doclet)
     {
-        return false;
+        this.env = env;
+        this.doclet = doclet;
     }
 
     @Override
-    public boolean inOverview()
+    public Set<Location> getAllowedLocations()
     {
-        return false;
-    }
-
-    @Override
-    public boolean inPackage()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean inType()
-    {
-        return true;
+        return allowedLocations;
     }
 
     @Override
@@ -96,53 +85,26 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
     }
 
     @Override
-    public ClassDescription getDescription(String className)
-    {
-        ClassDescription result = classDescriptions.get(className);
-
-        if (result == null)
-        {
-            // System.err.printf("*** Search for CD %s ...\n", className);
-
-            ClassDoc cd = firstSeen.findClass(className);
-
-            // System.err.printf("CD %s ... %s\n", className, cd == null ? "NOT found" : "found");
-
-            result = cd == null ? new ClassDescription() : new ClassDescription(cd, this);
-
-            classDescriptions.put(className, result);
-        }
-
-        return result;
-    }
-
-    @Override
-    public String toString(Tag tag)
-    {
-        throw new IllegalStateException("toString(Tag) should not be called for a non-inline tag.");
-    }
-
-    @Override
-    public String toString(Tag[] tags)
+    public String toString(List<? extends DocTree> tags, Element element)
     {
-        if (tags.length == 0)
+        if (tags.size() == 0)
             return null;
 
         // This should only be invoked with 0 or 1 tags. I suppose someone could put @tapestrydoc in the comment block
         // more than once.
 
-        Tag tag = tags[0];
+        DocTree tag = tags.get(0);
 
         try
         {
             StringWriter writer = new StringWriter(5000);
 
-            ClassDoc classDoc = (ClassDoc) tag.holder();
+            TypeElement classDoc = (TypeElement) element;
 
             if (firstSeen == null)
                 firstSeen = classDoc;
 
-            ClassDescription cd = getDescription(classDoc.qualifiedName());
+            ClassDescription cd = getDescription(classDoc.getQualifiedName().toString());
 
             writeClassDescription(cd, writer);
 
@@ -158,6 +120,27 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
         }
     }
 
+    @Override
+    public ClassDescription getDescription(String className)
+    {
+        ClassDescription result = classDescriptions.get(className);
+
+        if (result == null)
+        {
+            // System.err.printf("*** Search for CD %s ...\n", className);
+
+            TypeElement cd = env.getElementUtils().getTypeElement(className);
+
+            // System.err.printf("CD %s ... %s\n", className, cd == null ? "NOT found" : "found");
+
+            result = cd == null ? new ClassDescription(env) : new ClassDescription(cd, this, env);
+
+            classDescriptions.put(className, result);
+        }
+
+        return result;
+    }
+
     private void writeElement(Writer writer, String elementSpec, String text) throws IOException
     {
     	String elementName = elementSpec;
@@ -203,9 +186,10 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
 
     private void writerParameter(ParameterDescription pd, String rowClass, Writer writer) throws IOException
     {
+        String description = pd.extractDescription();
 
         writer.write("<tr class='values " + rowClass + "'>");
-        writer.write("<td rowspan='2' class='colFirst'>");
+        writer.write("<td" + (StringUtils.isEmpty(description) ? "" : " rowspan='2'") + " class='colFirst'>");
         writer.write(pd.name);
         writer.write("</td>");
 
@@ -238,11 +222,8 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
 
         writer.write("</tr>");
 
-        String description = pd.extractDescription();
-
-        if (description.length() > 0)
+        if (StringUtils.isNotEmpty(description))
         {
-
             writer.write("<tr class='" + rowClass + "'>");
             writer.write("<td colspan='4' class='description colLast'>");
             writer.write(description);
@@ -304,7 +285,7 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
      * Shorten the given class name by removing built-in Java packages
      * (currently just java.lang)
      *
-     * @param className
+     * @param name
      *         name of class, with package
      * @return potentially shorter class name
      */
@@ -313,9 +294,14 @@ public class TapestryDocTaglet implements Taglet, ClassDescriptionSource
         return name.replace("java.lang.", "");
     }
 
-    private void streamXdoc(ClassDoc classDoc, Writer writer) throws Exception
+    private void streamXdoc(TypeElement classDoc, Writer writer) throws Exception
     {
-        File sourceFile = classDoc.position().file();
+        JavaFileObject sourceFileObject = env.getJavaFileManager()
+                .getJavaFileForInput(StandardLocation.SOURCE_PATH,
+                        classDoc.getQualifiedName().toString(),
+                        JavaFileObject.Kind.SOURCE);
+
+        File sourceFile = new File(sourceFileObject.toUri());
 
         // The .xdoc file will be adjacent to the sourceFile
 
diff --git a/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy b/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
index 008d1b1..e85d3bf 100644
--- a/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
+++ b/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
@@ -1,125 +1,243 @@
 package org.apache.tapestry5.javadoc
 
+import com.sun.source.doctree.DocCommentTree
+import com.sun.source.doctree.DocTree
+import com.sun.source.doctree.LiteralTree
+import com.sun.source.doctree.TextTree
 import spock.lang.Specification
 
-import com.sun.javadoc.FieldDoc
-import com.sun.tools.doclets.internal.toolkit.util.TextTag
-import com.sun.tools.javadoc.TagImpl
-
+import javax.lang.model.element.VariableElement
 
 class ParameterDescriptionSpec extends Specification {
 
-	def "Parameter description without embedded tags is passed through"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, "Plain text")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "Plain text"
-	}
-
-	def "Embedded code tags are turned into HTML <code> elements"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TagImpl(null, "@code", "blah")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "<code>blah</code>"
-	}
-
-	// TAP5-2266
-	def "HTML in embedded code tags is escaped"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, "This renders the component as a "),
-			new TagImpl(null, "@code", "<li>"),
-			new TextTag(null, " (instead of a "),
-			new TagImpl(null, "@code", "<div>"),
-			new TextTag(null, ")")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "This renders the component as a <code>&lt;li&gt;</code> (instead of a <code>&lt;div&gt;</code>)"
-	}
-
-
-	def "Characters with special meaning are escaped"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, "Javadoc with < character")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "Javadoc with &lt; character"
-	}
-
-	def "Entities in Javadoc are left alone"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, "Text &amp; entity")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "Text &amp; entity"
-	}
-
-	def "Un-safe tags in Javadoc are removed"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, "We don't <br>want new lines or</td> table stuff")
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == "We don't want new lines or table stuff"
-	}
-
-	def "#src in Javadoc becomes #target in HTML"(){
-		setup:
-		FieldDoc fieldDoc = Mock()
-		def inlineTags = [
-			new TextTag(null, src)
-		]
-		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter", "String", "value", "literal", false, true, false, "1", false)
-		when:
-		def extracted = parameterDescription.extractDescription()
-		then:
-		1 * fieldDoc.inlineTags() >> inlineTags
-		extracted == target
-		where:
-		src     | target
-		"&"     | "&amp;"
-		"&amp;" | "&amp;"
-		"<"     | "&lt;"
-		"<b>"   | "<b>"
-
-	}
-
-
-
+    def "Parameter description without embedded tags is passed through"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [mockTextTree("Plain text")]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "Plain text"
+    }
+
+    private static TextTree mockTextTree(String body) {
+        ['getKind': { DocTree.Kind.TEXT },
+         'getBody': { body }
+        ] as TextTree
+    }
+
+    private static LiteralTree mockCodeTree(String body) {
+        ['getKind': { DocTree.Kind.CODE },
+         'getBody': { mockTextTree(body) }
+        ] as LiteralTree
+    }
+
+    def "Embedded code tags are turned into HTML <code> elements"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockCodeTree("blah")
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "<code>blah</code>"
+    }
+
+    // TAP5-2266
+    def "HTML in embedded code tags is escaped"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockTextTree("This renders the component as a "),
+                mockCodeTree("<li>"),
+                mockTextTree(" (instead of a "),
+                mockCodeTree("<div>"),
+                mockTextTree(")")
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "This renders the component as a <code>&lt;li&gt;</code> (instead of a <code>&lt;div&gt;</code>)"
+    }
+
+    def "Characters with special meaning are escaped"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockTextTree("Javadoc with < character")
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "Javadoc with &lt; character"
+    }
+
+    def "Entities in Javadoc are left alone"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockTextTree("Text &amp; entity")
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "Text &amp; entity"
+    }
+
+    def "Un-safe tags in Javadoc are removed"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockTextTree("We don't <br>want new lines or</td> table stuff")
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == "We don't want new lines or table stuff"
+    }
+
+    def "#src in Javadoc becomes #target in HTML"() {
+        setup:
+        DocCommentTreeProvider docCommentTreeProvider = Mock()
+        DocCommentTree docCommentTree = Mock()
+        VariableElement fieldDoc = Mock()
+
+        def fullBody = [
+                mockTextTree(src)
+        ]
+        ParameterDescription parameterDescription =
+                new ParameterDescription(
+                        fieldDoc,
+                        "parameter",
+                        "String",
+                        "value",
+                        "literal",
+                        false,
+                        true,
+                        false,
+                        "1",
+                        false,
+                        docCommentTreeProvider)
+        when:
+        def extracted = parameterDescription.extractDescription()
+        then:
+        1 * docCommentTreeProvider.getDocCommentTree(fieldDoc) >> docCommentTree
+        1 * docCommentTree.getFullBody() >> fullBody
+        extracted == target
+        where:
+        src     | target
+        "&"     | "&amp;"
+        "&amp;" | "&amp;"
+        "<"     | "&lt;"
+        "<b>"   | "<b>"
+    }
 }
diff --git a/tapestry-jpa/build.gradle b/tapestry-jpa/build.gradle
index 275a084..6d5d65f 100644
--- a/tapestry-jpa/build.gradle
+++ b/tapestry-jpa/build.gradle
@@ -7,7 +7,7 @@ dependencies {
 
 
   testCompile project(':tapestry-test')
-  testCompile 'org.eclipse.persistence:eclipselink:2.6.2'
+  testCompile 'org.eclipse.persistence:eclipselink:2.7.4'
 
   testRuntime "com.h2database:h2:1.2.145"
   testRuntime "org.apache.tomcat:dbcp:6.0.32"
diff --git a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
index f5727fa..96da95d 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
@@ -43,7 +43,7 @@ import java.util.Set;
  * be coerced using {@link Number#intValue() intValue}. Strings
  * that can be coerced using {@link Double#valueOf(String)} will be,
  * and then cast to int.
- * <li><a name="lossy">When the requested type is a long, other {@link Number} types will
+ * <li><a id="lossy">When the requested type is a long, other {@link Number} types will
  * be coerced using {@link Number#longValue() longValue}. Strings
  * that can be coerced using {@link Double#valueOf(String)} will be,
  * and then cast to long. This two-step conversion is lossy for very
diff --git a/tapestry-spring/build.gradle b/tapestry-spring/build.gradle
index 6f56966..678c73f 100644
--- a/tapestry-spring/build.gradle
+++ b/tapestry-spring/build.gradle
@@ -2,7 +2,8 @@ description = "Integration of Tapestry with the Spring Inversion Of Control Cont
 
 dependencies {
   compile project(':tapestry-core')
-  compile "org.springframework:spring-web:3.1.0.RELEASE"
+  compile "org.springframework:spring-web:5.1.9.RELEASE"
+  compile "org.springframework:spring-context:5.1.9.RELEASE"
 
   provided "javax.servlet:javax.servlet-api:${versions.servletapi}"
 
diff --git a/tapestry-spring/src/test/java/org/apache/tapestry5/spring/integration/standard/TapestrySpringIntegrationTest.java b/tapestry-spring/src/test/java/org/apache/tapestry5/spring/integration/standard/TapestrySpringIntegrationTest.java
index 64a341c..5a312fc 100644
--- a/tapestry-spring/src/test/java/org/apache/tapestry5/spring/integration/standard/TapestrySpringIntegrationTest.java
+++ b/tapestry-spring/src/test/java/org/apache/tapestry5/spring/integration/standard/TapestrySpringIntegrationTest.java
@@ -48,7 +48,7 @@ public class TapestrySpringIntegrationTest extends SeleniumTestCase
     {
         openBaseURL();
 
-        assertText("message", "SPRING VERSION 3.1.0.RELEASE: PIPELINE WAS INVOKED");
+        assertText("message", "SPRING VERSION 5.1.9.RELEASE: PIPELINE WAS INVOKED");
     }
 
     @Test
diff --git a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
index 6592420..f8ba030 100644
--- a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
+++ b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
@@ -389,7 +389,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         this.testContext = context;
 
         selenium = (Selenium) context.getAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
-        webDriver = ((WrapsDriver) selenium).getWrappedDriver();
+        webDriver = ((com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium) selenium).getWrappedDriver();
         baseURL = (String) context.getAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
         errorReporter = (ErrorReporter) context.getAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE);
     }