diff --git a/jaxb-ri/docs/release-documentation/src/docbook/jaxb-changelog.xml b/jaxb-ri/docs/release-documentation/src/docbook/jaxb-changelog.xml
index f0ee42401..36ea1c21e 100644
--- a/jaxb-ri/docs/release-documentation/src/docbook/jaxb-changelog.xml
+++ b/jaxb-ri/docs/release-documentation/src/docbook/jaxb-changelog.xml
@@ -41,6 +41,9 @@
#1783: Dependency Exclusion for stax-ex in jaxb-bom is incompatible with dependency:analyze-dep-mgt
+
+ #1785: XJC ConstField generates empty javadoc comment blocks
+
dtd-parser #39: Parser parses #IMPLIED use attributes as NORMAL (and vice versa)
diff --git a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/generator/bean/field/ConstField.java b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/generator/bean/field/ConstField.java
index 0463cb9c4..613046b6f 100644
--- a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/generator/bean/field/ConstField.java
+++ b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/generator/bean/field/ConstField.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -54,8 +54,11 @@ final class ConstField extends AbstractField {
$ref = outline.ref.field(JMod.PUBLIC|JMod.STATIC|JMod.FINAL,
ptype!=null?ptype:implType, prop.getName(true), defaultValue );
- $ref.javadoc().append(prop.javadoc);
+ // Do not append empty javadoc.
+ if ( (prop.javadoc != null) && (prop.javadoc.length() > 0) )
+ $ref.javadoc().append(prop.javadoc);
+
annotate($ref);
}
diff --git a/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java b/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java
index 70b5439b2..dfd2341f1 100644
--- a/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java
+++ b/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,19 +16,28 @@
import com.sun.codemodel.JFormatter;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JType;
+import com.sun.codemodel.writer.SingleStreamCodeWriter;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
+import com.sun.tools.xjc.util.Util;
+
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.StringReader;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import junit.framework.TestCase;
+import org.junit.Assert;
import org.xml.sax.InputSource;
/**
@@ -38,6 +47,9 @@
*/
public class CodeGenTest extends TestCase {
+ // See com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl
+ protected static final String XML_API_TEST = "xjc-api.test";
+
public void testGh1460_Gh1064() throws Throwable {
SchemaCompiler sc = XJC.createSchemaCompiler();
sc.forcePackageName("ghbugs.b1460");
@@ -121,6 +133,93 @@ public void testIssue1750() throws FileNotFoundException, URISyntaxException {
}
}
+ /**
+ * Test issues #1785 for {@link com.sun.tools.xjc.generator.bean.field.ConstField}.
+ *
+ * @throws FileNotFoundException When the test schema file cannot be read.
+ * @throws URISyntaxException When the test {@link InputSource} cannot be parsed.
+ *
+ * @see Issue #1785
+ */
+ public void testIssue1785() throws FileNotFoundException, URISyntaxException, IOException {
+ String schemaFileName = "/schemas/issue1785/document.xsd";
+ String packageName = "org.example.issue1785";
+ String documentName = packageName + ".Document";
+ String suidFieldName = "serialVersionUID";
+ String codeModelDestPathName = "target/generated-test-sources/issue1785";
+
+ // Parse the XML schema.
+ SchemaCompiler sc = XJC.createSchemaCompiler();
+ sc.forcePackageName(packageName);
+ sc.parseSchema(getInputSource(schemaFileName));
+
+ // Generate the defined model.
+ S2JJAXBModel model = sc.bind();
+ Plugin[] extensions = null;
+ ErrorListener errorListener = new ConsoleErrorReporter();
+ JCodeModel cm = model.generateCode(extensions, errorListener);
+
+ // Assert Document class is modeled.
+ JDefinedClass dc = cm._getClass(documentName);
+ assertNotNull(documentName, dc);
+
+ // Assert serialVersionUID
+ assertTrue(suidFieldName, dc.fields().containsKey(suidFieldName));
+ assertNotNull(suidFieldName + " value", dc.fields().get(suidFieldName));
+
+ // Generate the Document classes to a directory, for review.
+ if ( Util.getSystemProperty(XML_API_TEST) != null ) {
+ File codeModelDestPath = new File(codeModelDestPathName);
+ if ( !codeModelDestPath.exists() )
+ codeModelDestPath.mkdirs();
+ cm.build(codeModelDestPath);
+ }
+
+ // Generate the Document classes to single String, for assertions.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ cm.build(new SingleStreamCodeWriter(baos));
+ String cmString = baos.toString(StandardCharsets.UTF_8);
+
+ // Assert non-empty javadoc blocks.
+ assertNonEmptyJavadocBlocks(cmString);
+ }
+
+ private void assertNonEmptyJavadocBlocks(String cmString) throws IOException {
+ int lineNo = 0;
+ try ( LineNumberReader lnr = new LineNumberReader(new StringReader(cmString)) ) {
+ StringBuilder javadocBlock = null;
+ String line;
+ while ( (line = lnr.readLine()) != null ) {
+ String trimLine = line.trim();
+ String javadoc = null;
+ if ( trimLine.startsWith("/**") ) {
+ lineNo = lnr.getLineNumber();
+ javadocBlock = new StringBuilder();
+ javadoc = trimLine.substring(3);
+ }
+ if ( javadocBlock != null ) {
+ if ( javadoc == null ) {
+ if ( trimLine.startsWith("*") && !trimLine.startsWith("*/") )
+ javadoc = trimLine.substring(1);
+ else
+ javadoc = trimLine;
+ }
+ int endIndex = 0;
+ if ( (endIndex = javadoc.lastIndexOf("*/")) != -1 ) {
+ javadocBlock.append(javadoc.substring(0, endIndex));
+ int javadocLen = javadocBlock.toString().trim().length();
+
+ // Assert current javadoc block length is not zero!
+ Assert.assertNotEquals("Empty javadoc at " + lineNo, 0, javadocLen);
+ javadocBlock = null;
+ }
+ else
+ javadocBlock.append(javadoc);
+ }
+ }
+ }
+ }
+
private InputSource getInputSource(String systemId) throws FileNotFoundException, URISyntaxException {
URL url = CodeGenTest.class.getResource(systemId);
File f = new File(url.toURI());
diff --git a/jaxb-ri/xjc/src/test/resources/schemas/issue1785/document.xsd b/jaxb-ri/xjc/src/test/resources/schemas/issue1785/document.xsd
new file mode 100644
index 000000000..d7730639c
--- /dev/null
+++ b/jaxb-ri/xjc/src/test/resources/schemas/issue1785/document.xsd
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A tautology!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+