Feed Exception Revise

1. Add compliation exception for missing Twitter4J library. Try to
expose this exception when create feed.
2. Tweaked 'invalid feed parameter exception'. Expose detailed exception
information to front end.
3. Related test cases fix.

Change-Id: Iee65b2a5365067c9ba2aa1615ac23f0ace41b51e
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1534
Reviewed-by: Michael Blow <mblow@apache.org>
Tested-by: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/feeds/connect-feed/connect-feed.0.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/feeds/connect-feed/connect-feed.0.ddl.aql
index 8a13210..9237c1e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/feeds/connect-feed/connect-feed.0.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/feeds/connect-feed/connect-feed.0.ddl.aql
@@ -37,10 +37,10 @@
 create dataset Tweets3 (Tweet)
 primary key id;
 
-create feed TwitterFeed using push_twitter(
-("type-name"="Tweet"),
-("format"="twitter-status"),
-("consumer.key"="********************"),
-("consumer.secret"="********************"),
-("access.token"="********************"),
-("access.token.secret"="********************"));
+create feed TwitterFeed using socket_adapter
+(
+    ("sockets"="127.0.0.1:10001"),
+    ("address-type"="IP"),
+    ("type-name"="Tweet"),
+    ("format"="adm")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 29998fd..5df39db 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -153,15 +153,15 @@
     <test-case FilePath="feeds">
       <compilation-unit name="twitter-feed">
         <output-dir compare="Text">twitter-feed</output-dir>
-        <expected-error>One or more parameters are missing from adapter configuration</expected-error>
-        <expected-error>Unknown source feed</expected-error>
+        <expected-error>Twitter4J library not found!</expected-error>
+        <expected-error>Unknown source feed: TwitterFeed</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="feeds">
       <compilation-unit name="revised-tweet-parser">
         <output-dir compare="Text">revised-tweet-parser</output-dir>
-        <expected-error>One or more parameters are missing from adapter configuration</expected-error>
-        <expected-error>Unknown source feed</expected-error>
+        <expected-error>Twitter4J library not found!</expected-error>
+        <expected-error>Unknown source feed: TwitterFeed</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="feeds">
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 8f859c7..96ac491 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -93,9 +93,9 @@
     public static final int OPERATORS_FEED_INTAKE_OPERATOR_DESCRIPTOR_CLASSLOADER_NOT_CONFIGURED = 3004;
     public static final int PARSER_DELIMITED_NONOPTIONAL_NULL = 3005;
     public static final int PARSER_DELIMITED_ILLEGAL_FIELD = 3006;
-    public static final int FEED_MANAGEMENT_ACTIVE_LIFE_CYCLE_EVENT_SUBSCRIBER_ACTIVE_JOB_FAILURE = 3007;
+    public static final int ADAPTER_TWITTER_TWITTER4J_LIB_NOT_FOUND = 3007;
     public static final int OPERATORS_FEED_INTAKE_OPERATOR_NODE_PUSHABLE_FAIL_AT_INGESTION = 3008;
-    public static final int OPERATORS_FEED_MSG_OPERATOR_NODE_PUSHABLE_INVALID_SUBSCRIBABLE_RUNTIME = 3009;
+    public static final int FEED_CREATE_FEED_DATATYPE_ERROR = 3009;
     public static final int PARSER_HIVE_NON_PRIMITIVE_LIST_NOT_SUPPORT = 3010;
     public static final int PARSER_HIVE_FIELD_TYPE = 3011;
     public static final int PARSER_HIVE_GET_COLUMNS = 3012;
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index bf9c6f9..a0bfab9 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -79,9 +79,9 @@
 3004 = Unable to create adapter as class loader not configured for library %1$s in dataverse %2$s
 3005 = At record: %1$s - Field %2$s is not privatean optional type so it cannot accept null value.
 3006 = Illegal field %1$s in closed type %2$s
-3007 = Failure in active job.
+3007 = Twitter4J library not found!
 3008 = Unable to ingest data
-3009 = Invalid subscribable runtime type %1$s
+3009 = Exception in get record type %1$s for feed
 3010 = Doesn't support Hive data with list of non-primitive types
 3011 = Can't get hive type for field of type %1$s
 3012 = Failed to get columns of record
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DatasourceFactoryProvider.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DatasourceFactoryProvider.java
index 1428863..41fc7e4 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DatasourceFactoryProvider.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DatasourceFactoryProvider.java
@@ -38,6 +38,7 @@
 import org.apache.asterix.external.util.ExternalDataUtils;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import twitter4j.conf.ConfigurationBuilder;
 
 public class DatasourceFactoryProvider {
 
@@ -108,6 +109,11 @@
             case ExternalDataConstants.READER_PUSH_TWITTER:
             case ExternalDataConstants.READER_PULL_TWITTER:
             case ExternalDataConstants.READER_USER_STREAM_TWITTER:
+                try {
+                    Class.forName("twitter4j.Twitter");
+                } catch (ClassNotFoundException e) {
+                    throw new RuntimeDataException(ErrorCode.ADAPTER_TWITTER_TWITTER4J_LIB_NOT_FOUND, e);
+                }
                 return new TwitterRecordReaderFactory();
             case ExternalDataConstants.ALIAS_SOCKET_ADAPTER:
             case ExternalDataConstants.SOCKET:
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
index 4596054..5150db3 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
@@ -19,20 +19,16 @@
 package org.apache.asterix.lang.aql.statement;
 
 import java.io.StringReader;
-import java.rmi.RemoteException;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.asterix.active.EntityId;
-import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.external.feed.management.FeedConnectionRequest;
-import org.apache.asterix.external.feed.policy.FeedPolicyAccessor;
 import org.apache.asterix.external.feed.watch.FeedActivityDetails;
 import org.apache.asterix.external.util.ExternalDataConstants;
-import org.apache.asterix.external.util.FeedUtils;
 import org.apache.asterix.lang.aql.parser.AQLParserFactory;
 import org.apache.asterix.lang.common.base.IParser;
 import org.apache.asterix.lang.common.base.IParserFactory;
@@ -179,7 +175,7 @@
                     .getTypeName();
             return outputType;
 
-        } catch (AlgebricksException | RemoteException | ACIDException ae) {
+        } catch (MetadataException ae) {
             throw new MetadataException(ae);
         }
     }
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataException.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataException.java
index 0501d48..61c21f4 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataException.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataException.java
@@ -21,6 +21,8 @@
 
 import org.apache.asterix.common.exceptions.CompilationException;
 
