Repository: joelittlejohn/jsonschema2pojo (language: java)

Issue:
Javadoc for constructors missing "description" on parameters?
I'm using the jsonschema2dataclass gradle plugin (issue clone from https://github.com/jsonschema2dataclass/js2d-gradle/issues/604) but I think this issue is coming from the core library here.

for data like:

```
...
                "hash": {
                    "description": "Specifies the hash algorithm and value for the content",
                    "type": "object",
                    "properties": {
                        "algorithm": {
                            "description": "The hashing function used to compute the hash value",
                            "type": "string",
                            "enum": [ "sha256" ]
                        },
                        "value": {
                            "description": "The hash value for the content",
                            "type": "string"
                        }
                    },
                    "required": [ "algorithm", "value" ]
                }
...
```
a constructor is created like:
```
     /**
      *
      * @param value
      * @param algorithm
      */
     public Hash(Hash.Algorithm algorithm, String value) {
         super();
         this.algorithm = algorithm;
         this.value = value;
     }
```

Would it make sense to inject the description into the generated javadoc here so we don't get javadoc generation warnings (happens with Temurin Java11) like:
```
/home/.../Hash.java:44: warning: no description for @param
     * @param value
       ^
```

I was hoping the javadoc could include descriptions from the json spec itself and be generated something like:
```
     /**
      *
      * @param value      the hash value for the content
      * @param algorithm  the hashing function used to compute the hash value
      */
     public Hash(Hash.Algorithm algorithm, String value) {
         super();
         this.algorithm = algorithm;
         this.value = value;
     }
```


Discussion / hints:
It looks like adding descriptions to constructor's javadoc `@param` could be added fairly easily.
It would probably need to support line splitting similar to:
https://github.com/joelittlejohn/jsonschema2pojo/blob/d2f8deaafb426ebe9a21ed14fdbe53a327a29215/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/DescriptionRule.java#L60-L67
<br>

