You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2018/06/05 13:29:19 UTC

[ambari] branch trunk updated: [AMBARI-23996] Changing column type from timestamp to long in users.create_time and user_authentication.[create|update]_time (#1456)

This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 3876e39  [AMBARI-23996] Changing column type from timestamp to long in users.create_time and user_authentication.[create|update]_time (#1456)
3876e39 is described below

commit 3876e39fbd8fca4f2d346b8f5ca419fc82b1c592
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Tue Jun 5 15:29:08 2018 +0200

    [AMBARI-23996] Changing column type from timestamp to long in users.create_time and user_authentication.[create|update]_time (#1456)
    
    * AMBARI-23396. Changing column type from timstamp to long in users.create_time and user_authentication.[create|update]_time
    
    * AMBARI-23996. Covering the upgrade path
---
 .../UserAuthenticationSourceResourceProvider.java  |  5 +-
 .../controller/internal/UserResourceProvider.java  |  3 +-
 .../orm/entities/UserAuthenticationEntity.java     | 21 +++----
 .../ambari/server/orm/entities/UserEntity.java     | 19 +++---
 .../ambari/server/security/authorization/User.java |  2 +-
 .../ambari/server/upgrade/UpgradeCatalog270.java   | 67 +++++++++++++++++++++-
 .../src/main/resources/Ambari-DDL-Derby-CREATE.sql | 10 ++--
 .../src/main/resources/Ambari-DDL-MySQL-CREATE.sql | 10 ++--
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql    | 10 ++--
 .../main/resources/Ambari-DDL-Postgres-CREATE.sql  | 10 ++--
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql    | 10 ++--
 .../main/resources/Ambari-DDL-SQLServer-CREATE.sql | 10 ++--
 ...erAuthenticationSourceResourceProviderTest.java |  5 +-
 .../internal/UserResourceProviderTest.java         |  3 +-
 .../jwt/AmbariJwtAuthenticationFilterTest.java     |  2 +-
 .../security/ldap/AmbariLdapDataPopulatorTest.java |  3 +-
 .../server/upgrade/UpgradeCatalog270Test.java      | 48 +++++++++++++++-
 17 files changed, 172 insertions(+), 66 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
index 6a5f528..6a099f3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
@@ -18,6 +18,7 @@
 package org.apache.ambari.server.controller.internal;
 
 import java.util.Collection;
+import java.util.Date;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
@@ -388,8 +389,8 @@ public class UserAuthenticationSourceResourceProvider extends AbstractAuthorized
         entity.getUserAuthenticationId(),
         entity.getAuthenticationType(),
         entity.getAuthenticationKey(),
-        entity.getCreateTime(),
-        entity.getUpdateTime());
+        new Date(entity.getCreateTime()),
+        new Date(entity.getUpdateTime()));
   }
 
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
index 2141327..1177b57 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
@@ -18,6 +18,7 @@
 package org.apache.ambari.server.controller.internal;
 
 import java.text.NumberFormat;
+import java.util.Date;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -692,7 +693,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
         userEntity.getActive(),
         isAdmin,
         userEntity.getConsecutiveFailures(),
-        userEntity.getCreateTime());
+        new Date(userEntity.getCreateTime()));
     userResponse.setGroups(groups);
     return userResponse;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
index 262c8ac..e909494 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
@@ -17,8 +17,6 @@
  */
 package org.apache.ambari.server.orm.entities;
 
-import java.util.Date;
-
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -36,8 +34,6 @@ import javax.persistence.PrePersist;
 import javax.persistence.PreUpdate;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 
 import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 import org.apache.commons.lang.builder.EqualsBuilder;
@@ -78,13 +74,11 @@ public class UserAuthenticationEntity {
 
   @Column(name = "create_time", nullable = false)
   @Basic
-  @Temporal(value = TemporalType.TIMESTAMP)
-  private Date createTime = new Date();
+  private long createTime;
 
   @Column(name = "update_time", nullable = false)
   @Basic
-  @Temporal(value = TemporalType.TIMESTAMP)
-  private Date updateTime = new Date();
+  private long updateTime ;
 
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "user_id", referencedColumnName = "user_id", nullable = false)
@@ -114,11 +108,11 @@ public class UserAuthenticationEntity {
     this.authenticationKey = authenticationKey;
   }
 
