Repository: gojek/feast
Pull request #262 (2019-10-19 13:45:59)

Clean up the Maven build
Hi folks!

There are three main themes here:

1. The pebble that got me rolling, this was giving us a headache while trying to work:

   Fix the `core` module dependency on `ingestion` so that Maven resolves it as an inter-project dep, without requiring it to be `install`ed to (local) repository and mucking with the version as you work.
1. Use [`<dependencyManagement>`] in parent POM for common dependencies and families—version drift between modules on things like gRPC and Google Cloud deps will bring more pain in the long run than any short-term convenience of letting them differ between modules I think. This makes it easy to control that consistently.
1. Avoid (re)defining `<properties>` in submodule POMs—similar reasoning  as dependencies: drift leads to suffering. If you build only a subset of modules at a time, effective values may differ based on how Maven orders the build.

   Also avoid repeating things that inherit from the parent POM.

I got a little carried away and enabled `-Xlint`. That's opinionated, so it's a separate commit I can remove if you're opposed to it.

I needed to massage dependency versions slightly, for instance `grpcVersion` was set to a few different values in different modules and I picked what appeared to be most common for current Beam / Google Cloud deps in the tree which finally got Maven's resolver happy and no bincompat issues from tests.

This passes `mvn verify`, let's see how it fares in CI…

~~Oh, finally, I did not yet touch the `sdk/java` module that was added in the last day or two, because it is not currently a child of the root POM. I really believe that it should be for the same reasoning of version consistency pain above, so I may push another commit making it so.~~ This is done. Let me know if you don't want that.

/cc @smadarasmi 

[`<dependencyManagement>`]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management

feast-ci-bot: @ches: GitHub didn't allow me to request PR reviews from the following users: smadarasmi.

Note that only [gojek members](https://github.com/orgs/gojek/people) and repo collaborators can review this PR, and authors cannot review their own PRs.

<details>

In response to [this](https://github.com/gojek/feast/pull/262):

>Hi folks!
>
>There are three main themes here:
>
>1. The pebble that got me rolling, this was giving us a headache while trying to work:
>
>   Fix the `core` module dependency on `ingestion` so that Maven resolves it as an inter-project dep, without requiring it to be `install`ed to (local) repository and mucking with the version as you work.
>1. Use [`<dependencyManagement>`] in parent POM for common dependencies and families—version drift between modules on things like gRPC and Google Cloud deps will bring more pain in the long run than any short-term convenience of letting them differ between modules I think. This makes it easy to control that consistently.
>1. Avoid (re)defining `<properties>` in submodule POMs—similar reasoning  as dependencies: drift leads to suffering. If you build only a subset of modules at a time, effective values may differ based on how Maven orders the build.
>
>   Also avoid repeating things that inherit from the parent POM.
>
>I got a little carried away and enabled `-Xlint`. That's opinionated, so it's a separate commit I can remove if you're opposed to it.
>
>I needed to massage dependency versions slightly, for instance `grpcVersion` was set to a few different values in different modules and I picked what appeared to be most common for current Beam / Google Cloud deps in the tree which finally got Maven's resolver happy and no bincompat issues from tests.
>
>This passes `mvn verify`, let's see how it fares in CI…
>
>Oh, finally, I did not yet touch the `sdk/java` module that was added in the last day or two, because it is not currently a child of the root POM. I really believe that it should be for the same reasoning of version consistency pain above, so I may push another commit making it so. Let me know if you don't want that.
>
>/cc @smadarasmi 
>
>[`<dependencyManagement>`]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
feast-ci-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/gojek/feast/pull/262#" title="Author self-approved">ches</a>*
To fully approve this pull request, please assign additional approvers.
We suggest the following additional approver: **zhilingc**

If they are not already assigned, you can assign the PR to them by writing `/assign @zhilingc` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=gojek%2Ffeast).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/gojek/feast/blob/0.3-dev/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["zhilingc"]} -->
feast-ci-bot: Hi @ches. Thanks for your PR.

I'm waiting for a [gojek](https://github.com/orgs/gojek/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/gojek/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=gojek%2Ffeast).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

ches: I've made `sdk/java` a child module of the main build now.
ches: Thanks for the review!

I've signed the CLA individually, I'll see about the steps for us to have a corporate signatory this week.

It might be good to put setup of a CLA bot in the backlog.
woop: > Thanks for the review!
> 
> I've signed the CLA individually, I'll see about the steps for us to have a corporate signatory this week.
> 
> It might be good to put setup of a CLA bot in the backlog.

Great thanks. I have added it as a note in our project backlog!
ches: Rebased to fix conflicts. Needed to trivially touch source code this time, for the rename of `ImportJobPipelineOptions` to `ImportOptions` which must have happened since the version in the binary build of `ingestion` last published to Jitpack. Hopefully that workflow is no longer needed ☺️ 

Patch:
diff --git a/core/pom.xml b/core/pom.xml
index 12574876d..e4c63bf84 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -19,14 +19,15 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>feast</groupId>
         <artifactId>feast-parent</artifactId>
         <version>${revision}</version>
     </parent>
-    <artifactId>feast-core</artifactId>
-    <packaging>jar</packaging>
+
     <name>Feast Core</name>
+    <artifactId>feast-core</artifactId>
 
     <build>
         <plugins>
@@ -78,46 +79,32 @@
         </plugins>
     </build>
 
-    <repositories>
-        <repository>
-            <id>jcenter</id>
-            <url>https://jcenter.bintray.com/</url>
-        </repository>
-        <repository>
-            <id>jitpack.io</id>
-            <url>https://jitpack.io</url>
-        </repository>
-    </repositories>
-
     <dependencies>
         <dependency>
-            <groupId>com.github.gojek.feast</groupId>
+            <groupId>feast</groupId>
             <artifactId>feast-ingestion</artifactId>
-            <version>9428b230a5</version>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+          <groupId>javax.inject</groupId>
+          <artifactId>javax.inject</artifactId>
+          <version>1</version>
         </dependency>
         <!--compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
-            <version>${springBootVersion}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <!--compile 'org.springframework.boot:spring-boot-starter-log4j2'-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-log4j2</artifactId>
-            <version>${springBootVersion}</version>
         </dependency>
         <!--compile 'org.lognet:grpc-spring-boot-starter:2.4.1'-->
         <dependency>
             <groupId>org.lognet</groupId>
             <artifactId>grpc-spring-boot-starter</artifactId>
-            <version>2.4.1</version>
         </dependency>
         <!--compile "org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}"-->
         <dependency>
@@ -129,47 +116,35 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
-            <version>${springBootVersion}</version>
         </dependency>
 
         <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-configuration-processor</artifactId>
-            <version>${springBootVersion}</version>
         </dependency>
 
 