+import java.io.Serializable;
+
 public class MetadataException extends CompilationException {
     private static final long serialVersionUID = 1L;
 
@@ -35,4 +37,8 @@
     public MetadataException(String message, Throwable cause) {
         super(message, cause);
     }
+
+    public MetadataException(int errorCode, Serializable... params) {
+        super(errorCode, params);
+    }
 }
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/feeds/FeedMetadataUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/feeds/FeedMetadataUtil.java
index 385f2bd..3e22e6e 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/feeds/FeedMetadataUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/feeds/FeedMetadataUtil.java
@@ -25,6 +25,7 @@
 import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.library.ILibraryManager;
 import org.apache.asterix.external.api.IAdapterFactory;
 import org.apache.asterix.external.api.IDataSourceAdapter;
@@ -154,7 +155,7 @@
                 }
             }
         } catch (Exception e) {
-            throw new AsterixException("Invalid feed parameters", e);
+            throw new AsterixException("Invalid feed parameters. Exception Message:" + e.getMessage() , e);
         }
     }
 
@@ -269,7 +270,7 @@
     }
 
     public static ARecordType getOutputType(IFeed feed, Map<String, String> configuration, String key)
-            throws RemoteException, ACIDException, MetadataException {
+            throws MetadataException {
         ARecordType outputType = null;
         String fqOutputType = configuration.get(key);
 
@@ -308,7 +309,7 @@
                 } catch (ACIDException | RemoteException e2) {
                     e.addSuppressed(e2);
                 }
-                throw e;
+                throw new MetadataException(ErrorCode.FEED_CREATE_FEED_DATATYPE_ERROR, e, datatypeName);
             }
         } finally {
             MetadataManager.INSTANCE.releaseReadLatch();