This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 48edbeed90 NIFI-13329 - Updating the standard content viewer to render
an error message when there is an error formatting.
48edbeed90 is described below
commit 48edbeed9066a564bfe6fffff80778f4b603c46a
Author: Matt Gilman <[email protected]>
AuthorDate: Fri May 31 14:29:26 2024 -0400
NIFI-13329 - Updating the standard content viewer to render an error
message when there is an error formatting.
Co-authored-by: Pierre Villard <[email protected]>
Signed-off-by: Pierre Villard <[email protected]>
This closes #8905.
---
.../nifi-standard-content-viewer/pom.xml | 1 +
.../nifi/web/StandardContentViewerController.java | 138 +++++++++++----------
.../src/main/webapp/WEB-INF/jsp/format-error.jsp | 22 ++++
.../src/main/webapp/css/main.css | 30 +++++
4 files changed, 124 insertions(+), 67 deletions(-)
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
index 02095ac086..6eec34603d 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
@@ -57,6 +57,7 @@
<targetPath>WEB-INF/jsp</targetPath>
<includes>
<include>codemirror.jsp</include>
+ <include>format-error.jsp</include>
</includes>
<filtering>true</filtering>
</resource>
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
index e07d613713..e41ebec606 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
@@ -25,8 +25,9 @@ import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.io.DatumReader;
import org.apache.nifi.web.ViewableContent.DisplayMode;
-import org.apache.nifi.xml.processing.ProcessingException;
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
@@ -44,6 +45,8 @@ import java.util.Set;
public class StandardContentViewerController extends HttpServlet {
+ private static final Logger logger =
LoggerFactory.getLogger(StandardContentViewerController.class);
+
private static final Set<String> supportedMimeTypes = new HashSet<>();
static {
@@ -84,16 +87,15 @@ public class StandardContentViewerController extends
HttpServlet {
if (DisplayMode.Original.equals(content.getDisplayMode())) {
formatted = content.getContent();
} else {
- if ("application/json".equals(contentType)) {
- // format json
- final ObjectMapper mapper = new ObjectMapper();
- final Object objectJson =
mapper.readValue(content.getContentStream(), Object.class);
- formatted =
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectJson);
- } else if ("application/xml".equals(contentType) ||
"text/xml".equals(contentType)) {
- // format xml
- final StringWriter writer = new StringWriter();
-
- try {
+ try {
+ if ("application/json".equals(contentType)) {
+ // format json
+ final ObjectMapper mapper = new ObjectMapper();
+ final Object objectJson =
mapper.readValue(content.getContentStream(), Object.class);
+ formatted =
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectJson);
+ } else if ("application/xml".equals(contentType) ||
"text/xml".equals(contentType)) {
+ // format xml
+ final StringWriter writer = new StringWriter();
final StreamSource source = new
StreamSource(content.getContentStream());
final StreamResult result = new StreamResult(writer);
@@ -101,67 +103,69 @@ public class StandardContentViewerController extends
HttpServlet {
transformProvider.setIndent(true);
transformProvider.transform(source, result);
- } catch (final ProcessingException te) {
- throw new IOException("Unable to transform content as
XML: " + te, te);
- }
- // get the transformed xml
- formatted = writer.toString();
- } else if ("application/avro-binary".equals(contentType) ||
"avro/binary".equals(contentType) ||
"application/avro+binary".equals(contentType)) {
- final StringBuilder sb = new StringBuilder();
- sb.append("[");
- // Use Avro conversions to display logical type values in
human readable way.
- final GenericData genericData = new GenericData();
- genericData.addLogicalTypeConversion(new
Conversions.DecimalConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.DateConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.TimeMicrosConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.TimeMillisConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.TimestampMicrosConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.TimestampMillisConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.LocalTimestampMicrosConversion());
- genericData.addLogicalTypeConversion(new
TimeConversions.LocalTimestampMillisConversion());
- final DatumReader<GenericData.Record> datumReader = new
GenericDatumReader<>(null, null, genericData);
- try (final DataFileStream<GenericData.Record>
dataFileReader = new DataFileStream<>(content.getContentStream(), datumReader))
{
- while (dataFileReader.hasNext()) {
- final GenericData.Record record =
dataFileReader.next();
- final String formattedRecord =
genericData.toString(record);
- sb.append(formattedRecord);
- sb.append(",");
- // Do not format more than 10 MB of content.
- if (sb.length() > 1024 * 1024 * 2) {
- break;
+ // get the transformed xml
+ formatted = writer.toString();
+ } else if ("application/avro-binary".equals(contentType)
|| "avro/binary".equals(contentType) ||
"application/avro+binary".equals(contentType)) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ // Use Avro conversions to display logical type values
in human readable way.
+ final GenericData genericData = new GenericData();
+ genericData.addLogicalTypeConversion(new
Conversions.DecimalConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.DateConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.TimeMicrosConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.TimeMillisConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.TimestampMicrosConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.TimestampMillisConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.LocalTimestampMicrosConversion());
+ genericData.addLogicalTypeConversion(new
TimeConversions.LocalTimestampMillisConversion());
+ final DatumReader<GenericData.Record> datumReader =
new GenericDatumReader<>(null, null, genericData);
+ try (final DataFileStream<GenericData.Record>
dataFileReader = new DataFileStream<>(content.getContentStream(), datumReader))
{
+ while (dataFileReader.hasNext()) {
+ final GenericData.Record record =
dataFileReader.next();
+ final String formattedRecord =
genericData.toString(record);
+ sb.append(formattedRecord);
+ sb.append(",");
+ // Do not format more than 10 MB of content.
+ if (sb.length() > 1024 * 1024 * 2) {
+ break;
+ }
}
}
- }
- if (sb.length() > 1) {
- sb.deleteCharAt(sb.length() - 1);
+ if (sb.length() > 1) {
+ sb.deleteCharAt(sb.length() - 1);
+ }
+ sb.append("]");
+ final String json = sb.toString();
+
+ final ObjectMapper mapper = new ObjectMapper();
+ final Object objectJson = mapper.readValue(json,
Object.class);
+ formatted =
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectJson);
+
+ contentType = "application/json";
+ } else if ("text/x-yaml".equals(contentType) ||
"text/yaml".equals(contentType) || "text/yml".equals(contentType)
+ || "application/x-yaml".equals(contentType) ||
"application/x-yml".equals(contentType)
+ || "application/yaml".equals(contentType) ||
"application/yml".equals(contentType)) {
+ Yaml yaml = new Yaml();
+ // Parse the YAML file
+ final Object yamlObject =
yaml.load(content.getContentStream());
+ DumperOptions options = new DumperOptions();
+ options.setIndent(2);
+ options.setPrettyFlow(true);
+ // Fix below - additional configuration
+
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+ Yaml output = new Yaml(options);
+ formatted = output.dump(yamlObject);
+
+ } else {
+ // leave plain text alone when formatting
+ formatted = content.getContent();
}
- sb.append("]");
- final String json = sb.toString();
-
- final ObjectMapper mapper = new ObjectMapper();
- final Object objectJson = mapper.readValue(json,
Object.class);
- formatted =
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectJson);
-
- contentType = "application/json";
- } else if ("text/x-yaml".equals(contentType) ||
"text/yaml".equals(contentType) || "text/yml".equals(contentType)
- || "application/x-yaml".equals(contentType) ||
"application/x-yml".equals(contentType)
- || "application/yaml".equals(contentType) ||
"application/yml".equals(contentType)) {
- Yaml yaml = new Yaml();
- // Parse the YAML file
- final Object yamlObject =
yaml.load(content.getContentStream());
- DumperOptions options = new DumperOptions();
- options.setIndent(2);
- options.setPrettyFlow(true);
- // Fix below - additional configuration
- options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
- Yaml output = new Yaml(options);
- formatted = output.dump(yamlObject);
-
- } else {
- // leave plain text alone when formatting
- formatted = content.getContent();
+ } catch (final Throwable t) {
+ logger.warn("Unable to format FlowFile content", t);
+
this.getServletContext().getRequestDispatcher("/WEB-INF/jsp/format-error.jsp").include(request,
response);
+ return;
}
}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/format-error.jsp
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/format-error.jsp
new file mode 100644
index 0000000000..b91d657437
--- /dev/null
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/format-error.jsp
@@ -0,0 +1,22 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<link rel="stylesheet" href="../${project.build.finalName}/css/main.css"
type="text/css" />
+
+<div id="format-error">
+ Unable to format content. Please ensure the content type is correct
(defined by the 'mime.type' attribute of the FlowFile).
+</div>
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/css/main.css
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/css/main.css
new file mode 100644
index 0000000000..7aaa7e918a
--- /dev/null
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/css/main.css
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#format-error {
+ position: absolute;
+ right: 50px;
+ bottom: 50px;
+ left: 100px;
+ top: 104px;
+ border: 1px solid #aaa;
+ overflow: auto;
+ background-color: #fff;
+ font-style: italic;
+ padding: 5px;
+ font-size: 13px;
+}
\ No newline at end of file