From 1ae378d4e9e8c40b1a98f9bed5e10c673bb67589 Mon Sep 17 00:00:00 2001 From: Teddy Date: Wed, 20 Nov 2024 08:20:13 +0100 Subject: [PATCH] MINOR: Move from Date to LocalDate for thread safe operations (#18679) * fix: move from Date to LocalDate for thread safe operations * style: ran java linting * fix: invalid range in test case (cherry picked from commit 91de99ad17ab31dc19b3227784072b9b798652da) --- .../openmetadata/common/utils/CommonUtil.java | 48 +++++++++---------- .../service/jdbi3/TableRepository.java | 4 +- .../resources/usage/UsageResource.java | 6 +-- .../openmetadata/service/util/EntityUtil.java | 4 +- .../openmetadata/service/util/RestUtil.java | 17 ++++--- .../databases/TableResourceTest.java | 2 +- .../resources/usage/UsageResourceTest.java | 8 ++-- 7 files changed, 45 insertions(+), 44 deletions(-) diff --git a/common/src/main/java/org/openmetadata/common/utils/CommonUtil.java b/common/src/main/java/org/openmetadata/common/utils/CommonUtil.java index b6445acfc382..7e0da8b6ac45 100644 --- a/common/src/main/java/org/openmetadata/common/utils/CommonUtil.java +++ b/common/src/main/java/org/openmetadata/common/utils/CommonUtil.java @@ -24,22 +24,20 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.text.DateFormat; -import java.text.ParseException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; -import java.util.Calendar; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TimeZone; import java.util.UUID; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -121,42 +119,42 @@ public static Collection getResourcesFromDirectory(File file, Pattern pa } /** Get date after {@code days} from the given date or before i{@code days} when it is negative */ - public static Date getDateByOffset(Date date, int days) { - Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - calendar.setTime(date); - calendar.add(Calendar.DATE, days); - return calendar.getTime(); + public static LocalDate getDateByOffset(LocalDate localDate, int days) { + return localDate.plusDays(days); } /** Get date after {@code days} from the given date or before i{@code days} when it is negative */ - public static Date getDateByOffset(DateFormat dateFormat, String strDate, int days) { - Date date; + public static LocalDate getDateByOffset(DateTimeFormatter dateFormat, String strDate, int days) { + LocalDate localDate; try { - date = dateFormat.parse(strDate); - } catch (ParseException e) { + localDate = LocalDate.parse(strDate, dateFormat); + } catch (DateTimeParseException e) { throw new IllegalArgumentException("Failed to parse date " + strDate, e); } - return getDateByOffset(date, days); + return getDateByOffset(localDate, days); } /** Get date after {@code days} from the given date or before i{@code days} when it is negative */ - public static String getDateStringByOffset(DateFormat dateFormat, String strDate, int days) { - return dateFormat.format(getDateByOffset(dateFormat, strDate, days)); + public static String getDateStringByOffset( + DateTimeFormatter dateFormat, String strDate, int days) { + LocalDate localDate = getDateByOffset(dateFormat, strDate, days); + return localDate.format(dateFormat); } /** Check if given date is with in today - pastDays and today + futureDays */ public static boolean dateInRange( - DateFormat dateFormat, String date, int futureDays, int pastDays) { - Date today = new Date(); - Date startDate = getDateByOffset(today, -pastDays); - Date endDate = getDateByOffset(today, futureDays); - Date givenDate; + DateTimeFormatter dateFormat, String date, int futureDays, int pastDays) { + LocalDate today = LocalDate.now(); + LocalDate startDate = getDateByOffset(today, -pastDays); + LocalDate endDate = getDateByOffset(today, futureDays); + LocalDate givenDate; try { - givenDate = dateFormat.parse(date); - } catch (ParseException e) { + givenDate = LocalDate.parse(date, dateFormat); + } catch (DateTimeParseException e) { throw new IllegalArgumentException("Failed to parse date " + date, e); } - return givenDate.after(startDate) && givenDate.before(endDate); + return (givenDate.isAfter(startDate) || givenDate.equals(startDate)) + && (givenDate.isBefore(endDate) || givenDate.equals(endDate)); } public static final String HMAC_SHA256_ALGORITHM = "HmacSHA256"; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java index 3c85de74f59a..bb428941ce55 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java @@ -36,10 +36,10 @@ import com.google.common.collect.Streams; import java.io.IOException; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; @@ -1004,7 +1004,7 @@ private List aggregateAndFilterDailyCounts( } private TableJoins getJoins(Table table) { - String today = RestUtil.DATE_FORMAT.format(new Date()); + String today = RestUtil.DATE_FORMAT.format(LocalDate.now()); String todayMinus30Days = CommonUtil.getDateStringByOffset(RestUtil.DATE_FORMAT, today, -30); return new TableJoins() .withStartDate(todayMinus30Days) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java index 99231ea25613..942c8a8ca280 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java @@ -19,7 +19,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.Date; +import java.time.LocalDate; import java.util.UUID; import javax.validation.Valid; import javax.ws.rs.Consumes; @@ -105,7 +105,7 @@ public EntityUsage get( ResourceContext resourceContext = new ResourceContext(entity); authorizer.authorize(securityContext, operationContext, resourceContext); int actualDays = Math.min(Math.max(days, 1), 30); - String actualDate = date == null ? RestUtil.DATE_FORMAT.format(new Date()) : date; + String actualDate = date == null ? RestUtil.DATE_FORMAT.format(LocalDate.now()) : date; return addHref(uriInfo, dao.get(entity, id, actualDate, actualDays)); } @@ -155,7 +155,7 @@ public EntityUsage getByName( ResourceContext resourceContext = new ResourceContext<>(entity, null, fqn); authorizer.authorize(securityContext, operationContext, resourceContext); int actualDays = Math.min(Math.max(days, 1), 30); - String actualDate = date == null ? RestUtil.DATE_FORMAT.format(new Date()) : date; + String actualDate = date == null ? RestUtil.DATE_FORMAT.format(LocalDate.now()) : date; return addHref(uriInfo, dao.getByName(entity, fqn, actualDate, actualDays)); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java index f93c00a919aa..e08ff1e910fb 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityUtil.java @@ -22,11 +22,11 @@ import java.io.IOException; import java.security.MessageDigest; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -219,7 +219,7 @@ public static UsageDetails getLatestUsage(UsageDAO usageDAO, UUID entityId) { .withDailyStats(stats) .withWeeklyStats(stats) .withMonthlyStats(stats) - .withDate(RestUtil.DATE_FORMAT.format(new Date())); + .withDate(RestUtil.DATE_FORMAT.format(LocalDate.now())); } return details; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/RestUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/RestUtil.java index 2f5f8bbd92a1..76fe345bf704 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/RestUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/RestUtil.java @@ -24,8 +24,11 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Base64; -import java.util.Date; import java.util.TimeZone; import java.util.UUID; import javax.ws.rs.BadRequestException; @@ -42,15 +45,14 @@ public final class RestUtil { public static final String CHANGE_CUSTOM_HEADER = "X-OpenMetadata-Change"; public static final String SIGNATURE_HEADER = "X-OM-Signature"; public static final DateFormat DATE_TIME_FORMAT; - public static final DateFormat DATE_FORMAT; + public static final DateTimeFormatter DATE_FORMAT; static { // Quoted "Z" to indicate UTC, no timezone offset DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"); DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("UTC")); } private RestUtil() {} @@ -91,12 +93,13 @@ public static URI getHref(UriInfo uriInfo, String collectionPath, UUID id) { } public static int compareDates(String date1, String date2) throws ParseException { - return DATE_FORMAT.parse(date1).compareTo(DATE_FORMAT.parse(date2)); + return LocalDateTime.parse(date1, DATE_FORMAT) + .compareTo(LocalDateTime.parse(date2, DATE_FORMAT)); } public static String today(int offsetDays) { - Date date = CommonUtil.getDateByOffset(new Date(), offsetDays); - return DATE_FORMAT.format(date); + LocalDate localDate = CommonUtil.getDateByOffset(LocalDate.now(), offsetDays); + return localDate.format(DATE_FORMAT); } public static void validateCursors(String before, String after) { diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/databases/TableResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/databases/TableResourceTest.java index 1f099ed5449d..629fba50de37 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/databases/TableResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/databases/TableResourceTest.java @@ -1001,7 +1001,7 @@ void put_tableJoinsInvalidColumnName_4xx(TestInfo test) throws IOException { // Invalid date older than 30 days String invalidColumnFQN4 = table2.getFullyQualifiedName() + ".c1"; TableJoins tableJoins4 = - getTableJoins(getColumnJoin(C1, invalidColumnFQN4)).withStartDate(RestUtil.today(-30)); + getTableJoins(getColumnJoin(C1, invalidColumnFQN4)).withStartDate(RestUtil.today(-31)); assertResponse( () -> putJoins(table1.getId(), tableJoins4, ADMIN_AUTH_HEADERS), BAD_REQUEST, diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/usage/UsageResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/usage/UsageResourceTest.java index 05c27f1b0c20..e99190f8d50a 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/usage/UsageResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/usage/UsageResourceTest.java @@ -31,8 +31,8 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.time.LocalDate; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.Map; import java.util.Random; @@ -200,7 +200,7 @@ void testValidUsageByName(TestInfo test, String methodType, Map Table table = tableResourceTest.createEntity(tableResourceTest.createRequest(test), ADMIN_AUTH_HEADERS); DailyCount usageReport = - usageReport().withCount(100).withDate(RestUtil.DATE_FORMAT.format(new Date())); + usageReport().withCount(100).withDate(RestUtil.DATE_FORMAT.format(LocalDate.now())); reportUsageByNameAndCheckPut( TABLE, table.getFullyQualifiedName(), usageReport, 100, 100, authHeaders); // a put request updates the data again @@ -221,7 +221,7 @@ void put_validUsageForTables_200_OK() throws HttpResponseException { // and monthly usage percentile rank is correct. // Publish usage for DAYS_OF_USAGE number of days starting from today - String today = RestUtil.DATE_FORMAT.format(new Date()); // today + String today = RestUtil.DATE_FORMAT.format(LocalDate.now()); // today // Add table usages of each table - 0, 1 to TABLE_COUNT - 1 to get database usage final int dailyDatabaseUsageCount = TABLE_COUNT * (TABLE_COUNT - 1) / 2; @@ -348,7 +348,7 @@ void put_validUsageForTables_200_OK() throws HttpResponseException { public DailyCount usageReport() { Random random = new Random(); - String today = RestUtil.DATE_FORMAT.format(new Date()); + String today = RestUtil.DATE_FORMAT.format(LocalDate.now()); return new DailyCount().withCount(random.nextInt(100)).withDate(today); }