-  public Date getCreateTime() {
+  public long getCreateTime() {
     return createTime;
   }
 
-  public Date getUpdateTime() {
+  public long getUpdateTime() {
     return updateTime;
   }
 
@@ -145,8 +139,9 @@ public class UserAuthenticationEntity {
    */
   @PrePersist
   protected void onCreate() {
-    createTime = new Date();
-    updateTime = new Date();
+    final long now = System.currentTimeMillis();
+    createTime = now;
+    updateTime = now;
   }
 
   /**
@@ -154,7 +149,7 @@ public class UserAuthenticationEntity {
    */
   @PreUpdate
   protected void onUpdate() {
-    updateTime = new Date();
+    updateTime = System.currentTimeMillis();
   }
 
   @Override
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
index c679fff..1621389 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
@@ -18,7 +18,6 @@
 package org.apache.ambari.server.orm.entities;
 
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -37,10 +36,9 @@ import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
+import javax.persistence.PrePersist;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 import javax.persistence.Version;
 
@@ -71,8 +69,7 @@ public class UserEntity {
 
   @Column(name = "create_time", nullable = false)
   @Basic
-  @Temporal(value = TemporalType.TIMESTAMP)
-  private Date createTime = new Date();
+  private long createTime;
 
   @Column(name = "active", nullable = false)
   private Integer active = 1;
@@ -211,11 +208,11 @@ public class UserEntity {
     this.localUsername = localUsername;
   }
 
-  public Date getCreateTime() {
+  public long getCreateTime() {
     return createTime;
   }
 
-  public void setCreateTime(Date createTime) {
+  public void setCreateTime(long createTime) {
     this.createTime = createTime;
   }
 
@@ -308,6 +305,14 @@ public class UserEntity {
     }
   }
 
+  /**
+   * Ensure the create time is set properly when the record is created.
+   */
+  @PrePersist
+  protected void onCreate() {
+    createTime = System.currentTimeMillis();
+  }
+
   // ----- Object overrides --------------------------------------------------
 
   @Override
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
index a418451..4be2a9c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
@@ -48,7 +48,7 @@ public class User {
   public User(UserEntity userEntity) {
     userId = userEntity.getUserId();
     userName = userEntity.getUserName();
-    createTime = userEntity.getCreateTime();
+    createTime = new Date(userEntity.getCreateTime());
     active = userEntity.getActive();
 
     groups = new ArrayList<>();
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
index 2fd79c8..d28b773 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
@@ -22,8 +22,11 @@ import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Timestamp;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -323,6 +326,7 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog {
    * @see #updateUsersTable()
    */
   protected void upgradeUserTables() throws SQLException {
+    convertUserCreationTimeToLong();
     createUserAuthenticationTable();
     updateGroupMembershipRecords();
     updateAdminPrivilegeRecords();
@@ -550,6 +554,65 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog {
   }
 
   /**
+   * In order to save the epoch equivalent of users.create_time we need to convert data in this column as follows:
+   * <ol>
+   * <li>creating a temporary column where we store the numeric representation of
+   * the timestamp
+   * <li>populating data in the temporary column
+   * <li>removing original column column
+   * <li>renaming the temporary column to the original column
+   * </ol>
+   *
+   * @throws SQLException
+   *           if an error occurs while executing SQL statements
+   *
+   */
+  private void convertUserCreationTimeToLong() throws SQLException {
+    if (!isUserCreationTimeMigrated()) {
+      LOG.info("Converting user creation times...");
+      final String temporaryColumnName = USERS_CREATE_TIME_COLUMN + "_numeric";
+      if (!dbAccessor.tableHasColumn(USERS_TABLE, temporaryColumnName)) {
+        final DBAccessor.DBColumnInfo tempColumnInfo = new DBAccessor.DBColumnInfo(temporaryColumnName, Long.class);
+        dbAccessor.addColumn(USERS_TABLE, tempColumnInfo);
+      }
+
+      if (dbAccessor.tableHasColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN)) {
+        final Map<Integer, Timestamp> currentUserCreateTimes = fetchCurrentUserCreateTimesNotYetMigrated(temporaryColumnName);
+        for (Map.Entry<Integer, Timestamp> currentUserCreateTime : currentUserCreateTimes.entrySet()) {
+          dbAccessor.updateTable(USERS_TABLE, temporaryColumnName, currentUserCreateTime.getValue().getTime(),
+              "WHERE " + USERS_USER_ID_COLUMN + "=" + currentUserCreateTime.getKey());
+        }
+
+        dbAccessor.dropColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN);
+      }
+
+      final DBAccessor.DBColumnInfo usersCreateTimeColumnInfo = new DBAccessor.DBColumnInfo(USERS_CREATE_TIME_COLUMN, Long.class, null, null, false);
+      dbAccessor.renameColumn(USERS_TABLE, temporaryColumnName, usersCreateTimeColumnInfo);
+      LOG.info("Converted user creation times");
+    } else {
+      LOG.info("Already converted user creation timestamps to EPOCH representation");
+    }
+  }
+
+  private boolean isUserCreationTimeMigrated() throws SQLException {
+    final int columnType = dbAccessor.getColumnType(USERS_TABLE, USERS_CREATE_TIME_COLUMN);
+    LOG.info(USERS_TABLE + "." + USERS_CREATE_TIME_COLUMN + "'s type = " + columnType);
+    return columnType != Types.DATE && columnType != Types.TIMESTAMP;
+  }
+
+  private Map<Integer, Timestamp> fetchCurrentUserCreateTimesNotYetMigrated(String temporaryColumnName) throws SQLException {
+    final Map<Integer, Timestamp> currentUserCreateTimes = new HashMap<>();
+    try (
+        PreparedStatement pstmt = dbAccessor.getConnection().prepareStatement("SELECT " + USERS_USER_ID_COLUMN + ", " + USERS_CREATE_TIME_COLUMN + " FROM " + USERS_TABLE + " WHERE " + temporaryColumnName + " IS NULL ORDER BY " + USERS_USER_ID_COLUMN);
+        ResultSet rs = pstmt.executeQuery()) {
+      while (rs.next()) {
+        currentUserCreateTimes.put(rs.getInt(1), rs.getTimestamp(2));
+      }
+    }
+    return currentUserCreateTimes;
+  }
+
+  /**
    * If the <code>users</code> table has not yet been migrated, create the <code>user_authentication</code>
    * table and generate relevant records for that table based on data in the <code>users</code> table.
    * <p>
@@ -570,8 +633,8 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog {
       columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_USER_ID_COLUMN, Integer.class, null, null, false));
       columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN, String.class, 50, null, false));
       columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN, String.class, 2048, null, true));
-      columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Timestamp.class, null, null, true));
-      columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Timestamp.class, null, null, true));
+      columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Long.class, null, null, true));
+      columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Long.class, null, null, true));
 
       // Make sure the temporary table does not exist
       dbAccessor.dropTable(temporaryTable);
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 2c5bc3b..66f4701 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -301,7 +301,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   display_name VARCHAR(255) NOT NULL,
   local_username VARCHAR(255) NOT NULL,
-  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+  create_time BIGINT NOT NULL,
   version BIGINT NOT NULL DEFAULT 0,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -312,8 +312,8 @@ CREATE TABLE user_authentication (
   user_id INTEGER NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+  create_time BIGINT NOT NULL,
+  update_time BIGINT NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id));
 
@@ -1270,12 +1270,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id)
 
 -- Insert the default administrator user.
 insert into users(user_id, principal_id, user_name, display_name, local_username, create_time)
-  SELECT 1, 1, 'admin', 'Administrator', 'admin', CURRENT_TIMESTAMP FROM SYSIBM.SYSDUMMY1;
+  SELECT 1, 1, 'admin', 'Administrator', 'admin', 0 FROM SYSIBM.SYSDUMMY1;
 
 -- Insert the LOCAL authentication data for the default administrator user.
 -- The authentication_key value is the salted digest of the password: admin
 insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP FROM SYSIBM.SYSDUMMY1;
+  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', 0, 0 FROM SYSIBM.SYSDUMMY1;
 
 insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
   SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 FROM SYSIBM.SYSDUMMY1
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 7e7c4d0..af64142 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -321,7 +321,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   display_name VARCHAR(255) NOT NULL,
   local_username VARCHAR(255) NOT NULL,
-  create_time TIMESTAMP DEFAULT NOW(),
+  create_time BIGINT NOT NULL,
   version BIGINT NOT NULL DEFAULT 0,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -332,8 +332,8 @@ CREATE TABLE user_authentication (
   user_id INTEGER NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_time TIMESTAMP DEFAULT NOW(),
+  create_time BIGINT NOT NULL,
+  update_time BIGINT NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)
 );
@@ -1219,12 +1219,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id) VALUES
 
 -- Insert the default administrator user.
 INSERT INTO users(user_id, principal_id, user_name, display_name, local_username, create_time)
-  SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW();
+  SELECT 1, 1, 'admin', 'Administrator', 'admin', UNIX_TIMESTAMP() * 1000;
 
 -- Insert the LOCAL authentication data for the default administrator user.
 -- The authentication_key value is the salted digest of the password: admin
 INSERT INTO user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW();
+  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000;
 
 INSERT INTO adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
   SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 UNION ALL
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 80e7aac..3a54f33 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -301,7 +301,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR2(1024) DEFAULT NULL,
   display_name VARCHAR2(255) NOT NULL,
   local_username VARCHAR2(255) NOT NULL,
-  create_time TIMESTAMP NULL,
+  create_time NUMBER(19) NOT NULL,
   version NUMBER(19) DEFAULT 0 NOT NULL,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -312,8 +312,8 @@ CREATE TABLE user_authentication (
   user_id NUMBER(10) NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time TIMESTAMP NULL,
-  update_time TIMESTAMP NULL,
+  create_time NUMBER(19) NOT NULL,
+  update_time NUMBER(19) NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)
 );
@@ -1211,12 +1211,12 @@ insert into adminprincipal (principal_id, principal_type_id)
 
 -- Insert the default administrator user.
 insert into users(user_id, principal_id, user_name, display_name, local_username, create_time)
-  SELECT 1, 1, 'admin', 'Administrator', 'admin', CURRENT_TIMESTAMP from dual;
+  SELECT 1, 1, 'admin', 'Administrator', 'admin', (SYSDATE - DATE '1970-01-01') * 86400000 from dual;
 
 -- Insert the LOCAL authentication data for the default administrator user.
 -- The authentication_key value is the salted digest of the password: admin
 insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP from dual;
+  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', (SYSDATE - DATE '1970-01-01') * 86400000, (SYSDATE - DATE '1970-01-01') * 86400000 from dual;
 
 insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
   select 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 from dual
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 42387a3..1611130 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -303,7 +303,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   display_name VARCHAR(255) NOT NULL,
   local_username VARCHAR(255) NOT NULL,
-  create_time TIMESTAMP DEFAULT NOW(),
+  create_time BIGINT NOT NULL,
   version BIGINT DEFAULT 0 NOT NULL,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -314,8 +314,8 @@ CREATE TABLE user_authentication (
   user_id INTEGER NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time TIMESTAMP DEFAULT NOW(),
-  update_time TIMESTAMP DEFAULT NOW(),
+  create_time BIGINT NOT NULL,
+  update_time BIGINT NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id));
 
@@ -1201,12 +1201,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id) VALUES
 
 -- Insert the default administrator user.
 INSERT INTO users(user_id, principal_id, user_name, display_name, local_username, create_time)
-  SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW();
+  SELECT 1, 1, 'admin', 'Administrator', 'admin', CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000;
 
 -- Insert the LOCAL authentication data for the default administrator user.
 -- The authentication_key value is the salted digest of the password: admin
 INSERT INTO user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW();
+  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000, CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000;
 
 INSERT INTO adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
   SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 UNION ALL
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index fd5f50a..bf6f63d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -299,7 +299,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   display_name VARCHAR(255) NOT NULL,
   local_username VARCHAR(255) NOT NULL,
-  create_time TIMESTAMP DEFAULT NOW(),
+  create_time NUMERIC(19) NOT NULL,
   version NUMERIC(19) NOT NULL DEFAULT 0,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -310,8 +310,8 @@ CREATE TABLE user_authentication (
   user_id INTEGER NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time TIMESTAMP DEFAULT NOW(),
-  update_time TIMESTAMP DEFAULT NOW(),
+  create_time NUMERIC(19) NOT NULL,
+  update_time NUMERIC(19) NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)
 );
@@ -1208,12 +1208,12 @@ insert into adminprincipal (principal_id, principal_type_id)
 
 -- Insert the default administrator user.
 insert into users(user_id, principal_id, user_name, display_name, local_username, create_time)
-  SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW();
+  SELECT 1, 1, 'admin', 'Administrator', 'admin', 0;
 
 -- Insert the LOCAL authentication data for the default administrator user.
 -- The authentication_key value is the salted digest of the password: admin
 insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW();
+  SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', 0, 0;
 
 
 insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 2b4a504..03fe222 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -305,7 +305,7 @@ CREATE TABLE users (
   active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   display_name VARCHAR(255) NOT NULL,
   local_username VARCHAR(255) NOT NULL,
-  create_time DATETIME DEFAULT GETDATE(),
+  create_time BIGINT NOT NULL,
   version BIGINT NOT NULL DEFAULT 0,
   CONSTRAINT PK_users PRIMARY KEY (user_id),
   CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
@@ -316,8 +316,8 @@ CREATE TABLE user_authentication (
   user_id INTEGER NOT NULL,
   authentication_type VARCHAR(50) NOT NULL,
   authentication_key VARCHAR(2048),
-  create_time DATETIME DEFAULT GETDATE(),
-  update_time DATETIME DEFAULT GETDATE(),
+  create_time BIGINT NOT NULL,
+  update_time BIGINT NOT NULL,
   CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id),
   CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)
 );
@@ -1227,12 +1227,12 @@ BEGIN TRANSACTION
 
   -- Insert the default administrator user.
   insert into users(user_id, principal_id, user_name, display_name, local_username, create_time)
-    select 1, 1, 'admin', 'Administrator', 'admin', GETDATE();
+    select 1, 1, 'admin', 'Administrator', 'admin', CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000;
 
   -- Insert the LOCAL authentication data for the default administrator user.
   -- The authentication_key value is the salted digest of the password: admin
   insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time)
-    select 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', GETDATE(), GETDATE();
+    select 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000, CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000;
 
 
   insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java
index c1dba1b..c1a5f54 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java
@@ -23,7 +23,6 @@ import static org.easymock.EasyMock.expectLastCall;
 
 import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -73,8 +72,8 @@ import com.google.inject.Injector;
  */
 public class UserAuthenticationSourceResourceProviderTest extends EasyMockSupport {
 
-  private static final Date CREATE_TIME = Calendar.getInstance().getTime();
-  private static final Date UPDATE_TIME = Calendar.getInstance().getTime();
+  private static final long CREATE_TIME = Calendar.getInstance().getTime().getTime();
+  private static final long UPDATE_TIME = Calendar.getInstance().getTime().getTime();
 
   @Before
   public void resetMocks() {
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java
index 2bc3f47..42fac4e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java
@@ -29,7 +29,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -129,7 +128,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
  */
 public class UserResourceProviderTest extends EasyMockSupport {
 
-  private static final Date CREATE_TIME = Calendar.getInstance().getTime();
+  private static final long CREATE_TIME = Calendar.getInstance().getTime().getTime();
 
   @Before
   public void resetMocks() {
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java
index ba4eb74..2c88d9f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java
@@ -409,7 +409,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport {
     expect(userEntity.getActive()).andReturn(true).atLeastOnce();
     expect(userEntity.getUserId()).andReturn(1).atLeastOnce();
     expect(userEntity.getUserName()).andReturn("username").atLeastOnce();
-    expect(userEntity.getCreateTime()).andReturn(new Date()).atLeastOnce();
+    expect(userEntity.getCreateTime()).andReturn(new Date().getTime()).atLeastOnce();
     expect(userEntity.getMemberEntities()).andReturn(Collections.emptySet()).atLeastOnce();
     expect(userEntity.getAuthenticationEntities()).andReturn(Collections.singletonList(userAuthenticationEntity)).atLeastOnce();
     expect(userEntity.getPrincipal()).andReturn(principal).atLeastOnce();
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
index 7d502be..a015b18 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
@@ -37,7 +37,6 @@ import static org.junit.Assert.assertEquals;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -2041,7 +2040,7 @@ public class AmbariLdapDataPopulatorTest {
     final UserEntity userEntity = new UserEntity();
     userEntity.setUserId(userIdCounter++);
     userEntity.setUserName(UserName.fromString(name).toString());
-    userEntity.setCreateTime(new Date());
+    userEntity.setCreateTime(0);
     userEntity.setActive(true);
     userEntity.setMemberEntities(new HashSet<>());
 
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
index 8b2f98c..38f2db1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
@@ -96,6 +96,7 @@ import static org.apache.ambari.server.upgrade.UpgradeCatalog270.STAGE_TABLE;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNIQUE_USERS_0_INDEX;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNI_KKP;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_CONSECUTIVE_FAILURES_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_CREATE_TIME_COLUMN;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_DISPLAY_NAME_COLUMN;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LDAP_USER_COLUMN;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LOCAL_USERNAME_COLUMN;
@@ -136,14 +137,18 @@ import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
 
 import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Timestamp;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -424,6 +429,10 @@ public class UpgradeCatalog270Test {
     dbAccessor.addPKConstraint(AMBARI_CONFIGURATION_TABLE, "PK_ambari_configuration", AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN, AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN);
     expectLastCall().once();
 
+    //upgradeUserTable - converting users.create_time to long
+    Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture = newCapture(CaptureType.ALL);
+    Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture = newCapture(CaptureType.ALL);
+
     // upgradeUserTable - create user_authentication table
     Capture<List<DBAccessor.DBColumnInfo>> createUserAuthenticationTableCaptures = newCapture(CaptureType.ALL);
     Capture<List<DBAccessor.DBColumnInfo>> createMembersTableCaptures = newCapture(CaptureType.ALL);
@@ -443,6 +452,7 @@ public class UpgradeCatalog270Test {
     // Any return value will work here as long as a SQLException is not thrown.
     expect(dbAccessor.getColumnType(USERS_TABLE, USERS_USER_TYPE_COLUMN)).andReturn(0).anyTimes();
 
+    prepareConvertingUsersCreationTime(dbAccessor, temporaryColumnCreationCapture, temporaryColumnRenameCapture);
     prepareCreateUserAuthenticationTable(dbAccessor, createUserAuthenticationTableCaptures);
     prepareUpdateGroupMembershipRecords(dbAccessor, createMembersTableCaptures);
     prepareUpdateAdminPrivilegeRecords(dbAccessor, createAdminPrincipalTableCaptures);
@@ -555,6 +565,7 @@ public class UpgradeCatalog270Test {
     Assert.assertEquals(State.UNKNOWN, capturedLastValidColumn.getDefaultValue());
     Assert.assertEquals(String.class, capturedLastValidColumn.getType());
 
+    validateConvertingUserCreationTime(temporaryColumnCreationCapture,temporaryColumnRenameCapture);
     validateCreateUserAuthenticationTable(createUserAuthenticationTableCaptures);
     validateUpdateGroupMembershipRecords(createMembersTableCaptures);
     validateUpdateAdminPrivilegeRecords(createAdminPrincipalTableCaptures);
@@ -609,6 +620,33 @@ public class UpgradeCatalog270Test {
     return module;
   }
 
+  private void prepareConvertingUsersCreationTime(DBAccessor dbAccessor, Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture,
+      Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture) throws SQLException {
+    expect(dbAccessor.getColumnType(USERS_TABLE, USERS_CREATE_TIME_COLUMN)).andReturn(Types.TIMESTAMP).once();
+    final String temporaryColumnName = USERS_CREATE_TIME_COLUMN + "_numeric";
+    expect(dbAccessor.tableHasColumn(USERS_TABLE, temporaryColumnName)).andReturn(Boolean.FALSE);
+    dbAccessor.addColumn(eq(USERS_TABLE), capture(temporaryColumnCreationCapture));
+    expect(dbAccessor.tableHasColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN)).andReturn(Boolean.TRUE);
+
+    final Connection connectionMock = niceMock(Connection.class);
+    expect(dbAccessor.getConnection()).andReturn(connectionMock).once();
+    final PreparedStatement preparedStatementMock = niceMock(PreparedStatement.class);
+    expect(connectionMock.prepareStatement(anyString())).andReturn(preparedStatementMock);
+    final ResultSet resultSetMock = niceMock(ResultSet.class);
+    expect(preparedStatementMock.executeQuery()).andReturn(resultSetMock);
+    expect(resultSetMock.next()).andReturn(Boolean.TRUE).once();
+    expect(resultSetMock.getInt(1)).andReturn(1);
+    expect(resultSetMock.getTimestamp(2)).andReturn(new Timestamp(1l));
+    replay(connectionMock, preparedStatementMock, resultSetMock);
+
+    expect(dbAccessor.updateTable(eq(USERS_TABLE), eq(temporaryColumnName), eq(1l), anyString())).andReturn(anyInt());
+
+    dbAccessor.dropColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN);
+    expectLastCall().once();
+
+    dbAccessor.renameColumn(eq(USERS_TABLE), eq(temporaryColumnName), capture(temporaryColumnRenameCapture));
+  }
+
   private void prepareCreateUserAuthenticationTable(DBAccessor dbAccessor, Capture<List<DBAccessor.DBColumnInfo>> capturedData)
       throws SQLException {
 
@@ -632,6 +670,12 @@ public class UpgradeCatalog270Test {
     expect(dbAccessor.executeUpdate(startsWith("insert into " + USER_AUTHENTICATION_TABLE))).andReturn(1).once();
   }
 
+  private void validateConvertingUserCreationTime(Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture, Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture) {
+    Assert.assertTrue(temporaryColumnCreationCapture.hasCaptured());
+    Assert.assertTrue(temporaryColumnRenameCapture.hasCaptured());
+    assertEquals(new DBAccessor.DBColumnInfo(USERS_CREATE_TIME_COLUMN, Long.class, null, null, false), temporaryColumnRenameCapture.getValue());
+  }
+
   private void validateCreateUserAuthenticationTable(Capture<List<DBAccessor.DBColumnInfo>> capturedData) {
     Assert.assertTrue(capturedData.hasCaptured());
     List<List<DBAccessor.DBColumnInfo>> capturedValues = capturedData.getValues();
@@ -643,8 +687,8 @@ public class UpgradeCatalog270Test {
               new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_USER_ID_COLUMN, Integer.class, null, null, false),
               new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN, String.class, 50, null, false),
               new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN, String.class, 2048, null, true),
-              new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Timestamp.class, null, null, true),
-              new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Timestamp.class, null, null, true)
+              new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Long.class, null, null, true),
+              new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Long.class, null, null, true)
           )
       );
     }

-- 
To stop receiving notification emails like this one, please contact
smolnar@apache.org.