-        <!--compile "io.grpc:grpc-netty:${grpcVersion}"-->
-        <dependency>
-            <groupId>io.grpc</groupId>
-            <artifactId>grpc-netty</artifactId>
-            <version>${grpcVersion}</version>
-        </dependency>
         <!--compile "io.grpc:grpc-services:${grpcVersion}"-->
         <dependency>
             <groupId>io.grpc</groupId>
             <artifactId>grpc-services</artifactId>
-            <version>${grpcVersion}</version>
         </dependency>
         <!--compile "io.grpc:grpc-stub:${grpcVersion}"-->
         <dependency>
             <groupId>io.grpc</groupId>
             <artifactId>grpc-stub</artifactId>
-            <version>${grpcVersion}</version>
         </dependency>
         <!--compile "com.google.protobuf:protobuf-java-util:${protobufVersion}"-->
         <dependency>
             <groupId>com.google.protobuf</groupId>
             <artifactId>protobuf-java-util</artifactId>
-            <version>${protobufVersion}</version>
         </dependency>
 
         <!--compile 'com.google.guava:guava:26.0-jre'-->
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>26.0-jre</version>
         </dependency>
         <!--compile 'com.google.code.gson:gson:2.8.5'-->
         <dependency>
@@ -177,18 +152,6 @@
             <artifactId>gson</artifactId>
             <version>2.8.5</version>
         </dependency>
-        <!--compile 'commons-codec:commons-codec:1.10'-->
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-            <version>1.10</version>
-        </dependency>
-        <!--compile 'joda-time:joda-time:2.9.9'-->
-        <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
-            <version>2.9.9</version>
-        </dependency>
         <dependency>
             <groupId>com.google.api-client</groupId>
             <artifactId>google-api-client</artifactId>
@@ -200,153 +163,28 @@
             <version>v1b3-rev266-1.25.0</version>
         </dependency>
 
-        <!--compile 'org.jdbi:jdbi3:3.0.0-beta2'-->
-        <dependency>
-            <groupId>org.jdbi</groupId>
-            <artifactId>jdbi3</artifactId>
-            <version>3.0.0-beta2</version>
-        </dependency>
-        <!--compile 'org.jdbi:jdbi3-sqlobject:3.4.0'-->
-        <dependency>
-            <groupId>org.jdbi</groupId>
-            <artifactId>jdbi3-sqlobject</artifactId>
-            <version>3.4.0</version>
-        </dependency>
-        <!--compile 'org.postgresql:postgresql:42.2.5'-->
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-            <version>42.2.5</version>
-        </dependency>
         <!--compile 'org.hibernate:hibernate-core:5.3.6.Final'-->
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
             <version>5.3.6.Final</version>
         </dependency>
-        <!--compile 'com.google.cloud.bigtable:bigtable-hbase-1.x:1.5.0'-->
-        <dependency>
-            <groupId>com.google.cloud.bigtable</groupId>
-            <artifactId>bigtable-hbase-2.x-shaded</artifactId>
-            <version>1.5.0</version>
-        </dependency>
-        <!--compile 'com.google.cloud:google-cloud-bigquery:1.48.0'-->
-        <dependency>
-            <groupId>com.google.cloud</groupId>
-            <artifactId>google-cloud-bigquery</artifactId>
-            <version>1.48.0</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.cloud</groupId>
-            <artifactId>google-cloud-nio</artifactId>
-            <version>0.83.0-alpha</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.flink</groupId>
-            <artifactId>flink-clients_2.11</artifactId>
-            <version>1.5.5</version>
-        </dependency>
-
-        <!-- Jackson due to jinjava dependency problems -->
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <version>2.9.9.1</version>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-            <version>2.9.9</version>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <version>2.9.9</version>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.dataformat</groupId>
-            <artifactId>jackson-dataformat-yaml</artifactId>
-            <version>2.9.9</version>
-        </dependency>
-
-        <!--compile 'com.github.spullara.mustache.java:compiler:0.9.5'-->
-        <dependency>
-            <groupId>com.github.spullara.mustache.java</groupId>
-            <artifactId>compiler</artifactId>
-            <version>0.9.5</version>
-        </dependency>
-        <dependency>
-            <groupId>com.hubspot.jinjava</groupId>
-            <artifactId>jinjava</artifactId>
-            <version>2.4.12</version>
-            <!--exclude jackson-->
-            <exclusions>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-databind</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-core</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-annotations</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <!--compile 'io.micrometer:micrometer-core:1.0.7'-->
-        <dependency>
-            <groupId>io.micrometer</groupId>
-            <artifactId>micrometer-core</artifactId>
-            <version>1.0.7</version>
-        </dependency>
-        <!--compile 'io.micrometer:micrometer-registry-prometheus:1.0.7'-->
-        <dependency>
-            <groupId>io.micrometer</groupId>
-            <artifactId>micrometer-registry-statsd</artifactId>
-            <version>1.0.7</version>
-        </dependency>
-        <dependency>
-            <groupId>com.datadoghq</groupId>
-            <artifactId>java-dogstatsd-client</artifactId>
-            <version>2.6.1</version>
-        </dependency>
 
         <dependency>
             <groupId>org.apache.kafka</groupId>
             <artifactId>kafka-clients</artifactId>
-            <version>2.3.0</version>
-        </dependency>
-
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-exec</artifactId>
-            <version>1.3</version>
         </dependency>
 
         <!--compileOnly 'org.projectlombok:lombok:1.18.2'-->
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.18.2</version>
-            <scope>provided</scope>
         </dependency>
 
-        <!--testCompile "io.grpc:grpc-testing:${grpcVersion}"-->
-        <dependency>
-            <groupId>io.grpc</groupId>
-            <artifactId>grpc-testing</artifactId>
-            <version>${grpcVersion}</version>
-            <scope>test</scope>
-        </dependency>
         <!--testCompile 'org.hamcrest:hamcrest-all:1.3'-->
         <dependency>
             <groupId>org.hamcrest</groupId>
             <artifactId>hamcrest-all</artifactId>
-            <version>1.3</version>
-            <scope>test</scope>
         </dependency>
 
         <!--testCompile 'com.jayway.jsonpath:json-path-assert:2.2.0'-->
@@ -362,36 +200,14 @@
             <version>2.23.0</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>com.squareup.okhttp3</groupId>
-            <artifactId>mockwebserver</artifactId>
-            <version>3.11.0</version>
-            <scope>test</scope>
-        </dependency>
 
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-test</artifactId>
-            <version>5.0.8.RELEASE</version>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-test</artifactId>
-            <version>${springBootVersion}</version>
-            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-test-autoconfigure</artifactId>
-            <version>${springBootVersion}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-            <version>1.4.198</version>
-            <scope>test</scope>
         </dependency>
     </dependencies>
 </project>
diff --git a/core/src/main/java/feast/core/job/dataflow/DataflowJobManager.java b/core/src/main/java/feast/core/job/dataflow/DataflowJobManager.java
index 13767a20e..d94ed6118 100644
--- a/core/src/main/java/feast/core/job/dataflow/DataflowJobManager.java
+++ b/core/src/main/java/feast/core/job/dataflow/DataflowJobManager.java
@@ -17,8 +17,6 @@
 
 package feast.core.job.dataflow;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import com.google.api.services.dataflow.Dataflow;
 import com.google.api.services.dataflow.model.Job;
 import com.google.common.base.Strings;