- should it only contain value from `description`, `title` or both ? From [json schema reference](https://json-schema.org/understanding-json-schema/reference/generic.html):

> The title and description keywords must be strings. A “title” will preferably be short, whereas a “description” will provide a more lengthy explanation about the purpose of the data described by the schema.

- does current solution (or if requested change would be added) make sense in case no `description` provided ? Should generator still add `@param` without any text which would upset compiler ?
my 2c:

> should it only contain value from description, title or both ? From [json schema reference](https://json-schema.org/understanding-json-schema/reference/generic.html)

They're probably redundant, so maybe some order? ->
1. `description` if available
2. `title` if available

> does current solution (or if requested change would be added) make sense in case no description provided ? Should generator still add @param without any text which would upset compiler ?

I think if the schema itself doesn't provide a description, then that's a problem with the schema, not this library. Although I could see a solution where it's just the param again to not trigger some javadoc error?
```
@param value value
```

Sounds reasonable.

@joelittlejohn if you would happen to have a spare minute at some point, would be happy to hear your thoughts on given topic.
I'd put following as a javadoc. Presented dot after `title` and `description` is placed if a part doesn't have it.

```java
/**
@param title. description. 
*/
```
My 2c: the javadoc warning is there for a reason, because I think adding `param` on its own, with no additional string, is completely useless. I can't think of any benefit that it provides to just have `@param value`. There's also no benefit to having `@param value value`. The javadoc tool understands what parameters exist, even if they're not added to the javadoc.

I like what @eirnym proposed, where each part is optional of course, so this kind of thing:

```java
/**
 * @param {title. }?{description.}? 
 */
```
> because I think adding param on its own, with no additional string, is completely useless

Wouldn't that imply that `@param` itself should be also optional ? Eg.
```java
/**
 * {@param {title. }?{description.}?}?
 */
```
<br>

Let's consider simple "artificial" schema:
```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "title": "a title",
      "description": "Type lorem ipsum"
    },
    "id": {
      "type": "integer"
    }
  }
}
```
What would be the expected output in case `includeConstructors` and `includeAllPropertiesConstructor` are used as configuration options:
```java
    /**
     * 
     * @param id
     *     
     * @param type
     *     a type. Type lorem ipsum
     */
    public Example(String type, Integer id) {
        super();
        this.type = type;
        this.id = id;
    }
```
or
```java
    /**
     * 
     * @param type
     *     a type. Type lorem ipsum
     */
    public Example(String type, Integer id) {
        super();
        this.type = type;
        this.id = id;
    }
```
Yes, param itself would be optional.

I think from your example the second output would be better. We only include params where we can provide some useful info. Do you find the omission of id in the second example to be odd?
Saying that it looks a bit odd indeed, I have to admit that I have no strong opinion on whether it's something that should be avoided at any cost.

Fix patch:
diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ConstructorRule.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ConstructorRule.java
index ba4a983c0..51629df3c 100644
--- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ConstructorRule.java
+++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ConstructorRule.java
@@ -21,13 +21,15 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
+import java.util.StringJoiner;
 
+import org.apache.commons.lang3.StringUtils;
 import org.jsonschema2pojo.GenerationConfig;
 import org.jsonschema2pojo.Schema;
 import org.jsonschema2pojo.util.NameHelper;
@@ -69,10 +71,10 @@ public JDefinedClass apply(String nodeName, JsonNode node, JsonNode parent, JDef
     return instanceClass;
   }
 
-  private JDefinedClass handleLegacyConfiguration(JsonNode node, JDefinedClass instanceClass, Schema currentSchema) {
+  private void handleLegacyConfiguration(JsonNode node, JDefinedClass instanceClass, Schema currentSchema) {
     // Determine which properties belong to that class (or its superType/parent)
-    LinkedHashSet<String> requiredClassProperties = getConstructorProperties(node, true);
-    LinkedHashSet<String> requiredCombinedSuperProperties = getSuperTypeConstructorPropertiesRecursive(node, currentSchema, true);
+    Map<String, String> requiredClassProperties = getConstructorProperties(node, true);
+    Map<String, String> requiredCombinedSuperProperties = getSuperTypeConstructorPropertiesRecursive(node, currentSchema, true);
 
     // Only generate the constructors if there are actually properties to put in them
     if (!requiredClassProperties.isEmpty() || !requiredCombinedSuperProperties.isEmpty()) {
@@ -84,9 +86,6 @@ private JDefinedClass handleLegacyConfiguration(JsonNode node, JDefinedClass ins
       // Generate the actual constructor taking in only the required properties
       addFieldsConstructor(instanceClass, requiredClassProperties, requiredCombinedSuperProperties);
     }
-
-    // Return the original class we modified
-    return instanceClass;
   }
 
   private void handleMultiChoiceConstructorConfiguration(JsonNode node, JDefinedClass instanceClass, Schema currentSchema) {
@@ -94,10 +93,10 @@ private void handleMultiChoiceConstructorConfiguration(JsonNode node, JDefinedCl
     boolean requiresConstructors = false;
 
     // Use these lists to keep track of the properties on the class, but we'll only populate them if we need to
-    LinkedHashSet<String> requiredClassProperties = null;
-    LinkedHashSet<String> classProperties = null;
-    LinkedHashSet<String> requiredCombinedSuperProperties = null;
-    LinkedHashSet<String> combinedSuperProperties = null;
+    Map<String, String> requiredClassProperties = null;
+    Map<String, String> classProperties = null;
+    Map<String, String> requiredCombinedSuperProperties = null;
+    Map<String, String> combinedSuperProperties = null;
 
     GenerationConfig generationConfig = ruleFactory.getGenerationConfig();
     boolean includeCopyConstructor = generationConfig.isIncludeCopyConstructor();
@@ -139,7 +138,7 @@ private void handleMultiChoiceConstructorConfiguration(JsonNode node, JDefinedCl
     }
   }
 
-  private void addFieldsConstructor(JDefinedClass instanceClass, Set<String> classProperties, Set<String> combinedSuperProperties) {
+  private void addFieldsConstructor(JDefinedClass instanceClass, Map<String, String> classProperties, Map<String, String> combinedSuperProperties) {
     GenerationConfig generationConfig = ruleFactory.getGenerationConfig();
 
     // Generate the constructor with the properties which were located
@@ -154,7 +153,7 @@ private void addFieldsConstructor(JDefinedClass instanceClass, Set<String> class
     }
   }
 
-  private void addCopyConstructor(JDefinedClass instanceClass, Set<String> classProperties, Set<String> combinedSuperProperties) {
+  private void addCopyConstructor(JDefinedClass instanceClass, Map<String, String> classProperties, Map<String, String> combinedSuperProperties) {
     GenerationConfig generationConfig = ruleFactory.getGenerationConfig();
 
     // Generate the constructor with the properties which were located
@@ -173,13 +172,13 @@ private void addCopyConstructor(JDefinedClass instanceClass, Set<String> classPr
    * Retrieve the list of properties to go in the constructor from node. This is all properties listed in node["properties"] if ! onlyRequired, and
    * only required properties if onlyRequired.
    */
-  private LinkedHashSet<String> getConstructorProperties(JsonNode node, boolean onlyRequired) {
+  private Map<String, String> getConstructorProperties(JsonNode node, boolean onlyRequired) {
 
     if (!node.has("properties")) {
-      return new LinkedHashSet<>();
+      return new LinkedHashMap<>();
     }
 
-    LinkedHashSet<String> rtn = new LinkedHashSet<>();
+    LinkedHashMap<String, String> rtn = new LinkedHashMap<>();
     Set<String> draft4RequiredProperties = new HashSet<>();
 
     // setup the set of required properties for draft4 style "required"
@@ -200,38 +199,49 @@ private LinkedHashSet<String> getConstructorProperties(JsonNode node, boolean on
       Map.Entry<String, JsonNode> property = properties.next();
 
       JsonNode propertyObj = property.getValue();
+      final String javadoc = getJavadocForProperty(propertyObj);
       if (onlyRequired) {
         // draft3 style
-        if (propertyObj.has("required") && propertyObj.get("required")
-            .asBoolean()) {
-          rtn.add(nameHelper.getPropertyName(property.getKey(), property.getValue()));
+        if (propertyObj.has("required") && propertyObj.get("required").asBoolean()) {
+            rtn.put(nameHelper.getPropertyName(property.getKey(), property.getValue()), javadoc);
         }
 
         // draft4 style
         if (draft4RequiredProperties.contains(property.getKey())) {
-          rtn.add(nameHelper.getPropertyName(property.getKey(), property.getValue()));
+          rtn.put(nameHelper.getPropertyName(property.getKey(), property.getValue()), javadoc);
         }
       } else {
-        rtn.add(nameHelper.getPropertyName(property.getKey(), property.getValue()));
+        rtn.put(nameHelper.getPropertyName(property.getKey(), property.getValue()), javadoc);
       }
     }
     return rtn;
   }
 
+    private String getJavadocForProperty(JsonNode propertyObj) {
+        final StringJoiner stringJoiner = new StringJoiner(" ");
+        if (propertyObj.has("title") && StringUtils.isNotBlank(propertyObj.get("title").textValue())) {
+            stringJoiner.add(StringUtils.appendIfMissing(propertyObj.get("title").asText(), "."));
+        }
+        if (propertyObj.has("description") && StringUtils.isNotBlank(propertyObj.get("description").textValue())) {
+            stringJoiner.add(StringUtils.appendIfMissing(propertyObj.get("description").asText(), "."));
+        }
+        return stringJoiner.toString();
+    }
+
   /**
    * Recursive, walks the schema tree and assembles a list of all properties of this schema's super schemas
    */
-  private LinkedHashSet<String> getSuperTypeConstructorPropertiesRecursive(JsonNode node, Schema schema, boolean onlyRequired) {
+  private Map<String, String> getSuperTypeConstructorPropertiesRecursive(JsonNode node, Schema schema, boolean onlyRequired) {
     Schema superTypeSchema = reflectionHelper.getSuperSchema(node, schema, true);
 
     if (superTypeSchema == null) {
-      return new LinkedHashSet<>();
+      return new LinkedHashMap<>();
     }
 
     JsonNode superSchemaNode = superTypeSchema.getContent();
 
-    LinkedHashSet<String> rtn = getConstructorProperties(superSchemaNode, onlyRequired);
-    rtn.addAll(getSuperTypeConstructorPropertiesRecursive(superSchemaNode, superTypeSchema, onlyRequired));
+    Map<String, String> rtn = getConstructorProperties(superSchemaNode, onlyRequired);
+    rtn.putAll(getSuperTypeConstructorPropertiesRecursive(superSchemaNode, superTypeSchema, onlyRequired));
 
     return rtn;
   }
@@ -301,14 +311,13 @@ private void generateFieldsConcreteBuilderConstructor(JDefinedClass baseBuilderC
     }
   }
 
-  private JMethod generateCopyConstructor(JDefinedClass jclass, Set<String> classProperties, Set<String> combinedSuperProperties) {
+  private JMethod generateCopyConstructor(JDefinedClass jclass, Map<String, String> classProperties, Map<String, String> combinedSuperProperties) {
 
     // Create the JMethod for the copy constructor
     JMethod copyConstructorResult = jclass.constructor(JMod.PUBLIC);
 
     // Add a parameter to the copyConstructor for the actual object being copied
-    copyConstructorResult.javadoc()
-        .addParam("source");
+    copyConstructorResult.javadoc().addParam("source").append("the object being copied");
     JVar copyConstructorParam = copyConstructorResult.param(jclass, "source");
 
     // Create the method block for the copyConstructor
@@ -325,7 +334,7 @@ private JMethod generateCopyConstructor(JDefinedClass jclass, Set<String> classP
     // For each of the class properties being set we then need to do something like the following
     // this.property = source.property
     Map<String, JFieldVar> fields = jclass.fields();
-    for (String property : classProperties) {
+    for (String property : classProperties.keySet()) {
       JFieldVar field = fields.get(property);
 
       if (field == null) {
@@ -339,7 +348,7 @@ private JMethod generateCopyConstructor(JDefinedClass jclass, Set<String> classP
     return copyConstructorResult;
   }
 
-  private JMethod generateFieldsConstructor(JDefinedClass jclass, Set<String> classProperties, Set<String> combinedSuperProperties) {
+  private JMethod generateFieldsConstructor(JDefinedClass jclass, Map<String, String> classProperties, Map<String, String> combinedSuperProperties) {
     // add the public constructor with property parameters
     JMethod fieldsConstructor = jclass.constructor(JMod.PUBLIC);
 
@@ -359,15 +368,17 @@ private JMethod generateFieldsConstructor(JDefinedClass jclass, Set<String> clas
     Map<String, JFieldVar> fields = jclass.fields();
     Map<String, JVar> classFieldParams = new HashMap<>();
 
-    for (String property : classProperties) {
+    for (Entry<String, String> entry : classProperties.entrySet()) {
+      String property = entry.getKey();
       JFieldVar field = fields.get(property);
 
       if (field == null) {
         throw new IllegalStateException("Property " + property + " hasn't been added to JDefinedClass before calling addConstructors");
       }
 
-      fieldsConstructor.javadoc()
-          .addParam(property);
+      if (StringUtils.isNotEmpty(entry.getValue())) {
+          fieldsConstructor.javadoc().addParam(property).append(entry.getValue());
+      }
       if (generationConfig.isIncludeConstructorPropertiesAnnotation() && constructorPropertiesAnnotation != null) {
         constructorPropertiesAnnotation.param(field.name());
       }
@@ -380,7 +391,8 @@ private JMethod generateFieldsConstructor(JDefinedClass jclass, Set<String> clas
 
     List<JVar> superConstructorParams = new ArrayList<>();
 
-    for (String property : combinedSuperProperties) {
+    for (Entry<String, String> entry : combinedSuperProperties.entrySet()) {
+      String property = entry.getKey();
       JFieldVar field = reflectionHelper.searchSuperClassesForField(property, jclass);
 
       if (field == null) {
@@ -393,8 +405,9 @@ private JMethod generateFieldsConstructor(JDefinedClass jclass, Set<String> clas
         param = fieldsConstructor.param(field.type(), field.name());
       }
 
-      fieldsConstructor.javadoc()
-          .addParam(property);
+      if (StringUtils.isNotEmpty(entry.getValue())) {
+          fieldsConstructor.javadoc().addParam(property).append(entry.getValue());
+      }
       if (generationConfig.isIncludeConstructorPropertiesAnnotation() && constructorPropertiesAnnotation != null) {
         constructorPropertiesAnnotation.param(param.name());
       }
diff --git a/pom.xml b/pom.xml
index 94df6680e..eb9a4500c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -410,9 +410,9 @@
                 <scope>test</scope>
             </dependency>
             <dependency>
-                <groupId>qdox</groupId>
+                <groupId>com.thoughtworks.qdox</groupId>
                 <artifactId>qdox</artifactId>
-                <version>1.6.1</version>
+                <version>2.0.3</version>
                 <scope>test</scope>
             </dependency>
             <dependency>


Test patch:
diff --git a/jsonschema2pojo-integration-tests/pom.xml b/jsonschema2pojo-integration-tests/pom.xml
index a464b39b1..8ac004ed3 100644
--- a/jsonschema2pojo-integration-tests/pom.xml
+++ b/jsonschema2pojo-integration-tests/pom.xml
@@ -180,7 +180,7 @@
             <artifactId>robolectric</artifactId>
         </dependency>
         <dependency>
-            <groupId>qdox</groupId>
+            <groupId>com.thoughtworks.qdox</groupId>
             <artifactId>qdox</artifactId>
         </dependency>
         <dependency>
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsIT.java
index 995880e15..7b19ab354 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsIT.java
@@ -26,7 +26,6 @@
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.experimental.runners.Enclosed;
 import org.junit.runner.RunWith;
@@ -74,8 +73,7 @@ public static Object getValue(Object instance, String methodName) throws NoSuchM
   }
 
 
-  @Ignore
-  public static class ConstructorTestClasses {
+  private static class ConstructorTestClasses {
 
     protected Class<?> typeWithoutProperties;
     protected Class<?> typeWithoutRequiredProperties;
@@ -104,7 +102,7 @@ public ConstructorTestClasses(Jsonschema2PojoRule classSchemaRule, Map<String, O
   /**
    * Tests what happens when includeConstructors is set to true
    */
-  public static class DefaultInlcudeConstructorsIT {
+  public static class DefaultIncludeConstructorsIT {
 
     @ClassRule
     public static Jsonschema2PojoRule classSchemaRule = new Jsonschema2PojoRule();
@@ -126,7 +124,7 @@ public void testGeneratesConstructorWithAllProperties() throws Exception {
     }
 
     @Test
-    public void testGeneratesCosntructorWithAllPropertiesArrayStyle() throws Exception {
+    public void testGeneratesConstructorWithAllPropertiesArrayStyle() throws Exception {
       assertHasModifier(JMod.PUBLIC, getAllPropertiesConstructor(testClasses.typeWithRequiredArray).getModifiers(), "public");
     }
 
@@ -225,7 +223,7 @@ public void testGeneratesConstructorWithAllProperties() throws Exception {
     }
 
     @Test
-    public void testGeneratesCosntructorWithAllPropertiesArrayStyle() throws Exception {
+    public void testGeneratesConstructorWithAllPropertiesArrayStyle() throws Exception {
       assertHasModifier(JMod.PUBLIC, getAllPropertiesConstructor(testClasses.typeWithRequiredArray).getModifiers(), "public");
     }
 
@@ -297,7 +295,7 @@ public void testGeneratesConstructorWithAllProperties() throws Exception {
     }
 
     @Test
-    public void testGeneratesCosntructorWithAllPropertiesArrayStyle() throws Exception {
+    public void testGeneratesConstructorWithAllPropertiesArrayStyle() throws Exception {
       assertHasModifier(JMod.PUBLIC, getAllPropertiesConstructor(testClasses.typeWithRequiredArray).getModifiers(), "public");
     }
 
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsJavadocIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsJavadocIT.java
new file mode 100644
index 000000000..19a7acacc
--- /dev/null
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/ConstructorsJavadocIT.java
@@ -0,0 +1,157 @@
+/**
+ * Copyright © 2010-2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jsonschema2pojo.integration;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+import static org.jsonschema2pojo.integration.util.CodeGenerationHelper.config;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.hamcrest.Matcher;
+import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.thoughtworks.qdox.JavaProjectBuilder;
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaConstructor;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
+
+@RunWith(Enclosed.class)
+public class ConstructorsJavadocIT {
+
+    private static final DefaultJavaClass cString = new DefaultJavaClass(String.class.getName());
+    private static final DefaultJavaClass cDouble = new DefaultJavaClass(Double.class.getName());
+
+    @RunWith(Parameterized.class)
+    public static class ConstructorWithRequiredPropertiesOnlyIT {
+
+        @Parameters(name = "{0}")
+        public static Collection<String> data() {
+            return asList("constructorsRequiredPropertiesOnly", "includeRequiredPropertiesConstructor");
+        }
+
+        @Rule
+        public final Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule();
+
+        private final String configuration;
+
+        public ConstructorWithRequiredPropertiesOnlyIT(String configuration) {
+            this.configuration = configuration;
+        }
+
+        @Test
+        public void requiredPropertiesConstructor_hasJavadocForDocumentedProperties() throws IOException {
+            JavaClass javaClass = buildJavadocClass(
+                    schemaRule,
+                    config("includeConstructors", true, "includeAllPropertiesConstructor", false, configuration, true));
+
+            assertThat(javaClass.getConstructors().size(), is(2));
+            assertNoArgConstructor(javaClass.getConstructor(Collections.emptyList()));
+            final List<String> paramTagValues = getParamTagValues(javaClass.getConstructor(asList(cString, cString, cString, cString, cDouble, cDouble)));
+            // 3 documented properties in sub class and 2 documented from super class
+            assertThat(paramTagValues.size(), is(5));
+            assertSuperClassDocumentedProperties(paramTagValues);
+            assertThat(paramTagValues, hasItemContaining("descriptionOnly", "A description_only description."));
+            assertThat(paramTagValues, hasItemContaining("titleAndDescription", "A title_and_description title. A title_and_description description."));
+            assertThat(paramTagValues, hasItemContaining("tileOnly", "A title_only title."));
+        }
+    }
+
+    public static class ConstructorWithAllPropertiesIT {
+
+        @Rule
+        public final Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule();
+
+        @Test
+        public void allPropertiesConstructor_hasJavadocForDocumentedProperties() throws IOException {
+            // 'constructorsRequiredPropertiesOnly' is false and 'includeAllPropertiesConstructor' is true by default
+            JavaClass javaClass = buildJavadocClass(schemaRule, config("includeConstructors", true));
+
+            assertThat(javaClass.getConstructors().size(), is(2));
+            assertNoArgConstructor(javaClass.getConstructor(Collections.emptyList()));
+            final List<String> paramTagValues = getParamTagValues(javaClass.getConstructor(
+                            asList(cString, cString, cString, cString, cString, cString, cString, cString, cDouble, cDouble, cDouble)));
+            // 6 documented properties in sub class and 2 documented from super class
+            assertThat(paramTagValues.size(), is(8));
+            assertThat(paramTagValues, hasItemContaining("descriptionOnly", "A description_only description."));
+            assertThat(paramTagValues, hasItemContaining("nonRequiredTileOnly", "A non_required_tile_only title."));
+            assertThat(paramTagValues, hasItemContaining("titleAndDescription", "A title_and_description title. A title_and_description description."));
+            assertThat(paramTagValues, hasItemContaining("nonRequiredDescriptionOnly", "A non_required_description_only description."));
+            assertThat(paramTagValues, hasItemContaining("tileOnly", "A title_only title."));
+            assertThat(paramTagValues, hasItemContaining("nonRequiredTitleAndDescription", "A non_required_title_and_description title. A non_required_title_and_description description."));
+            assertSuperClassDocumentedProperties(paramTagValues);
+        }
+
+    }
+
+    public static class IncludeCopyConstructorIT {
+
+        @Rule
+        public final Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule();
+
+        @Test
+        public void copyConstructor_hasJavadocForDocumentedProperties() throws IOException {
+            JavaClass javaClass = buildJavadocClass(schemaRule, config("includeConstructors", true, "includeCopyConstructor", true));
+
+            assertNoArgConstructor(javaClass.getConstructor(Collections.emptyList()));
+
+            final List<String> paramTagValues = getParamTagValues(javaClass.getConstructor(Collections.singletonList(javaClass)));
+            assertThat(paramTagValues, hasSize(1));
+            assertThat(paramTagValues, hasItemContaining("source", "the object being copied"));
+        }
+
+    }
+
+    private static JavaClass buildJavadocClass(Jsonschema2PojoRule schemaRule, Map<String, Object> config) throws IOException {
+        schemaRule.generateAndCompile("/schema/constructors/javadoc/javadocConstructor.json", "com.example", config);
+
+        final JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
+        javaDocBuilder.addSource(schemaRule.generated("com/example/JavadocConstructor.java"));
+        return javaDocBuilder.getClassByName("com.example.JavadocConstructor");
+    }
+
+    private static List<String> getParamTagValues(JavaConstructor javaConstructor) {
+        return javaConstructor.getTagsByName("param").stream().map(DocletTag::getValue).collect(Collectors.toList());
+    }
+
+    private static void assertNoArgConstructor(JavaConstructor noArgConstructor) {
+        assertThat(noArgConstructor.getComment(), equalTo("No args constructor for use in serialization"));
+    }
+
+    private static void assertSuperClassDocumentedProperties(List<String> paramTagValues) {
+        assertThat(paramTagValues, hasItemContaining("scPropertyWTitle", "A sc_property_w_title title."));
+        assertThat(paramTagValues, hasItemContaining("scPropertyWDescription", "A sc_property_w_description description."));
+    }
+
+    private static Matcher<Iterable<? super String>> hasItemContaining(String first, String second) {
+        return hasItem(both(containsString(first)).and(containsString(second)));
+    }
+
+}
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionEnumIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionEnumIT.java
index bb9eec3b3..b18aac03a 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionEnumIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionEnumIT.java
@@ -27,7 +27,7 @@
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 
 /*
@@ -46,7 +46,7 @@ public static void generateClasses() throws IOException {
         schemaRule.generateAndCompile("/schema/description/descriptionEnum.json", "com.example");
         File generatedJavaFile = schemaRule.generated("com/example/DescriptionEnum.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithDescription = javaDocBuilder.getClassByName("com.example.DescriptionEnum");
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionIT.java
index ce0b5181f..9dd4a0e53 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DescriptionIT.java
@@ -21,17 +21,20 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 import com.thoughtworks.qdox.model.JavaMethod;
-import com.thoughtworks.qdox.model.Type;
+import com.thoughtworks.qdox.model.JavaType;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
 
 public class DescriptionIT {
 
@@ -45,7 +48,7 @@ public static void generateClasses() throws IOException {
         schemaRule.generateAndCompile("/schema/description/description.json", "com.example");
         File generatedJavaFile = schemaRule.generated("com/example/Description.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithDescription = javaDocBuilder.getClassByName("com.example.Description");
@@ -73,7 +76,7 @@ public void descriptionAppearsInFieldJavadoc() {
     @Test
     public void descriptionAppearsInGetterJavadoc() {
 
-        JavaMethod javaMethod = classWithDescription.getMethodBySignature("getDescription", new Type[] {});
+        JavaMethod javaMethod = classWithDescription.getMethodBySignature("getDescription", Collections.emptyList());
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("A description for this property"));
@@ -83,7 +86,8 @@ public void descriptionAppearsInGetterJavadoc() {
     @Test
     public void descriptionAppearsInSetterJavadoc() {
 
-        JavaMethod javaMethod = classWithDescription.getMethodBySignature("setDescription", new Type[] { new Type("java.lang.String") });
+        final List<JavaType> parameterTypes = Collections.singletonList(new DefaultJavaClass("java.lang.String"));
+        JavaMethod javaMethod = classWithDescription.getMethodBySignature("setDescription", parameterTypes);
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("A description for this property"));
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DollarCommentIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DollarCommentIT.java
index 8d0599eea..d785ea02c 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DollarCommentIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/DollarCommentIT.java
@@ -16,11 +16,13 @@
 
 package org.jsonschema2pojo.integration;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 import com.thoughtworks.qdox.model.JavaMethod;
-import com.thoughtworks.qdox.model.Type;
+import com.thoughtworks.qdox.model.JavaType;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
+
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -28,6 +30,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.assertThat;
@@ -44,7 +48,7 @@ public static void generateClasses() throws IOException {
         schemaRule.generateAndCompile("/schema/dollar_comment/dollar_comment.json", "com.example");
         File generatedJavaFile = schemaRule.generated("com/example/DollarComment.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithDescription = javaDocBuilder.getClassByName("com.example.DollarComment");
@@ -72,7 +76,7 @@ public void dollarCommentAppearsInFieldJavadoc() {
     @Test
     public void dollarCommentAppearsInGetterJavadoc() {
 
-        JavaMethod javaMethod = classWithDescription.getMethodBySignature("getWithComment", new Type[] {});
+        JavaMethod javaMethod = classWithDescription.getMethodBySignature("getWithComment", Collections.emptyList());
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("JavaDoc linking to {@link #descriptionAndComment}"));
@@ -82,7 +86,8 @@ public void dollarCommentAppearsInGetterJavadoc() {
     @Test
     public void dollarCommentAppearsInSetterJavadoc() {
 
-        JavaMethod javaMethod = classWithDescription.getMethodBySignature("setWithComment", new Type[] { new Type("java.lang.String") });
+        final List<JavaType> parameterTypes = Collections.singletonList(new DefaultJavaClass("java.lang.String"));
+        JavaMethod javaMethod = classWithDescription.getMethodBySignature("setWithComment", parameterTypes);
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("JavaDoc linking to {@link #descriptionAndComment}"));
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/JavaNameIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/JavaNameIT.java
index fb810907c..ebad2885e 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/JavaNameIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/JavaNameIT.java
@@ -33,7 +33,7 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 
@@ -138,7 +138,7 @@ public void originalPropertyNamesAppearInJavaDoc() throws IOException {
         schemaRule.generateAndCompile("/schema/javaName/javaName.json", "com.example.javaname");
         File generatedJavaFile = schemaRule.generated("com/example/javaname/JavaName.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         JavaClass classWithDescription = javaDocBuilder.getClassByName("com.example.javaname.JavaName");
@@ -174,7 +174,7 @@ public void arrayRequiredAppearsInFieldJavadoc() throws IOException {
         schemaRule.generateAndCompile("/schema/javaName/javaNameWithRequiredProperties.json", "com.example.required");
         File generatedJavaFileWithRequiredProperties = schemaRule.generated("com/example/required/JavaNameWithRequiredProperties.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFileWithRequiredProperties);
 
         JavaClass classWithRequiredProperties = javaDocBuilder.getClassByName("com.example.required.JavaNameWithRequiredProperties");
@@ -192,7 +192,7 @@ public void inlineRequiredAppearsInFieldJavadoc() throws IOException {
         schemaRule.generateAndCompile("/schema/javaName/javaNameWithRequiredProperties.json", "com.example.required");
         File generatedJavaFileWithRequiredProperties = schemaRule.generated("com/example/required/JavaNameWithRequiredProperties.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFileWithRequiredProperties);
 
         JavaClass classWithRequiredProperties = javaDocBuilder.getClassByName("com.example.required.JavaNameWithRequiredProperties");
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredArrayIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredArrayIT.java
index 2ede45a5c..a64690ba0 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredArrayIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredArrayIT.java
@@ -21,17 +21,20 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 import com.thoughtworks.qdox.model.JavaMethod;
-import com.thoughtworks.qdox.model.Type;
+import com.thoughtworks.qdox.model.JavaType;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
 
 public class RequiredArrayIT extends RequiredIT {
     @ClassRule public static Jsonschema2PojoRule classSchemaRule = new Jsonschema2PojoRule();
@@ -44,7 +47,7 @@ public static void generateClasses() throws IOException {
         classSchemaRule.generateAndCompile("/schema/required/requiredArray.json", "com.example");
         File generatedJavaFile = classSchemaRule.generated("com/example/RequiredArray.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithRequired = javaDocBuilder.getClassByName("com.example.RequiredArray");
@@ -63,7 +66,7 @@ public void requiredAppearsInFieldJavadoc() {
     @Test
     public void requiredAppearsInGetterJavadoc() {
 
-        JavaMethod javaMethod = classWithRequired.getMethodBySignature("getRequiredProperty", new Type[] {});
+        JavaMethod javaMethod = classWithRequired.getMethodBySignature("getRequiredProperty", Collections.emptyList());
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("(Required)"));
@@ -73,7 +76,8 @@ public void requiredAppearsInGetterJavadoc() {
     @Test
     public void requiredAppearsInSetterJavadoc() {
 
-        JavaMethod javaMethod = classWithRequired.getMethodBySignature("setRequiredProperty", new Type[] { new Type("java.lang.String") });
+        final List<JavaType> parameterTypes = Collections.singletonList(new DefaultJavaClass("java.lang.String"));
+        JavaMethod javaMethod = classWithRequired.getMethodBySignature("setRequiredProperty", parameterTypes);
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("(Required)"));
@@ -81,7 +85,7 @@ public void requiredAppearsInSetterJavadoc() {
     }
 
     @Test
-    public void nonRequiredFiedHasNoRequiredText() {
+    public void nonRequiredFieldHasNoRequiredText() {
 
         JavaField javaField = classWithRequired.getFieldByName("nonRequiredProperty");
         String javaDocComment = javaField.getComment();
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredIT.java
index e54f112f0..aae9651ca 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/RequiredIT.java
@@ -21,17 +21,20 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 import com.thoughtworks.qdox.model.JavaMethod;
-import com.thoughtworks.qdox.model.Type;
+import com.thoughtworks.qdox.model.JavaType;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
 
 public class RequiredIT {
     @ClassRule public static Jsonschema2PojoRule classSchemaRule = new Jsonschema2PojoRule();
@@ -44,7 +47,7 @@ public static void generateClasses() throws IOException {
         classSchemaRule.generateAndCompile("/schema/required/required.json", "com.example");
         File generatedJavaFile = classSchemaRule.generated("com/example/Required.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithRequired = javaDocBuilder.getClassByName("com.example.Required");
@@ -63,7 +66,7 @@ public void requiredAppearsInFieldJavadoc() {
     @Test
     public void requiredAppearsInGetterJavadoc() {
 
-        JavaMethod javaMethod = classWithRequired.getMethodBySignature("getRequiredProperty", new Type[] {});
+        JavaMethod javaMethod = classWithRequired.getMethodBySignature("getRequiredProperty", Collections.emptyList());
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("(Required)"));
@@ -73,7 +76,8 @@ public void requiredAppearsInGetterJavadoc() {
     @Test
     public void requiredAppearsInSetterJavadoc() {
 
-        JavaMethod javaMethod = classWithRequired.getMethodBySignature("setRequiredProperty", new Type[] { new Type("java.lang.String") });
+        final List<JavaType> parameterTypes = Collections.singletonList(new DefaultJavaClass("java.lang.String"));
+        JavaMethod javaMethod = classWithRequired.getMethodBySignature("setRequiredProperty", parameterTypes);
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("(Required)"));
@@ -81,7 +85,7 @@ public void requiredAppearsInSetterJavadoc() {
     }
 
     @Test
-    public void nonRequiredFiedHasNoRequiredText() {
+    public void nonRequiredFieldHasNoRequiredText() {
 
         JavaField javaField = classWithRequired.getFieldByName("nonRequiredProperty");
         String javaDocComment = javaField.getComment();
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleEnumIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleEnumIT.java
index 1ee8fbe21..8225231ba 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleEnumIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleEnumIT.java
@@ -27,7 +27,7 @@
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 
 /*
@@ -45,7 +45,7 @@ public static void generateClasses() throws IOException {
         classSchemaRule.generateAndCompile("/schema/title/titleEnum.json", "com.example");
         File generatedJavaFile = classSchemaRule.generated("com/example/TitleEnum.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithTitle = javaDocBuilder.getClassByName("com.example.TitleEnum");
diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleIT.java
index f0a91dcc7..140ab7bbb 100644
--- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleIT.java
+++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TitleIT.java
@@ -21,17 +21,20 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaField;
 import com.thoughtworks.qdox.model.JavaMethod;
-import com.thoughtworks.qdox.model.Type;
+import com.thoughtworks.qdox.model.JavaType;
+import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
 
 public class TitleIT {
     @ClassRule public static Jsonschema2PojoRule classSchemaRule = new Jsonschema2PojoRule();
@@ -44,7 +47,7 @@ public static void generateClasses() throws IOException {
         classSchemaRule.generateAndCompile("/schema/title/title.json", "com.example");
         File generatedJavaFile = classSchemaRule.generated("com/example/Title.java");
 
-        JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
+        JavaProjectBuilder javaDocBuilder = new JavaProjectBuilder();
         javaDocBuilder.addSource(generatedJavaFile);
 
         classWithTitle = javaDocBuilder.getClassByName("com.example.Title");
@@ -72,7 +75,7 @@ public void descriptionAppearsInFieldJavadoc() {
     @Test
     public void descriptionAppearsInGetterJavadoc() {
 
-        JavaMethod javaMethod = classWithTitle.getMethodBySignature("getTitle", new Type[] {});
+        JavaMethod javaMethod = classWithTitle.getMethodBySignature("getTitle", Collections.emptyList());
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("A title for this property"));
@@ -82,7 +85,8 @@ public void descriptionAppearsInGetterJavadoc() {
     @Test
     public void descriptionAppearsInSetterJavadoc() {
 
-        JavaMethod javaMethod = classWithTitle.getMethodBySignature("setTitle", new Type[] { new Type("java.lang.String") });
+        final List<JavaType> parameterTypes = Collections.singletonList(new DefaultJavaClass("java.lang.String"));
+        JavaMethod javaMethod = classWithTitle.getMethodBySignature("setTitle", parameterTypes);
         String javaDocComment = javaMethod.getComment();
 
         assertThat(javaDocComment, containsString("A title for this property"));
diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/constructors/javadoc/javadocConstructor.json b/jsonschema2pojo-integration-tests/src/test/resources/schema/constructors/javadoc/javadocConstructor.json
new file mode 100644
index 000000000..f23045ec4
--- /dev/null
+++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/constructors/javadoc/javadocConstructor.json
@@ -0,0 +1,66 @@
+{
+  "type": "object",
+  "extends": {
+    "$ref": "#/$defs/super_type"
+  },
+  "properties": {
+    "non_documented": {
+      "type": "string",
+      "description": null,
+      "title": null,
+      "required": true
+    },
+    "tile_only": {
+      "type": "string",
+      "title": "A title_only title",
+      "required": true
+    },
+    "description_only": {
+      "type": "string",
+      "description": "A description_only description.",
+      "required": true
+    },
+    "title_and_description": {
+      "type": "string",
+      "title": "A title_and_description title.",
+      "description": "A title_and_description description",
+      "required": true
+    },
+    "non_required_non_documented": {
+      "type": "string"
+    },
+    "non_required_tile_only": {
+      "type": "string",
+      "title": "A non_required_tile_only title."
+    },
+    "non_required_description_only": {
+      "type": "string",
+      "description": "A non_required_description_only description"
+    },
+    "non_required_title_and_description": {
+      "type": "string",
+      "title": "A non_required_title_and_description title",
+      "description": "A non_required_title_and_description description."
+    }
+  },
+  "$defs": {
+    "super_type": {
+      "type": "object",
+      "properties": {
+        "undocumented_sc_property": {
+          "type": "number"
+        },
+        "sc_property_w_title": {
+          "type": "number",
+          "title": "A sc_property_w_title title",
+          "required": true
+        },
+        "sc_property_w_description": {
+          "type": "number",
+          "description": "A sc_property_w_description description",
+          "required": true
+        }
+      }
+    }
+  }
+}
\ No newline at end of file