http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml
new file mode 100644
index 0000000..d7d5605
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml
@@ -0,0 +1,31 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <!--
+      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.
+    -->
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-standard-services</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+    </parent>
+    
+    <artifactId>nifi-record-serialization-service-api</artifactId>
+    <packaging>jar</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java
new file mode 100644
index 0000000..5a71086
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.components.Validator;
+
+public class DataTypeValidator implements Validator {
+    private static final Set<String> validValues;
+    private static final Set<String> allowsFormatting;
+
+    static {
+        final Set<String> values = new HashSet<>();
+        values.add("string");
+        values.add("boolean");
+        values.add("byte");
+        values.add("char");
+        values.add("int");
+        values.add("long");
+        values.add("float");
+        values.add("double");
+        values.add("time");
+        values.add("date");
+        values.add("timestamp");
+        validValues = Collections.unmodifiableSet(values);
+
+        final Set<String> formattable = new HashSet<>();
+        formattable.add("date");
+        formattable.add("time");
+        formattable.add("timestmap");
+        allowsFormatting = Collections.unmodifiableSet(formattable);
+    }
+
+    @Override
+    public ValidationResult validate(final String subject, final String input, 
final ValidationContext context) {
+        final String[] splits = input.split("\\:");
+
+        final boolean valid;
+        if (splits.length == 2) {
+            final String type = splits[0].trim();
+            if (validValues.contains(type)) {
+                if (allowsFormatting.contains(splits[0].trim())) {
+                    valid = true;
+                } else {
+                    valid = false;
+                }
+            } else {
+                valid = false;
+            }
+        } else {
+            valid = validValues.contains(input.trim());
+        }
+
+        return new ValidationResult.Builder()
+            .subject(subject)
+            .input(input)
+            .valid(valid)
+            .explanation("Valid values for this property are: " + validValues
+                + ", where date, time, and timestamp may optionally contain a 
format (e.g., date:MM-dd-yyyy)")
+            .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java
new file mode 100644
index 0000000..d45a850
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+/**
+ * An Exception that can be thrown to indicate that data was read but could 
not properly be parsed
+ */
+public class MalformedRecordException extends Exception {
+    public MalformedRecordException(final String message) {
+        super(message);
+    }
+
+    public MalformedRecordException(final String message, final Throwable 
cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java
new file mode 100644
index 0000000..a0cfc79
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.nifi.serialization.record.Record;
+import org.apache.nifi.serialization.record.RecordSchema;
+
+/**
+ * <p>
+ * A RowRecordReader is responsible for parsing data and returning a record at 
a time
+ * in order to allow the caller to iterate over the records individually.
+ * </p>
+ *
+ * <p>
+ * PLEASE NOTE: This interface is still considered 'unstable' and may change 
in a non-backward-compatible
+ * manner between minor or incremental releases of NiFi.
+ * </p>
+ */
+public interface RecordReader extends Closeable {
+
+    /**
+     * Returns the next record in the stream or <code>null</code> if no more 
records are available.
+     *
+     * @param schema the schema to use in order to determine how to interprets 
the fields in a record
+     * @return the next record in the stream or <code>null</code> if no more 
records are available.
+     *
+     * @throws IOException if unable to read from the underlying data
+     * @throws MalformedRecordException if an unrecoverable failure occurs 
when trying to parse a record
+     */
+    Record nextRecord() throws IOException, MalformedRecordException;
+
+    /**
+     * @return a RecordSchema that is appropriate for the records in the stream
+     * @throws MalformedRecordException if an unrecoverable failure occurs 
when trying to parse the underlying data
+     */
+    RecordSchema getSchema() throws MalformedRecordException;
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java
new file mode 100644
index 0000000..7d6fa1c
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.nifi.serialization.record.RecordSet;
+
+/**
+ * <p>
+ * A ResultSetWriter is responsible for writing a ResultSet to a given {@link 
OutputStream}.
+ * </p>
+ *
+ * <p>
+ * PLEASE NOTE: This interface is still considered 'unstable' and may change 
in a non-backward-compatible
+ * manner between minor or incremental releases of NiFi.
+ * </p>
+ */
+public interface RecordSetWriter extends RecordWriter {
+    /**
+     * Writes the given result set to the given output stream
+     *
+     * @param recordSet the record set to serialize
+     * @param out the OutputStream to write to
+     * @return the results of writing the data
+     * @throws IOException if unable to write to the given OutputStream
+     */
+    WriteResult write(RecordSet recordSet, OutputStream out) throws 
IOException;
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java
new file mode 100644
index 0000000..2286f3f
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java
@@ -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.
+ */
+
+package org.apache.nifi.serialization;
+
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.logging.ComponentLog;
+
+/**
+ * <p>
+ * A Controller Service that is responsible for creating a {@link 
RecordSetWriter}.
+ * </p>
+ */
+public interface RecordSetWriterFactory extends ControllerService {
+    RecordSetWriter createWriter(ComponentLog logger);
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java
new file mode 100644
index 0000000..eef8d82
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.nifi.serialization.record.Record;
+
+public interface RecordWriter {
+    /**
+     * Writes the given result set to the given output stream
+     *
+     * @param recordSet the record set to serialize
+     * @param out the OutputStream to write to
+     * @return the results of writing the data
+     * @throws IOException if unable to write to the given OutputStream
+     */
+    WriteResult write(Record record, OutputStream out) throws IOException;
+
+    /**
+     * @return the MIME Type that the Result Set Writer produces. This will be 
added to FlowFiles using
+     *         the mime.type attribute.
+     */
+    String getMimeType();
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java
new file mode 100644
index 0000000..5ef4c7c
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.logging.ComponentLog;
+
+/**
+ * <p>
+ * A Controller Service that is responsible for creating a {@link 
RecordReader}.
+ * </p>
+ */
+public interface RowRecordReaderFactory extends ControllerService {
+    RecordReader createRecordReader(InputStream in, ComponentLog logger) 
throws MalformedRecordException, IOException;
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java
new file mode 100644
index 0000000..246e0af
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.stream.Collectors;
+
+import org.apache.nifi.serialization.record.DataType;
+import org.apache.nifi.serialization.record.RecordField;
+import org.apache.nifi.serialization.record.RecordSchema;
+
+public class SimpleRecordSchema implements RecordSchema {
+    private final List<RecordField> fields;
+    private final Map<String, Integer> fieldIndices;
+
+    public SimpleRecordSchema(final List<RecordField> fields) {
+        this.fields = Collections.unmodifiableList(new ArrayList<>(fields));
+        this.fieldIndices = new HashMap<>(fields.size());
+
+        int index = 0;
+        for (final RecordField field : fields) {
+            fieldIndices.put(field.getFieldName(), index++);
+        }
+    }
+
+    @Override
+    public List<RecordField> getFields() {
+        return fields;
+    }
+
+    @Override
+    public int getFieldCount() {
+        return fields.size();
+    }
+
+    @Override
+    public RecordField getField(final int index) {
+        return fields.get(index);
+    }
+
+    @Override
+    public List<DataType> getDataTypes() {
+        return getFields().stream().map(recordField -> 
recordField.getDataType())
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<String> getFieldNames() {
+        return getFields().stream().map(recordField -> 
recordField.getFieldName())
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public Optional<DataType> getDataType(final String fieldName) {
+        final OptionalInt idx = getFieldIndex(fieldName);
+        return idx.isPresent() ? 
Optional.of(fields.get(idx.getAsInt()).getDataType()) : Optional.empty();
+    }
+
+    private OptionalInt getFieldIndex(final String fieldName) {
+        final Integer index = fieldIndices.get(fieldName);
+        return index == null ? OptionalInt.empty() : OptionalInt.of(index);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof RecordSchema)) {
+            return false;
+        }
+
+        final RecordSchema other = (RecordSchema) obj;
+        return fields.equals(other.getFields());
+    }
+
+    @Override
+    public int hashCode() {
+        return 143 + 3 * fields.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("[");
+
+        for (int i = 0; i < fields.size(); i++) {
+            final RecordField field = fields.get(i);
+
+            sb.append("\"");
+            sb.append(field.getFieldName());
+            sb.append("\" : \"");
+            sb.append(field.getDataType());
+            sb.append("\"");
+
+            if (i < fields.size() - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java
new file mode 100644
index 0000000..3fb2741
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * <p>
+ * Provides information about what was written to an OutputStream by a {@link 
RecordSetWriter}.
+ * Instances of WriteResult are typically instantiated by calling the static 
method {@link WriteResult#of(int, Map)}
+ * or using {@link WriteResult#EMPTY}.
+ * </p>
+ *
+ * <p>
+ * PLEASE NOTE: This interface is still considered 'unstable' and may change 
in a non-backward-compatible
+ * manner between minor or incremental releases of NiFi.
+ * </p>
+ */
+public interface WriteResult {
+
+    /**
+     * @return the number of records written
+     */
+    int getRecordCount();
+
+    /**
+     * @return values that should be added to the FlowFile as attributes
+     */
+    Map<String, String> getAttributes();
+
+    /**
+     * Creates a WriteResult with the given record count and attributes
+     *
+     * @param recordCount the number of records written
+     * @param attributes the attributes to add to the FlowFile
+     * @return A {@link WriteResult} representing the given parameters
+     */
+    public static WriteResult of(final int recordCount, final Map<String, 
String> attributes) {
+        return new WriteResult() {
+            @Override
+            public int getRecordCount() {
+                return recordCount;
+            }
+
+            @Override
+            public Map<String, String> getAttributes() {
+                return attributes;
+            }
+        };
+    }
+
+    public static final WriteResult EMPTY = of(0, Collections.emptyMap());
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java
new file mode 100644
index 0000000..0c187f1
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class DataType {
+    private final RecordFieldType fieldType;
+    private final String format;
+
+    private final RecordSchema childSchema;
+    private final List<DataType> childTypes;
+
+    DataType(final RecordFieldType fieldType, final String format) {
+        this(fieldType, format, (RecordSchema) null);
+    }
+
+    DataType(final RecordFieldType fieldType, final String format, final 
RecordSchema childSchema) {
+        this.fieldType = fieldType;
+        this.format = format;
+        this.childSchema = childSchema;
+        this.childTypes = Collections.emptyList();
+    }
+
+    DataType(final RecordFieldType fieldType, final String format, final 
List<DataType> childTypes) {
+        this.fieldType = fieldType;
+        this.format = format;
+        this.childSchema = null;
+        this.childTypes = Collections.unmodifiableList(childTypes);
+    }
+
+
+    public String getFormat() {
+        return format;
+    }
+
+    public RecordFieldType getFieldType() {
+        return fieldType;
+    }
+
+    public Optional<RecordSchema> getChildRecordSchema() {
+        return Optional.ofNullable(childSchema);
+    }
+
+    public List<DataType> getPossibleTypes() {
+        return childTypes;
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 + 41 * fieldType.hashCode() + 41 * (format == null ? 0 : 
format.hashCode());
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof DataType)) {
+            return false;
+        }
+
+        final DataType other = (DataType) obj;
+        return fieldType.equals(other.fieldType) && ((format == null && 
other.format == null) || (format != null && format.equals(other.format)));
+    }
+
+    @Override
+    public String toString() {
+        if (format == null) {
+            return fieldType.toString();
+        } else {
+            return fieldType.toString() + ":" + format;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java
new file mode 100644
index 0000000..3968f50
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ListRecordSet implements RecordSet {
+    private final Iterator<Record> recordItr;
+    private final RecordSchema schema;
+
+    public ListRecordSet(final RecordSchema schema, final List<Record> 
records) {
+        this.schema = schema;
+
+        final List<Record> copy = new ArrayList<>(records);
+        recordItr = copy.iterator();
+    }
+
+    @Override
+    public RecordSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public Record next() {
+        return recordItr.hasNext() ? recordItr.next() : null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
new file mode 100644
index 0000000..f3f9024
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+public class MapRecord implements Record {
+    private final RecordSchema schema;
+    private final Map<String, Object> values;
+
+    public MapRecord(final RecordSchema schema, final Map<String, Object> 
values) {
+        this.schema = Objects.requireNonNull(schema);
+        this.values = Objects.requireNonNull(values);
+    }
+
+    @Override
+    public RecordSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public Object[] getValues() {
+        final Object[] values = new Object[schema.getFieldCount()];
+        int i = 0;
+        for (final String fieldName : schema.getFieldNames()) {
+            values[i++] = getValue(fieldName);
+        }
+        return values;
+    }
+
+    @Override
+    public Object getValue(final String fieldName) {
+        return values.get(fieldName);
+    }
+
+    @Override
+    public String getAsString(final String fieldName) {
+        final Optional<DataType> dataTypeOption = 
schema.getDataType(fieldName);
+        if (!dataTypeOption.isPresent()) {
+            return null;
+        }
+
+        return convertToString(getValue(fieldName), 
dataTypeOption.get().getFormat());
+    }
+
+    @Override
+    public String getAsString(final String fieldName, final String format) {
+        return convertToString(getValue(fieldName), format);
+    }
+
+    private String getFormat(final String optionalFormat, final 
RecordFieldType fieldType) {
+        return (optionalFormat == null) ? fieldType.getDefaultFormat() : 
optionalFormat;
+    }
+
+    private String convertToString(final Object value, final String format) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof java.sql.Date) {
+            java.sql.Date date = (java.sql.Date) value;
+            final long time = date.getTime();
+            return new SimpleDateFormat(getFormat(format, 
RecordFieldType.DATE)).format(new java.util.Date(time));
+        }
+        if (value instanceof java.util.Date) {
+            return new SimpleDateFormat(getFormat(format, 
RecordFieldType.DATE)).format((java.util.Date) value);
+        }
+        if (value instanceof Timestamp) {
+            java.sql.Timestamp date = (java.sql.Timestamp) value;
+            final long time = date.getTime();
+            return new SimpleDateFormat(getFormat(format, 
RecordFieldType.TIMESTAMP)).format(new java.util.Date(time));
+        }
+        if (value instanceof Time) {
+            java.sql.Time date = (java.sql.Time) value;
+            final long time = date.getTime();
+            return new SimpleDateFormat(getFormat(format, 
RecordFieldType.TIME)).format(new java.util.Date(time));
+        }
+
+        return value.toString();
+    }
+
+    @Override
+    public Long getAsLong(final String fieldName) {
+        return convertToLong(getValue(fieldName), fieldName);
+    }
+
+    private Long convertToLong(final Object value, final Object fieldDesc) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Number) {
+            return ((Number) value).longValue();
+        }
+        if (value instanceof String) {
+            return Long.parseLong((String) value);
+        }
+        if (value instanceof Date) {
+            return ((Date) value).getTime();
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Long for field " + fieldDesc);
+    }
+
+    @Override
+    public Integer getAsInt(final String fieldName) {
+        return convertToInt(getValue(fieldName), fieldName);
+    }
+
+    private Integer convertToInt(final Object value, final Object fieldDesc) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Number) {
+            return ((Number) value).intValue();
+        }
+        if (value instanceof String) {
+            return Integer.parseInt((String) value);
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Integer for field " + fieldDesc);
+    }
+
+
+    @Override
+    public Double getAsDouble(final String fieldName) {
+        return convertToDouble(getValue(fieldName), fieldName);
+    }
+
+    private Double convertToDouble(final Object value, final Object fieldDesc) 
{
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Number) {
+            return ((Number) value).doubleValue();
+        }
+        if (value instanceof String) {
+            return Double.parseDouble((String) value);
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Double for field " + fieldDesc);
+    }
+
+    @Override
+    public Float getAsFloat(final String fieldName) {
+        return convertToFloat(getValue(fieldName), fieldName);
+    }
+
+    private Float convertToFloat(final Object value, final Object fieldDesc) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Number) {
+            return ((Number) value).floatValue();
+        }
+        if (value instanceof String) {
+            return Float.parseFloat((String) value);
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Float for field " + fieldDesc);
+    }
+
+    @Override
+    public Record getAsRecord(String fieldName) {
+        return convertToRecord(getValue(fieldName), fieldName);
+    }
+
+    private Record convertToRecord(final Object value, final Object fieldDesc) 
{
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Record) {
+            return (Record) value;
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Record for field " + fieldDesc);
+    }
+
+
+    @Override
+    public Boolean getAsBoolean(final String fieldName) {
+        return convertToBoolean(getValue(fieldName), fieldName);
+    }
+
+    private Boolean convertToBoolean(final Object value, final Object 
fieldDesc) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Boolean) {
+            return (Boolean) value;
+        }
+        if (value instanceof String) {
+            final String string = (String) value;
+            if (string.equalsIgnoreCase("true") || 
string.equalsIgnoreCase("t")) {
+                return Boolean.TRUE;
+            }
+
+            if (string.equalsIgnoreCase("false") || string.equals("f")) {
+                return Boolean.FALSE;
+            }
+
+            throw new TypeMismatchException("Cannot convert String value to 
Boolean for field " + fieldDesc + " because it is not a valid boolean value");
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Boolean for field " + fieldDesc);
+    }
+
+    @Override
+    public Date getAsDate(final String fieldName) {
+        final Optional<DataType> dataTypeOption = 
schema.getDataType(fieldName);
+        if (!dataTypeOption.isPresent()) {
+            return null;
+        }
+
+        return convertToDate(getValue(fieldName), fieldName, 
dataTypeOption.get().getFormat());
+    }
+
+    @Override
+    public Date getAsDate(final String fieldName, final String format) {
+        return convertToDate(getValue(fieldName), fieldName, format);
+    }
+
+    private Date convertToDate(final Object value, final Object fieldDesc, 
final String format) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Date) {
+            return (Date) value;
+        }
+        if (value instanceof Number) {
+            final Long time = ((Number) value).longValue();
+            return new Date(time);
+        }
+        if (value instanceof java.sql.Date) {
+            return new Date(((java.sql.Date) value).getTime());
+        }
+        if (value instanceof String) {
+            try {
+                return new SimpleDateFormat(getFormat(format, 
RecordFieldType.DATE)).parse((String) value);
+            } catch (final ParseException e) {
+                throw new TypeMismatchException("Cannot convert String value 
to date for field " + fieldDesc + " because it is not in the correct format of: 
" + format, e);
+            }
+        }
+
+        throw new TypeMismatchException("Cannot convert value of type " + 
value.getClass() + " to Boolean for field " + fieldDesc);
+    }
+
+    @Override
+    public Object[] getAsArray(final String fieldName) {
+        return convertToArray(getValue(fieldName));
+    }
+
+    private Object[] convertToArray(final Object value) {
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Object[]) {
+            return (Object[]) value;
+        }
+
+        if (value instanceof List) {
+            return ((List<?>) value).toArray();
+        }
+
+        return new Object[] {value};
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 + 41 * values.hashCode() + 7 * schema.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof MapRecord)) {
+            return false;
+        }
+        final MapRecord other = (MapRecord) obj;
+        return schema.equals(other.schema) && values.equals(other.values);
+    }
+
+    @Override
+    public String toString() {
+        return "MapRecord[values=" + values + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java
new file mode 100644
index 0000000..ca85741
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.util.Date;
+
+public interface Record {
+
+    RecordSchema getSchema();
+
+    /**
+     * <p>
+     * Returns a view of the the values of the fields in this Record.
+     * </p>
+     *
+     * <b>NOTE:</b> The array that is returned may be an underlying array that 
is backing
+     * the contents of the Record. As such, modifying the array in any way may 
result in
+     * modifying the record.
+     *
+     * @return a view of the values of the fields in this Record
+     */
+    Object[] getValues();
+
+    Object getValue(String fieldName);
+
+    String getAsString(String fieldName);
+
+    String getAsString(String fieldName, String format);
+
+    Long getAsLong(String fieldName);
+
+    Integer getAsInt(String fieldName);
+
+    Double getAsDouble(String fieldName);
+
+    Float getAsFloat(String fieldName);
+
+    Record getAsRecord(String fieldName);
+
+    Boolean getAsBoolean(String fieldName);
+
+    Date getAsDate(String fieldName);
+
+    Date getAsDate(String fieldName, String format);
+
+    Object[] getAsArray(String fieldName);
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java
new file mode 100644
index 0000000..135ae66
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+public class RecordField {
+    private final String fieldName;
+    private final DataType dataType;
+
+    public RecordField(final String fieldName, final DataType dataType) {
+        this.fieldName = fieldName;
+        this.dataType = dataType;
+    }
+
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    public DataType getDataType() {
+        return dataType;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((dataType == null) ? 0 : 
dataType.hashCode());
+        result = prime * result + ((fieldName == null) ? 0 : 
fieldName.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        RecordField other = (RecordField) obj;
+        return dataType.equals(other.getDataType()) && 
fieldName.equals(other.getFieldName());
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java
new file mode 100644
index 0000000..8ad212b
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public enum RecordFieldType {
+    STRING("string"),
+    BOOLEAN("boolean"),
+    BYTE("byte"),
+    CHAR("char"),
+    SHORT("short"),
+    INT("int"),
+    BIGINT("bigint"),
+    LONG("long"),
+    FLOAT("float"),
+    DOUBLE("double"),
+    DATE("date", "yyyy-MM-dd"),
+    TIME("time", "HH:mm:ss"),
+    TIMESTAMP("timestamp", "yyyy-MM-dd HH:mm:ss"),
+    RECORD("record"),
+    CHOICE("choice"),
+    ARRAY("array");
+
+
+    private static final Map<String, RecordFieldType> SIMPLE_NAME_MAP = new 
HashMap<String, RecordFieldType>();
+
+    static {
+      for (RecordFieldType value : values()) {
+        SIMPLE_NAME_MAP.put(value.simpleName, value);
+      }
+    }
+
+    private final String simpleName;
+    private final String defaultFormat;
+    private final DataType defaultDataType;
+
+    private RecordFieldType(final String simpleName) {
+        this(simpleName, null);
+    }
+
+    private RecordFieldType(final String simpleName, final String 
defaultFormat) {
+        this.simpleName = simpleName;
+        this.defaultFormat = defaultFormat;
+        this.defaultDataType = new DataType(this, defaultFormat);
+    }
+
+    public String getDefaultFormat() {
+        return defaultFormat;
+    }
+
+    /**
+     * @return the DataType with the default format
+     */
+    public DataType getDataType() {
+        return defaultDataType;
+    }
+
+    public DataType getDataType(final String format) {
+        return new DataType(this, format);
+    }
+
+    /**
+     * Returns a Data Type that represents a "RECORD" type with the given 
schema.
+     *
+     * @param childSchema the Schema for the Record
+     * @return a DataType that represents a Record with the given schema, or 
<code>null</code> if this RecordFieldType
+     *         is not the RECORD type.
+     */
+    public DataType getDataType(final RecordSchema childSchema) {
+        if (this != RECORD) {
+            return null;
+        }
+
+        return new DataType(this, getDefaultFormat(), childSchema);
+    }
+
+    /**
+     * Returns a Data Type that represents a "CHOICE" of multiple possible 
types. This method is
+     * only applicable for a RecordFieldType of {@link #CHOICE}.
+     *
+     * @param possibleChildTypes the possible types that are allowable
+     * @return a DataType that represents a "CHOICE" of multiple possible 
types, or <code>null</code> if this RecordFieldType
+     *         is not the CHOICE type.
+     */
+    public DataType getDataType(final List<DataType> possibleChildTypes) {
+        if (this != CHOICE) {
+            return null;
+        }
+
+        return new DataType(this, getDefaultFormat(), possibleChildTypes);
+    }
+
+    public static RecordFieldType of(final String typeString) {
+      return SIMPLE_NAME_MAP.get(typeString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java
new file mode 100644
index 0000000..115fb51
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface RecordSchema {
+    /**
+     * @return the list of fields that are present in the schema
+     */
+    List<RecordField> getFields();
+
+    /**
+     * @return the number of fields in the schema
+     */
+    int getFieldCount();
+
+    /**
+     * @param index the 0-based index of which field to return
+     * @return the index'th field
+     *
+     * @throws IndexOutOfBoundsException if the index is < 0 or >= the number 
of fields (determined by {@link #getFieldCount()}).
+     */
+    RecordField getField(int index);
+
+    /**
+     * @return the data types of the fields
+     */
+    List<DataType> getDataTypes();
+
+    /**
+     * @return the names of the fields
+     */
+    List<String> getFieldNames();
+
+    /**
+     * @param fieldName the name of the field whose type is desired
+     * @return the RecordFieldType associated with the field that has the 
given name, or
+     *         <code>null</code> if the schema does not contain a field with 
the given name
+     */
+    Optional<DataType> getDataType(String fieldName);
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java
new file mode 100644
index 0000000..25bbcdc
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.io.IOException;
+
+public interface RecordSet {
+
+    /**
+     * @return the {@link RecordSchema} that applies to the records in this 
RecordSet
+     */
+    RecordSchema getSchema() throws IOException;
+
+    /**
+     * @return the next {@link Record} in the set or <code>null</code> if 
there are no more records
+     */
+    Record next() throws IOException;
+
+    public static RecordSet of(final RecordSchema schema, final Record... 
records) {
+        return new RecordSet() {
+            private int index = 0;
+
+            @Override
+            public RecordSchema getSchema() {
+                return schema;
+            }
+
+            @Override
+            public Record next() {
+                if (index >= records.length) {
+                    return null;
+                }
+
+                return records[index++];
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
new file mode 100644
index 0000000..e166918
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.nifi.serialization.SimpleRecordSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResultSetRecordSet implements RecordSet, Closeable {
+    private static final Logger logger = 
LoggerFactory.getLogger(ResultSetRecordSet.class);
+    private final ResultSet rs;
+    private final RecordSchema schema;
+    private final Set<String> rsColumnNames;
+
+    public ResultSetRecordSet(final ResultSet rs) throws SQLException {
+        this.rs = rs;
+        this.schema = createSchema(rs);
+
+        rsColumnNames = new HashSet<>();
+        final ResultSetMetaData metadata = rs.getMetaData();
+        for (int i = 0; i < metadata.getColumnCount(); i++) {
+            rsColumnNames.add(metadata.getColumnLabel(i + 1));
+        }
+    }
+
+    @Override
+    public RecordSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public Record next() throws IOException {
+        try {
+            if (rs.next()) {
+                return createRecord(rs);
+            }
+        } catch (final SQLException e) {
+            throw new IOException("Could not obtain next record from 
ResultSet", e);
+        }
+
+        return null;
+    }
+
+    @Override
+    public void close() {
+        try {
+            rs.close();
+        } catch (final SQLException e) {
+            logger.error("Failed to close ResultSet", e);
+        }
+    }
+
+    private Record createRecord(final ResultSet rs) throws SQLException {
+        final Map<String, Object> values = new 
HashMap<>(schema.getFieldCount());
+
+        for (final RecordField field : schema.getFields()) {
+            final String fieldName = field.getFieldName();
+
+            final Object value;
+            if (rsColumnNames.contains(fieldName)) {
+                value = rs.getObject(field.getFieldName());
+            } else {
+                value = null;
+            }
+
+            values.put(fieldName, value);
+        }
+
+        return new MapRecord(schema, values);
+    }
+
+    private static RecordSchema createSchema(final ResultSet rs) throws 
SQLException {
+        final ResultSetMetaData metadata = rs.getMetaData();
+        final int numCols = metadata.getColumnCount();
+        final List<RecordField> fields = new ArrayList<>(numCols);
+
+        for (int i = 0; i < numCols; i++) {
+            final int column = i + 1;
+            final int sqlType = metadata.getColumnType(column);
+
+            final RecordFieldType fieldType = getFieldType(sqlType);
+            final String fieldName = metadata.getColumnLabel(column);
+            final RecordField field = new RecordField(fieldName, 
fieldType.getDataType());
+            fields.add(field);
+        }
+
+        return new SimpleRecordSchema(fields);
+    }
+
+    private static RecordFieldType getFieldType(final int sqlType) {
+        switch (sqlType) {
+            case Types.ARRAY:
+                return RecordFieldType.ARRAY;
+            case Types.BIGINT:
+            case Types.ROWID:
+                return RecordFieldType.LONG;
+            case Types.BINARY:
+            case Types.LONGVARBINARY:
+            case Types.VARBINARY:
+                return RecordFieldType.ARRAY;
+            case Types.BIT:
+            case Types.BOOLEAN:
+                return RecordFieldType.BOOLEAN;
+            case Types.CHAR:
+                return RecordFieldType.CHAR;
+            case Types.DATE:
+                return RecordFieldType.DATE;
+            case Types.DECIMAL:
+            case Types.DOUBLE:
+            case Types.NUMERIC:
+            case Types.REAL:
+                return RecordFieldType.DOUBLE;
+            case Types.FLOAT:
+                return RecordFieldType.FLOAT;
+            case Types.INTEGER:
+                return RecordFieldType.INT;
+            case Types.SMALLINT:
+                return RecordFieldType.SHORT;
+            case Types.TINYINT:
+                return RecordFieldType.BYTE;
+            case Types.LONGNVARCHAR:
+            case Types.LONGVARCHAR:
+            case Types.NCHAR:
+            case Types.NULL:
+            case Types.NVARCHAR:
+            case Types.VARCHAR:
+                return RecordFieldType.STRING;
+            case Types.OTHER:
+            case Types.JAVA_OBJECT:
+                return RecordFieldType.RECORD;
+            case Types.TIME:
+            case Types.TIME_WITH_TIMEZONE:
+                return RecordFieldType.TIME;
+            case Types.TIMESTAMP:
+            case Types.TIMESTAMP_WITH_TIMEZONE:
+                return RecordFieldType.TIMESTAMP;
+        }
+
+        return RecordFieldType.STRING;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java
new file mode 100644
index 0000000..af5f909
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package org.apache.nifi.serialization.record;
+
+public class TypeMismatchException extends RuntimeException {
+    public TypeMismatchException(String message) {
+        super(message);
+    }
+
+    public TypeMismatchException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml
new file mode 100644
index 0000000..2a6f240
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml
@@ -0,0 +1,41 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <!--
+      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.
+    -->
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-record-serialization-services-bundle</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>nifi-record-serialization-services-nar</artifactId>
+    <packaging>nar</packaging>
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <source.skip>true</source.skip>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-standard-services-api-nar</artifactId>
+            <type>nar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-record-serialization-services</artifactId>
+            <version>1.2.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..581eac4
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,269 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+APACHE NIFI SUBCOMPONENTS:
+
+The Apache NiFi project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses. 
+
+The binary distribution of this product bundles 'Hamcrest' which is available
+under a BSD license.  More details found here: http://hamcrest.org.
+
+       Copyright (c) 2000-2006, www.hamcrest.org
+       All rights reserved.
+       
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are 
met:
+       
+       Redistributions of source code must retain the above copyright notice, 
this list of
+       conditions and the following disclaimer. Redistributions in binary form 
must reproduce
+       the above copyright notice, this list of conditions and the following 
disclaimer in
+       the documentation and/or other materials provided with the distribution.
+       
+       Neither the name of Hamcrest nor the names of its contributors may be 
used to endorse
+       or promote products derived from this software without specific prior 
written
+       permission.
+       
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
IS" AND ANY
+       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT
+       SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT,
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED
+       TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN
+       CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY
+       WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH
+       DAMAGE.
+
+This product bundles 'asm' which is available under a 3-Clause BSD style 
license.
+For details see http://asm.ow2.org/asmdex-license.html
+
+    Copyright (c) 2012 France Télécom
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the names of its
+       contributors may be used to endorse or promote products derived from
+       this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+    THE POSSIBILITY OF SUCH DAMAGE.
+

Reply via email to