@@ -35,7 +33,7 @@ import feast.core.model.FeatureSet;
 import feast.core.model.JobInfo;
 import feast.core.util.TypeConversion;
 import feast.ingestion.ImportJob;
-import feast.ingestion.options.ImportJobPipelineOptions;
+import feast.ingestion.options.ImportOptions;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -128,7 +126,7 @@ public class DataflowJobManager implements JobManager {
 
   private String submitDataflowJob(String jobName, List<FeatureSetSpec> featureSets, Store sink, boolean update) {
     try {
-      ImportJobPipelineOptions pipelineOptions = getPipelineOptions(jobName, featureSets, sink, update);
+      ImportOptions pipelineOptions = getPipelineOptions(jobName, featureSets, sink, update);
       DataflowPipelineJob pipelineResult = runPipeline(pipelineOptions);
       String jobId = waitForJobToRun(pipelineResult);
       return jobId;
@@ -138,11 +136,10 @@ public class DataflowJobManager implements JobManager {
     }
   }
 
-  private ImportJobPipelineOptions getPipelineOptions(String jobName, List<FeatureSetSpec> featureSets, Store sink,
+  private ImportOptions getPipelineOptions(String jobName, List<FeatureSetSpec> featureSets, Store sink,
       boolean update) throws InvalidProtocolBufferException {
     String[] args = TypeConversion.convertMapToArgs(defaultOptions);
-    ImportJobPipelineOptions pipelineOptions = PipelineOptionsFactory.fromArgs(args)
-        .as(ImportJobPipelineOptions.class);
+    ImportOptions pipelineOptions = PipelineOptionsFactory.fromArgs(args).as(ImportOptions.class);
     Printer printer = JsonFormat.printer();
     List<String> featureSetsJson = new ArrayList<>();
     for (FeatureSetSpec featureSet : featureSets) {
@@ -164,7 +161,7 @@ public class DataflowJobManager implements JobManager {
     return pipelineOptions;
   }
 
-  public DataflowPipelineJob runPipeline(ImportJobPipelineOptions pipelineOptions)
+  public DataflowPipelineJob runPipeline(ImportOptions pipelineOptions)
       throws IOException {
     return (DataflowPipelineJob) ImportJob
         .runPipeline(pipelineOptions);
diff --git a/core/src/main/java/feast/core/job/direct/DirectRunnerJobManager.java b/core/src/main/java/feast/core/job/direct/DirectRunnerJobManager.java
index 7bd241f61..623f4faed 100644
--- a/core/src/main/java/feast/core/job/direct/DirectRunnerJobManager.java
+++ b/core/src/main/java/feast/core/job/direct/DirectRunnerJobManager.java
@@ -30,7 +30,7 @@ import feast.core.job.Runner;
 import feast.core.model.JobInfo;
 import feast.core.util.TypeConversion;
 import feast.ingestion.ImportJob;
-import feast.ingestion.options.ImportJobPipelineOptions;
+import feast.ingestion.options.ImportOptions;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -74,7 +74,7 @@ public class DirectRunnerJobManager implements JobManager {
   public String startJob(String name, List<FeatureSetSpec> featureSetSpecs,
       StoreProto.Store sinkSpec) {
     try {
-      ImportJobPipelineOptions pipelineOptions = getPipelineOptions(featureSetSpecs, sinkSpec);
+      ImportOptions pipelineOptions = getPipelineOptions(featureSetSpecs, sinkSpec);
       PipelineResult pipelineResult = runPipeline(pipelineOptions);
       DirectJob directJob = new DirectJob(name, pipelineResult);
       jobs.add(directJob);
@@ -85,12 +85,11 @@ public class DirectRunnerJobManager implements JobManager {
     }
   }
 
-  private ImportJobPipelineOptions getPipelineOptions(List<FeatureSetSpec> featureSetSpecs,
+  private ImportOptions getPipelineOptions(List<FeatureSetSpec> featureSetSpecs,
       StoreProto.Store sink)
       throws InvalidProtocolBufferException {
     String[] args = TypeConversion.convertMapToArgs(defaultOptions);
-    ImportJobPipelineOptions pipelineOptions = PipelineOptionsFactory.fromArgs(args)
-        .as(ImportJobPipelineOptions.class);
+    ImportOptions pipelineOptions = PipelineOptionsFactory.fromArgs(args).as(ImportOptions.class);
     Printer printer = JsonFormat.printer();
     List<String> featureSetsJson = new ArrayList<>();
     for (FeatureSetSpec featureSetSpec : featureSetSpecs) {
@@ -136,7 +135,7 @@ public class DirectRunnerJobManager implements JobManager {
     jobs.remove(extId);
   }
 
-  public PipelineResult runPipeline(ImportJobPipelineOptions pipelineOptions)
+  public PipelineResult runPipeline(ImportOptions pipelineOptions)
       throws IOException {
     return ImportJob.runPipeline(pipelineOptions);
   }
diff --git a/ingestion/pom.xml b/ingestion/pom.xml
index 8bfbec7dc..d79637ecb 100644
--- a/ingestion/pom.xml
+++ b/ingestion/pom.xml
@@ -19,63 +19,21 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
-  <groupId>feast</groupId>
-  <version>${revision}</version>
-  <artifactId>feast-ingestion</artifactId>
-  <packaging>jar</packaging>
-  <name>Feast Ingestion</name>
 
-  <properties>
-    <revision>0.3.0-SNAPSHOT</revision>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  <parent>
+    <groupId>feast</groupId>
+    <artifactId>feast-parent</artifactId>
+    <version>${revision}</version>
+  </parent>
 
-    <org.apache.beam.version>2.16.0</org.apache.beam.version>
-    <com.google.cloud.version>1.91.0</com.google.cloud.version>
-    <grpcVersion>1.21.1</grpcVersion>
-    <protocVersion>3.6.1</protocVersion>
-    <protobufVersion>3.6.1</protobufVersion>
-  </properties>
+  <name>Feast Ingestion</name>
+  <artifactId>feast-ingestion</artifactId>
 
   <build>
-    <extensions>
-      <extension>
-        <groupId>kr.motd.maven</groupId>
-        <artifactId>os-maven-plugin</artifactId>
-        <version>1.6.0</version>
-      </extension>
-    </extensions>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.7.0</version>
-        <configuration>
-          <source>1.8</source>
-          <target>1.8</target>
-        </configuration>
-      </plugin>
       <plugin>
         <groupId>org.xolstice.maven.plugins</groupId>
         <artifactId>protobuf-maven-plugin</artifactId>
-        <version>0.5.1</version>
-        <configuration>
-          <protocArtifact>
-            com.google.protobuf:protoc:${protocVersion}:exe:${os.detected.classifier}
-          </protocArtifact>
-          <pluginId>grpc-java</pluginId>
-          <pluginArtifact>
-            io.grpc:protoc-gen-grpc-java:${grpcVersion}:exe:${os.detected.classifier}
-          </pluginArtifact>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>compile</goal>
-              <goal>compile-custom</goal>
-              <goal>test-compile</goal>
-            </goals>
-          </execution>
-        </executions>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -131,17 +89,12 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>3.0.1</version>
         <executions>
           <execution>
             <id>attach-javadocs</id>
             <goals>
               <goal>jar</goal>
             </goals>
-            <!-- TODO: Remove "doclint: none" and fix javadoc error instead -->
-            <configuration>
-              <doclint>none</doclint>
-            </configuration>
           </execution>
         </executions>
       </plugin>
@@ -155,6 +108,12 @@
       <version>3.0.0</version>
     </dependency>
 
+    <dependency>
+      <groupId>javax.validation</groupId>
+      <artifactId>validation-api</artifactId>
+      <version>2.0.1.Final</version>
+    </dependency>
+
     <dependency>
       <groupId>org.hibernate.validator</groupId>
       <artifactId>hibernate-validator</artifactId>
@@ -173,60 +132,62 @@
       <scope>provided</scope>
     </dependency>
 
-    <!-- Provides FileSystemProvider for GCS. -->
-    <dependency>
-      <groupId>com.google.cloud</groupId>
-      <artifactId>google-cloud-nio</artifactId>
-      <version>0.83.0-alpha</version>
-    </dependency>
-
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-stub</artifactId>
-      <version>1.21.1</version>
     </dependency>
 
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage</artifactId>
-      <version>${com.google.cloud.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-bigquery</artifactId>
-      <version>${com.google.cloud.version}</version>
     </dependency>
 
-    <!-- Hamcrest needs to be above mockito and junit so it can clobber their versions of hamcrest -->
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
       <artifactId>hamcrest-library</artifactId>
-      <version>1.3</version>
-      <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
-      <version>2.28.2</version>
-      <scope>test</scope>
     </dependency>
 
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.dataformat</groupId>
       <artifactId>jackson-dataformat-yaml</artifactId>
-      <version>2.9.9</version>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.module</groupId>
       <artifactId>jackson-module-jsonSchema</artifactId>
-      <version>2.9.9</version>
     </dependency>
 
     <dependency>
       <groupId>com.google.protobuf</groupId>
       <artifactId>protobuf-java</artifactId>
-      <version>${protobufVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.protobuf</groupId>
+      <artifactId>protobuf-java-util</artifactId>
     </dependency>
 
     <dependency>
@@ -239,7 +200,6 @@
     <dependency>
       <groupId>joda-time</groupId>
       <artifactId>joda-time</artifactId>
-      <version>2.9.9</version>
     </dependency>
 
     <dependency>
@@ -260,16 +220,9 @@
       <version>${org.apache.beam.version}</version>
     </dependency>
 
-    <dependency>
-      <groupId>org.apache.kafka</groupId>
-      <artifactId>kafka_2.12</artifactId>
-      <version>2.3.0</version>
-    </dependency>
-
     <dependency>
       <groupId>redis.clients</groupId>
       <artifactId>jedis</artifactId>
-      <version>3.1.0</version>
     </dependency>
     <dependency>
       <groupId>io.prometheus</groupId>
@@ -279,8 +232,11 @@
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
-      <version>1.16.22</version>
-      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
     </dependency>
 
     <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
@@ -289,30 +245,13 @@
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
       <version>1.2.3</version>
-    </dependency>
-
-    <!-- Used for generating test data -->
-    <dependency>
-      <groupId>com.fasterxml.jackson.dataformat</groupId>
-      <artifactId>jackson-dataformat-csv</artifactId>
-      <version>2.9.6</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.github.kstyrc</groupId>
-      <artifactId>embedded-redis</artifactId>
-      <version>0.6</version>
-      <scope>test</scope>
+      <scope>runtime</scope>
     </dependency>
 
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
-      <version>26.0-jre</version>
-      <scope>compile</scope>
     </dependency>
 
-
   </dependencies>
 </project>
diff --git a/ingestion/src/main/java/feast/ingestion/transform/ReadFromSource.java b/ingestion/src/main/java/feast/ingestion/transform/ReadFromSource.java
index 3c6e9c8f4..b95090384 100644
--- a/ingestion/src/main/java/feast/ingestion/transform/ReadFromSource.java
+++ b/ingestion/src/main/java/feast/ingestion/transform/ReadFromSource.java
@@ -3,7 +3,6 @@ package feast.ingestion.transform;
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Preconditions;
 import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.TextFormat;
 import feast.core.SourceProto.Source;
 import feast.core.SourceProto.SourceType;
 import feast.ingestion.values.FailedElement;
@@ -148,7 +147,7 @@ public abstract class ReadFromSource extends PTransform<PBegin, PCollectionTuple
                               FailedElement.newBuilder()
                                   .setTransformName("KafkaRecordToFeatureRow")
                                   .setJobName(context.getPipelineOptions().getJobName())
-                                  .setPayload(TextFormat.printToString(featureRow))
+                                  .setPayload(featureRow.toString())
                                   .setErrorMessage(error)
                                   .build());
                         } else {
diff --git a/pom.xml b/pom.xml
index a8377fe95..f3735945d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,19 +17,35 @@
 
 <project>
     <modelVersion>4.0.0</modelVersion>
+
+    <name>Feast Parent</name>
     <groupId>feast</groupId>
     <artifactId>feast-parent</artifactId>
     <version>${revision}</version>
     <packaging>pom</packaging>
-    <name>Feast Parent</name>
+
+    <modules>
+        <module>ingestion</module>
+        <module>core</module>
+        <module>serving</module>
+        <module>sdk/java</module>
+    </modules>
 
     <properties>
-        <revision>0.3.0</revision>
+        <revision>0.3.0-SNAPSHOT</revision>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <protocVersion>3.6.1</protocVersion>
-        <grpcVersion>1.14.0</grpcVersion>
-        <protobufVersion>3.6.1</protobufVersion>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <grpcVersion>1.17.1</grpcVersion>
+        <protocVersion>3.10.0</protocVersion>
+        <protobufVersion>3.10.0</protobufVersion>
         <springBootVersion>2.0.9.RELEASE</springBootVersion>
+        <org.apache.beam.version>2.16.0</org.apache.beam.version>
+        <com.google.cloud.version>1.91.0</com.google.cloud.version>
+        <hamcrest.version>1.3</hamcrest.version>
+        <micrometer.version>1.0.7</micrometer.version>
+        <!-- OpenCensus is used in grpc and Google's HTTP client libs in Cloud SDKs -->
+        <opencensus.version>0.21.0</opencensus.version>
     </properties>
 
     <distributionManagement>
@@ -43,28 +59,293 @@
         </repository>
     </distributionManagement>
 
-    <modules>
-        <module>ingestion</module>
-        <module>core</module>
-        <module>serving</module>
-    </modules>
+    <dependencyManagement>
+        <dependencies>
+            <!-- Google Cloud -->
+            <dependency>
+                <groupId>com.google.cloud</groupId>
+                <artifactId>google-cloud-bigquery</artifactId>
+                <version>${com.google.cloud.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.cloud</groupId>
+                <artifactId>google-cloud-storage</artifactId>
+                <version>${com.google.cloud.version}</version>
+            </dependency>
+
+            <!-- Provides FileSystemProvider for GCS. -->
+            <dependency>
+                <groupId>com.google.cloud</groupId>
+                <artifactId>google-cloud-nio</artifactId>
+                <version>0.83.0-alpha</version>
+            </dependency>
+
+            <dependency>
+              <groupId>io.opencensus</groupId>
+              <artifactId>opencensus-api</artifactId>
+              <version>${opencensus.version}</version>
+            </dependency>
+            <dependency>
+              <groupId>io.opencensus</groupId>
+              <artifactId>opencensus-contrib-grpc-util</artifactId>
+              <version>${opencensus.version}</version>
+            </dependency>
+            <dependency>
+              <groupId>io.opencensus</groupId>
+              <artifactId>opencensus-contrib-http-util</artifactId>
+              <version>${opencensus.version}</version>
+            </dependency>
+
+            <!-- gRPC -->
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-netty</artifactId>
+                <version>${grpcVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-netty-shaded</artifactId>
+                <version>${grpcVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-protobuf</artifactId>
+                <version>${grpcVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-services</artifactId>
+                <version>${grpcVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-stub</artifactId>
+                <version>${grpcVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.grpc</groupId>
+                <artifactId>grpc-testing</artifactId>
+                <version>${grpcVersion}</version>
+                <scope>test</scope>
+            </dependency>
+
+            <!-- Jackson -->
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-annotations</artifactId>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-core</artifactId>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>2.9.9.1</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.dataformat</groupId>
+                <artifactId>jackson-dataformat-csv</artifactId>
+                <version>2.9.6</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.dataformat</groupId>
+                <artifactId>jackson-dataformat-yaml</artifactId>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.module</groupId>
+                <artifactId>jackson-module-jsonSchema</artifactId>
+                <version>2.9.9</version>
+            </dependency>
+
+            <!-- Spring -->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-configuration-processor</artifactId>
+                <version>${springBootVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-devtools</artifactId>
+                <version>${springBootVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-actuator</artifactId>
+                <version>${springBootVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-log4j2</artifactId>
+                <version>${springBootVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-test</artifactId>
+                <version>${springBootVersion}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-web</artifactId>
+                <version>${springBootVersion}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.springframework.boot</groupId>
+                        <artifactId>spring-boot-starter-logging</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-test</artifactId>
+                <version>${springBootVersion}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-test-autoconfigure</artifactId>
+                <version>${springBootVersion}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-test</artifactId>
+                <version>5.0.8.RELEASE</version>
+                <scope>test</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.lognet</groupId>
+                <artifactId>grpc-spring-boot-starter</artifactId>
+                <version>2.4.1</version>
+            </dependency>
+
+            <!-- Logging -->
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.7.25</version>
+            </dependency>
+
+            <!-- Other Stuff -->
+            <dependency>
+                <groupId>commons-codec</groupId>
+                <artifactId>commons-codec</artifactId>
+                <version>1.10</version>
+            </dependency>
+            <dependency>
+              <groupId>com.datadoghq</groupId>
+              <artifactId>java-dogstatsd-client</artifactId>
+              <version>2.6.1</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>26.0-jre</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.protobuf</groupId>
+                <artifactId>protobuf-java</artifactId>
+                <version>${protobufVersion}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.protobuf</groupId>
+                <artifactId>protobuf-java-util</artifactId>
+                <version>${protobufVersion}</version>
+            </dependency>
+            <dependency>
+              <groupId>io.micrometer</groupId>
+              <artifactId>micrometer-core</artifactId>
+              <version>${micrometer.version}</version>
+            </dependency>
+            <dependency>
+              <groupId>io.micrometer</groupId>
+              <artifactId>micrometer-registry-statsd</artifactId>
+              <version>${micrometer.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>joda-time</groupId>
+                <artifactId>joda-time</artifactId>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.kafka</groupId>
+                <artifactId>kafka-clients</artifactId>
+                <version>2.3.0</version>
+            </dependency>
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>1.18.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>redis.clients</groupId>
+                <artifactId>jedis</artifactId>
+                <version>3.1.0</version>
+            </dependency>
+
+            <!-- Misc Testing -->
+            <dependency>
+                <groupId>com.github.kstyrc</groupId>
+                <artifactId>embedded-redis</artifactId>
+                <version>0.6</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-all</artifactId>
+                <version>${hamcrest.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-core</artifactId>
+                <version>${hamcrest.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-library</artifactId>
+                <version>${hamcrest.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.mockito</groupId>
+                <artifactId>mockito-core</artifactId>
+                <version>2.28.2</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 
     <build>
         <extensions>
             <extension>
                 <groupId>kr.motd.maven</groupId>
                 <artifactId>os-maven-plugin</artifactId>
-                <version>1.6.0</version>
+                <version>1.6.2</version>
             </extension>
         </extensions>
+
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.7.0</version>
+                <version>3.8.1</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
+                    <compilerArgs>
+                        <arg>-Xlint:all</arg>
+                          <!-- -Xdoclint:all breaks on a false positive in JDK < 9 -->
+                          <!-- https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8186647 -->
+                        <arg>-Xdoclint:-syntax</arg>
+                    </compilerArgs>
                 </configuration>
             </plugin>
             <plugin>
@@ -82,6 +363,16 @@
 
         <pluginManagement>
             <plugins>
+                <plugin>
+                    <groupId>io.fabric8</groupId>
+                    <artifactId>docker-maven-plugin</artifactId>
+                    <version>0.20.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>3.1.0</version>
+                </plugin>
                 <plugin>
                     <groupId>org.codehaus.mojo</groupId>
                     <artifactId>exec-maven-plugin</artifactId>
@@ -105,8 +396,9 @@
                 <plugin>
                     <groupId>org.xolstice.maven.plugins</groupId>
                     <artifactId>protobuf-maven-plugin</artifactId>
-                    <version>0.5.1</version>
+                    <version>0.6.1</version>
                     <configuration>
+                        <checkStaleness>true</checkStaleness>
                         <protocArtifact>
                             com.google.protobuf:protoc:${protocVersion}:exe:${os.detected.classifier}
                         </protocArtifact>
diff --git a/protos/feast/types/Value.proto b/protos/feast/types/Value.proto
index 2cdb2c924..065497f30 100644
--- a/protos/feast/types/Value.proto
+++ b/protos/feast/types/Value.proto
@@ -16,8 +16,6 @@
 
 syntax = "proto3";
 
-import "google/protobuf/timestamp.proto";
-
 package feast.types;
 
 option java_package = "feast.types";
diff --git a/sdk/java/pom.xml b/sdk/java/pom.xml
index e9690cff5..43465ad91 100644
--- a/sdk/java/pom.xml
+++ b/sdk/java/pom.xml
@@ -4,13 +4,18 @@
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
-  <groupId>com.gojek.feast</groupId>
+  <name>Feast SDK for Java</name>
   <artifactId>feast-client</artifactId>
-  <version>0.3-SNAPSHOT</version>
+
+  <parent>
+    <groupId>feast</groupId>
+    <artifactId>feast-parent</artifactId>
+    <version>${revision}</version>
+    <relativePath>../..</relativePath>
+  </parent>
 
   <properties>
-    <grpc.version>1.24.0</grpc.version>
-    <protobuf.version>3.10.0</protobuf.version>
+    <!-- TODO: Standardize other modules on JUnit 5 and move this to parent -->
     <junit.version>5.5.2</junit.version>
   </properties>
 
@@ -19,34 +24,28 @@
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-netty-shaded</artifactId>
-      <version>${grpc.version}</version>
     </dependency>
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-protobuf</artifactId>
-      <version>${grpc.version}</version>
     </dependency>
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-stub</artifactId>
-      <version>${grpc.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.protobuf</groupId>
       <artifactId>protobuf-java-util</artifactId>
-      <version>${protobuf.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.protobuf</groupId>
       <artifactId>protobuf-java</artifactId>
-      <version>${protobuf.version}</version>
     </dependency>
 
     <!-- Logging -->
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.8.0-beta4</version>
     </dependency>
 
     <!-- JUnit 5 -->
@@ -66,54 +65,15 @@
   </dependencies>
 
   <build>
-    <extensions>
-      <extension>
-        <groupId>kr.motd.maven</groupId>
-        <artifactId>os-maven-plugin</artifactId>
-        <version>1.6.2</version>
-      </extension>
-    </extensions>
     <plugins>
       <plugin>
         <groupId>org.xolstice.maven.plugins</groupId>
         <artifactId>protobuf-maven-plugin</artifactId>
-        <version>0.6.1</version>
-        <configuration>
-          <protocArtifact>com.google.protobuf:protoc:3.10.0:exe:${os.detected.classifier}
-          </protocArtifact>
-          <pluginId>grpc-java</pluginId>
-          <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.24.0:exe:${os.detected.classifier}
-          </pluginArtifact>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>compile</goal>
-              <goal>compile-custom</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.8.1</version>
-        <configuration>
-          <source>8</source>
-          <target>8</target>
-        </configuration>
-      </plugin>
-      <!-- For Junit 5 support -->
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.22.0</version>
       </plugin>
       <!-- Javadoc -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>3.1.0</version>
         <configuration>
           <nohelp>true</nohelp>
         </configuration>
@@ -121,4 +81,4 @@
     </plugins>
   </build>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/serving/pom.xml b/serving/pom.xml
index 4ed3d9111..fd24bcafc 100644
--- a/serving/pom.xml
+++ b/serving/pom.xml
@@ -20,15 +20,6 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
-  <properties>
-    <revision>0.3.0</revision>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <protocVersion>3.6.1</protocVersion>
-    <grpcVersion>1.21.0</grpcVersion>
-    <protobufVersion>3.6.1</protobufVersion>
-    <springBootVersion>2.0.9.RELEASE</springBootVersion>
-  </properties>
-
   <parent>
     <groupId>feast</groupId>
     <artifactId>feast-parent</artifactId>
@@ -37,17 +28,8 @@
 
   <artifactId>feast-serving</artifactId>
   <name>Feast Serving</name>
-  <packaging>jar</packaging>
 
   <repositories>
-    <repository>
-      <snapshots>
-        <enabled>false</enabled>
-      </snapshots>
-      <id>central</id>
-      <name>bintray</name>
-      <url>https://jcenter.bintray.com</url>
-    </repository>
     <repository>
       <id>spring-plugins</id>
       <name>Spring Plugins</name>
@@ -88,10 +70,15 @@
   </build>
 
   <dependencies>
+    <!-- TODO: SLF4J is being used via Lombok, but also jog4j - pick one -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-configuration-processor</artifactId>
-      <version>${springBootVersion}</version>
       <optional>true</optional>
     </dependency>
 
@@ -99,70 +86,44 @@
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
-      <version>${springBootVersion}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.springframework.boot</groupId>
-          <artifactId>spring-boot-starter-logging</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <!--compile 'org.springframework.boot:spring-boot-starter-log4j2'-->
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-log4j2</artifactId>
-      <version>${springBootVersion}</version>
     </dependency>
 
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-devtools</artifactId>
-      <version>${springBootVersion}</version>
       <optional>true</optional>
     </dependency>
 
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-web</artifactId>
-      <version>2.12.0</version>
-    </dependency>
-
     <!--compile 'org.lognet:grpc-spring-boot-starter:2.4.1'-->
     <dependency>
       <groupId>org.lognet</groupId>
       <artifactId>grpc-spring-boot-starter</artifactId>
-      <version>2.4.1</version>
     </dependency>
     <!--compile "org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}"-->
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-actuator</artifactId>
-      <version>${springBootVersion}</version>
     </dependency>
 
-    <!--compile "io.grpc:grpc-netty:${grpcVersion}"-->
-    <dependency>
-      <groupId>io.grpc</groupId>
-      <artifactId>grpc-netty</artifactId>
-      <version>${grpcVersion}</version>
-    </dependency>
     <!--compile "io.grpc:grpc-services:${grpcVersion}"-->
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-services</artifactId>
-      <version>${grpcVersion}</version>
     </dependency>
     <!--compile "io.grpc:grpc-stub:${grpcVersion}"-->
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-stub</artifactId>
-      <version>${grpcVersion}</version>
     </dependency>
     <!--compile "com.google.protobuf:protobuf-java-util:${protobufVersion}"-->
     <dependency>
       <groupId>com.google.protobuf</groupId>
       <artifactId>protobuf-java-util</artifactId>
-      <version>${protobufVersion}</version>
     </dependency>
 
     <dependency>
@@ -175,25 +136,16 @@
     <dependency>
       <groupId>redis.clients</groupId>
       <artifactId>jedis</artifactId>
-      <version>2.9.0</version>
     </dependency>
     <!--compile 'com.google.guava:guava:26.0-jre'-->
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
-      <version>26.0-jre</version>
-    </dependency>
-    <!--compile 'commons-codec:commons-codec:1.10'-->
-    <dependency>
-      <groupId>commons-codec</groupId>
-      <artifactId>commons-codec</artifactId>
-      <version>1.10</version>
     </dependency>
     <!--compile 'joda-time:joda-time:2.9.9'-->
     <dependency>
       <groupId>joda-time</groupId>
       <artifactId>joda-time</artifactId>
-      <version>2.9.9</version>
     </dependency>
     <!--compile 'io.jaegertracing:jaeger-client:0.31.0'-->
     <dependency>
@@ -207,80 +159,37 @@
       <version>0.31.0</version>
     </dependency>
     <dependency>
-      <groupId>io.opentracing.contrib</groupId>
-      <artifactId>opentracing-concurrent</artifactId>
-      <version>0.2.0</version>
-    </dependency>
-
-
-    <!--compile 'io.micrometer:micrometer-core:1.0.7'-->
-    <dependency>
-      <groupId>io.micrometer</groupId>
-      <artifactId>micrometer-core</artifactId>
-      <version>1.0.7</version>
-    </dependency>
-    <!--compile 'io.micrometer:micrometer-registry-prometheus:1.0.7'-->
-    <dependency>
-      <groupId>io.micrometer</groupId>
-      <artifactId>micrometer-registry-statsd</artifactId>
-      <version>1.0.7</version>
-    </dependency>
-    <dependency>
-      <groupId>com.datadoghq</groupId>
-      <artifactId>java-dogstatsd-client</artifactId>
-      <version>2.6.1</version>
+      <groupId>io.opentracing</groupId>
+      <artifactId>opentracing-noop</artifactId>
+      <version>0.31.0</version>
     </dependency>
 
     <!-- Google Cloud -->
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-bigquery</artifactId>
-      <version>1.91.0</version>
     </dependency>
 
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage</artifactId>
-      <version>1.91.0</version>
     </dependency>
 
-    <!-- OpenCensus, needed by Google Cloud -->
-    <dependency>
-      <groupId>io.opencensus</groupId>
-      <artifactId>opencensus-impl</artifactId>
-      <version>0.24.0</version>
-      <scope>runtime</scope>
-    </dependency>
-
-
     <!--compileOnly 'org.projectlombok:lombok:1.18.2'-->
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
-      <version>1.18.2</version>
-      <scope>provided</scope>
     </dependency>
 
     <!--testCompile "io.grpc:grpc-testing:${grpcVersion}"-->
     <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-testing</artifactId>
-      <version>${grpcVersion}</version>
-      <scope>test</scope>
     </dependency>
     <!--testCompile 'org.springframework.boot:spring-boot-starter-test'-->
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
-      <version>${springBootVersion}</version>
-      <scope>test</scope>
-    </dependency>
-    <!--testCompile 'com.github.kstyrc:embedded-redis:0.6'-->
-    <dependency>
-      <groupId>com.github.kstyrc</groupId>
-      <artifactId>embedded-redis</artifactId>
-      <version>0.6</version>
-      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.mockito</groupId>
@@ -289,20 +198,6 @@
       <scope>test</scope>
     </dependency>
 
-    <dependency>
-      <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter</artifactId>
-      <version>RELEASE</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava-testlib</artifactId>
-      <version>26.0-jre</version>
-      <scope>test</scope>
-    </dependency>
-
     <!-- Hibernate for formatting SQL string -->
     <dependency>
       <groupId>org.hibernate</groupId>
@@ -311,22 +206,12 @@
     </dependency>
 
     <!-- Utilities -->
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-collections4</artifactId>
-      <version>4.4</version>
-    </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.dataformat</groupId>
       <artifactId>jackson-dataformat-yaml</artifactId>
-      <version>2.9.9</version>
-      <scope>compile</scope>
     </dependency>
-
-
   </dependencies>
 
-
   <profiles>
     <profile>
       <id>profile-local</id>
@@ -352,7 +237,6 @@
           <plugin>
             <groupId>io.fabric8</groupId>
             <artifactId>docker-maven-plugin</artifactId>
-            <version>0.20.1</version>
             <executions>
               <execution>
                 <id>prepare-bigtable-emulator</id>
@@ -393,9 +277,9 @@
           </resource>
         </resources>
 
-
       </build>
     </profile>
+
     <profile>
       <id>profile-ci</id>
       <activation>
@@ -408,7 +292,6 @@
           <plugin>
             <groupId>io.fabric8</groupId>
             <artifactId>docker-maven-plugin</artifactId>
-            <version>0.20.1</version>
             <executions>
               <execution>
                 <id>prepare-bigtable-emulator</id>
diff --git a/serving/src/main/java/feast/serving/service/CachedSpecService.java b/serving/src/main/java/feast/serving/service/CachedSpecService.java
index dfb62eca5..4fdf3e147 100644
--- a/serving/src/main/java/feast/serving/service/CachedSpecService.java
+++ b/serving/src/main/java/feast/serving/service/CachedSpecService.java
@@ -9,8 +9,6 @@ import com.google.common.cache.LoadingCache;
 import feast.core.CoreServiceProto.GetFeatureSetsRequest;
 import feast.core.CoreServiceProto.GetFeatureSetsRequest.Filter;
 import feast.core.CoreServiceProto.GetFeatureSetsResponse;
-import feast.core.CoreServiceProto.GetStoresRequest;
-import feast.core.CoreServiceProto.GetStoresResponse;
 import feast.core.CoreServiceProto.UpdateStoreRequest;
 import feast.core.CoreServiceProto.UpdateStoreResponse;
 import feast.core.FeatureSetProto.FeatureSetSpec;


Test patch:
diff --git a/core/src/test/java/feast/core/job/dataflow/DataflowJobManagerTest.java b/core/src/test/java/feast/core/job/dataflow/DataflowJobManagerTest.java
index 4aad1de0c..ba017aa2f 100644
--- a/core/src/test/java/feast/core/job/dataflow/DataflowJobManagerTest.java
+++ b/core/src/test/java/feast/core/job/dataflow/DataflowJobManagerTest.java
@@ -37,7 +37,7 @@ import feast.core.StoreProto.Store.RedisConfig;
 import feast.core.StoreProto.Store.StoreType;
 import feast.core.config.FeastProperties.MetricsProperties;
 import feast.core.exception.JobExecutionException;
-import feast.ingestion.options.ImportJobPipelineOptions;
+import feast.ingestion.options.ImportOptions;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
@@ -93,8 +93,8 @@ public class DataflowJobManagerTest {
     String expectedExtJobId = "feast-job-0";
     String jobName = "job";
 
-    ImportJobPipelineOptions expectedPipelineOptions = PipelineOptionsFactory.fromArgs("")
-        .as(ImportJobPipelineOptions.class);
+    ImportOptions expectedPipelineOptions = PipelineOptionsFactory.fromArgs("")
+        .as(ImportOptions.class);
     expectedPipelineOptions.setRunner(DataflowRunner.class);
     expectedPipelineOptions.setProject("project");
     expectedPipelineOptions.setRegion("region");
@@ -105,8 +105,8 @@ public class DataflowJobManagerTest {
     expectedPipelineOptions
         .setFeatureSetSpecJson(Lists.newArrayList(printer.print(featureSetSpec)));
 
-    ArgumentCaptor<ImportJobPipelineOptions> captor = ArgumentCaptor
-        .forClass(ImportJobPipelineOptions.class);
+    ArgumentCaptor<ImportOptions> captor = ArgumentCaptor
+        .forClass(ImportOptions.class);
 
     DataflowPipelineJob mockPipelineResult = Mockito.mock(DataflowPipelineJob.class);
     when(mockPipelineResult.getState()).thenReturn(State.RUNNING);
@@ -116,7 +116,7 @@ public class DataflowJobManagerTest {
     String jobId = dfJobManager.startJob(jobName, Lists.newArrayList(featureSetSpec), store);
 
     verify(dfJobManager, times(1)).runPipeline(captor.capture());
-    ImportJobPipelineOptions actualPipelineOptions = captor.getValue();
+    ImportOptions actualPipelineOptions = captor.getValue();
 
     expectedPipelineOptions.setOptionsId(actualPipelineOptions.getOptionsId()); // avoid comparing this value
 
diff --git a/core/src/test/java/feast/core/job/direct/DirectRunnerJobManagerTest.java b/core/src/test/java/feast/core/job/direct/DirectRunnerJobManagerTest.java
index c89f758b9..93f2519c3 100644
--- a/core/src/test/java/feast/core/job/direct/DirectRunnerJobManagerTest.java
+++ b/core/src/test/java/feast/core/job/direct/DirectRunnerJobManagerTest.java
@@ -17,7 +17,7 @@ import feast.core.StoreProto;
 import feast.core.StoreProto.Store.RedisConfig;
 import feast.core.StoreProto.Store.StoreType;
 import feast.core.config.FeastProperties.MetricsProperties;
-import feast.ingestion.options.ImportJobPipelineOptions;
+import feast.ingestion.options.ImportOptions;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
@@ -68,8 +68,8 @@ public class DirectRunnerJobManagerTest {
 
     Printer printer = JsonFormat.printer();
 
-    ImportJobPipelineOptions expectedPipelineOptions = PipelineOptionsFactory.fromArgs("")
-        .as(ImportJobPipelineOptions.class);
+    ImportOptions expectedPipelineOptions = PipelineOptionsFactory.fromArgs("")
+        .as(ImportOptions.class);
     expectedPipelineOptions.setAppName("DirectRunnerJobManager");
     expectedPipelineOptions.setRunner(DirectRunner.class);
     expectedPipelineOptions.setBlockOnRun(false);
@@ -78,8 +78,8 @@ public class DirectRunnerJobManagerTest {
         .setFeatureSetSpecJson(Lists.newArrayList(printer.print(featureSetSpec)));
 
     String expectedJobId = "feast-job-0";
-    ArgumentCaptor<ImportJobPipelineOptions> pipelineOptionsCaptor = ArgumentCaptor
-        .forClass(ImportJobPipelineOptions.class);
+    ArgumentCaptor<ImportOptions> pipelineOptionsCaptor = ArgumentCaptor
+        .forClass(ImportOptions.class);
     ArgumentCaptor<DirectJob> directJobCaptor = ArgumentCaptor
         .forClass(DirectJob.class);
 
@@ -90,7 +90,7 @@ public class DirectRunnerJobManagerTest {
     verify(drJobManager, times(1)).runPipeline(pipelineOptionsCaptor.capture());
     verify(directJobRegistry, times(1)).add(directJobCaptor.capture());
 
-    ImportJobPipelineOptions actualPipelineOptions = pipelineOptionsCaptor.getValue();
+    ImportOptions actualPipelineOptions = pipelineOptionsCaptor.getValue();
     DirectJob jobStarted = directJobCaptor.getValue();
     expectedPipelineOptions.setOptionsId(actualPipelineOptions.getOptionsId()); // avoid comparing this value
 
diff --git a/ingestion/src/test/java/feast/store/FileStoreOptionsTest.java b/ingestion/src/test/java/feast/store/FileStoreOptionsTest.java
index dc6629bba..562944b49 100644
--- a/ingestion/src/test/java/feast/store/FileStoreOptionsTest.java
+++ b/ingestion/src/test/java/feast/store/FileStoreOptionsTest.java
@@ -20,7 +20,6 @@ package feast.store;
 import static org.junit.Assert.assertEquals;
 
 import com.google.common.collect.ImmutableMap;
-import feast.store.FileStoreOptions;
 import org.joda.time.Duration;
 import org.junit.Test;
 import feast.options.OptionsParser;
diff --git a/ingestion/src/test/java/feast/store/TextFileDynamicIOTest.java b/ingestion/src/test/java/feast/store/TextFileDynamicIOTest.java
index 0a52b4bc7..5f0eedb99 100644
--- a/ingestion/src/test/java/feast/store/TextFileDynamicIOTest.java
+++ b/ingestion/src/test/java/feast/store/TextFileDynamicIOTest.java
@@ -77,7 +77,6 @@ public class TextFileDynamicIOTest {
     List<Path> files = Files.walk(path).collect(Collectors.toList());
     List<String> lines = Lists.newArrayList();
     for (Path file : files) {
-      System.out.println(file);
       if (file.toFile().isFile()) {
         lines.addAll(Files.readAllLines(file));
       }
diff --git a/ingestion/src/test/resources/logback-test.xml b/ingestion/src/test/resources/logback-test.xml
index 9a301f3bc..429ae39ae 100644
--- a/ingestion/src/test/resources/logback-test.xml
+++ b/ingestion/src/test/resources/logback-test.xml
@@ -16,13 +16,13 @@
   -->
 
 <configuration>
-  <logger name="feast" level="DEBUG" />
+  <logger name="feast" level="WARN" />
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
       <pattern>%d{HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
     </encoder>
   </appender>
-  <root level="INFO">
+  <root level="WARN">
     <appender-ref ref="STDOUT"/>
   </root>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java b/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
index 509e24689..6b27f1a50 100644
--- a/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
+++ b/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
@@ -1,8 +1,6 @@
 package feast.serving.service;
 
 import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.hasItems;
-import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
@@ -10,9 +8,6 @@ import static org.mockito.MockitoAnnotations.initMocks;
 import com.google.common.collect.Lists;
 import feast.core.CoreServiceProto.GetFeatureSetsRequest;
 import feast.core.CoreServiceProto.GetFeatureSetsResponse;
-import feast.core.CoreServiceProto.GetStoresRequest;
-import feast.core.CoreServiceProto.GetStoresRequest.Filter;
-import feast.core.CoreServiceProto.GetStoresResponse;
 import feast.core.CoreServiceProto.UpdateStoreRequest;
 import feast.core.CoreServiceProto.UpdateStoreResponse;
 import feast.core.FeatureSetProto.FeatureSetSpec;
@@ -24,7 +19,6 @@ import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,7 +28,6 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.Mock;
-import redis.embedded.Redis;
 
 public class CachedSpecServiceTest {