diff --git a/org.openwms.core.util/pom.xml b/org.openwms.core.util/pom.xml index f5ff31db..3f263b20 100644 --- a/org.openwms.core.util/pom.xml +++ b/org.openwms.core.util/pom.xml @@ -17,6 +17,34 @@ HEAD + + 6.5.2 + + + + + + com.github.dozermapper + dozer-core + ${dozer.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + jcl-over-slf4j + + + + + + @@ -57,8 +85,8 @@ provided - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided @@ -79,5 +107,11 @@ spring-test test + + org.mockito + mockito-core + 5.7.0 + test + diff --git a/org.openwms.core.util/src/main/java/org/openwms/core/http/AbstractWebController.java b/org.openwms.core.util/src/main/java/org/openwms/core/http/AbstractWebController.java index 8eece4a0..128ef8be 100644 --- a/org.openwms.core.util/src/main/java/org/openwms/core/http/AbstractWebController.java +++ b/org.openwms.core.util/src/main/java/org/openwms/core/http/AbstractWebController.java @@ -15,11 +15,13 @@ */ package org.openwms.core.http; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.ValidationException; import org.ameba.LoggingCategories; import org.ameba.exception.BehaviorAwareException; import org.ameba.exception.BusinessRuntimeException; import org.ameba.exception.TechnicalRuntimeException; -import org.ameba.http.AbstractBase; import org.ameba.http.Response; import org.openwms.core.exception.ExceptionCodes; import org.openwms.core.listener.RemovalNotAllowedException; @@ -35,9 +37,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.util.UriTemplate; -import javax.servlet.http.HttpServletRequest; -import javax.validation.ConstraintViolationException; -import javax.validation.ValidationException; +import java.io.Serializable; import java.net.URI; import java.util.Locale; @@ -73,7 +73,7 @@ protected ResponseEntity> handleRemovalNotAllowedException(RemovalNo .withMessageKey(rnae.getMessageKey()) .withObj(rnae.getData()) .build(), - HttpStatus.UNAUTHORIZED + HttpStatus.FORBIDDEN ); } @@ -195,7 +195,7 @@ protected String translate(String key, Object... objects) { * @param params A set of Serializable objects that are passed to the caller * @return A ResponseEntity with status {@code code} */ - protected ResponseEntity> buildResponse(HttpStatus code, String msg, String msgKey, T... params) { + protected ResponseEntity> buildResponse(HttpStatus code, String msg, String msgKey, T... params) { Response result = Response.newBuilder().withMessage(msg).withMessageKey(msgKey).withHttpStatus(code.toString()).withObj(params).build(); return new ResponseEntity<>(result, code); } @@ -211,7 +211,7 @@ protected ResponseEntity> buildResponse(Htt * @param params A set of Serializable objects that are passed to the caller * @return A ResponseEntity with status {@code code} */ - protected ResponseEntity> buildResponse(HttpStatus code, String msg, String msgKey, MultiValueMap headers, T... params) { + protected ResponseEntity> buildResponse(HttpStatus code, String msg, String msgKey, MultiValueMap headers, T... params) { Response result = Response.newBuilder().withMessage(msg).withMessageKey(msgKey).withHttpStatus(code.toString()).withObj(params).build(); return new ResponseEntity<>(result, headers, code); } @@ -223,7 +223,7 @@ protected ResponseEntity> buildResponse(Htt * @param params A set of Serializable objects that are passed to the caller * @return A ResponseEntity with status {@link HttpStatus#OK} */ - protected ResponseEntity> buildOKResponse(T... params) { + protected ResponseEntity> buildOKResponse(T... params) { return buildResponse(HttpStatus.OK, "", "", params); } @@ -237,7 +237,7 @@ protected ResponseEntity> buildOKResponse(T * @param params A set of Serializable objects that are passed to the caller * @return A ResponseEntity with status {@code code} */ - protected ResponseEntity> buildNOKResponseWithKey(HttpStatus code, String msg, String msgKey, T... params) { + protected ResponseEntity> buildNOKResponseWithKey(HttpStatus code, String msg, String msgKey, T... params) { return buildResponse(code, msg, msgKey, params); } @@ -250,7 +250,7 @@ protected ResponseEntity> buildNOKResponseW * @param params A set of Serializable objects that are passed to the caller * @return A ResponseEntity with status {@code code} */ - protected ResponseEntity> buildNOKResponse(HttpStatus code, String msg, T... params) { + protected ResponseEntity> buildNOKResponse(HttpStatus code, String msg, T... params) { return buildResponse(code, msg, "", params); } diff --git a/org.openwms.core.util/src/main/java/org/openwms/core/time/TimeProvider.java b/org.openwms.core.util/src/main/java/org/openwms/core/time/TimeProvider.java index 967a1044..be7e642e 100644 --- a/org.openwms.core.util/src/main/java/org/openwms/core/time/TimeProvider.java +++ b/org.openwms.core.util/src/main/java/org/openwms/core/time/TimeProvider.java @@ -18,6 +18,7 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Date; @@ -45,35 +46,62 @@ public interface TimeProvider { * * @return Timezone aware Date */ - default Date nowAsDate() { - return Date.from(ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()).toInstant()); + default Date nowAsCurrentDate() { + return Date.from(ZonedDateTime.of(LocalDateTime.now(ZoneId.systemDefault()), ZoneId.systemDefault()).toInstant()); + } + + /** + * Returns the current date and time in UTC timezone. + * + * @return UTC Date + */ + default Date nowAsZuluDate() { + return Date.from(ZonedDateTime.now(ZoneId.of("Z")).toInstant()); } /** * Returns the current date and time considering the configured timezone. * - * @return Timezone aware DateTime + * @return Timezone aware ZonedDateTime */ - default ZonedDateTime nowAsZonedDateTime() { + default ZonedDateTime nowAsCurrentZonedDateTime() { return nowAsZonedDateTime(ZoneId.systemDefault()); } /** * Returns the current date and time considering the configured timezone. * - * @param zoneId ZoneId - * @return Timezone aware DateTime + * @return Timezone aware ZonedDateTime + */ + default ZonedDateTime nowAsZuluZonedDateTime() { + return nowAsZonedDateTime(ZoneOffset.UTC); + } + + /** + * Returns the current date and time considering the given timezone. + * + * @param zoneId ZoneId to consider + * @return Timezone aware ZonedDateTime */ default ZonedDateTime nowAsZonedDateTime(ZoneId zoneId) { - return ZonedDateTime.of(LocalDateTime.now(), zoneId); + return ZonedDateTime.now(zoneId); } /** * Returns the current date and time of the system considering the configured timezone. * - * @return Timezone aware Date + * @return Timezone aware Instant + */ + default Instant nowAsCurrentInstant() { + return ZonedDateTime.of(LocalDateTime.now(ZoneId.systemDefault()), ZoneId.systemDefault()).toInstant(); + } + + /** + * Returns the date and time in UTC timezone. + * + * @return Timezone aware Instant */ - default Instant now() { - return ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()).toInstant(); + default Instant nowAsZuluInstant() { + return ZonedDateTime.of(LocalDateTime.now(ZoneOffset.UTC), ZoneOffset.UTC).toInstant(); } } diff --git a/org.openwms.core.util/src/test/java/org/openwms/core/time/TimeProviderTest.java b/org.openwms.core.util/src/test/java/org/openwms/core/time/TimeProviderTest.java new file mode 100644 index 00000000..fb4f52f4 --- /dev/null +++ b/org.openwms.core.util/src/test/java/org/openwms/core/time/TimeProviderTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2005-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openwms.core.time; + +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.spy; + +/** + * A TimeProviderTest. + * + * @author Heiko Scherrer + */ +class TimeProviderTest { + + + /** + * This test verifies if the nowAsCurrentDate method returns the current date + * and time considering the system's configured timezone. The date generation + * process by the method is replicated inside the test to compare and validate + * the actual result. + */ + @Test + public void testNowAsCurrentDate() { + TimeProvider timeProvider = new TimeProvider() {}; + + // Call the method under test + Date actualDate = timeProvider.nowAsCurrentDate(); + + // Get the expected current date + Date expectedDate = Date.from(ZonedDateTime.of(LocalDateTime.now(ZoneId.systemDefault()), ZoneId.systemDefault()).toInstant()); + + // Since the date creation and method call can't happen simultaneously, + // there might be slight microseconds difference between actual and expected dates. + // The comparison should be upto the seconds to avoid test failure + long actualTimeInSec = actualDate.getTime() / 1000; + long expectedTimeInSec = expectedDate.getTime() / 1000; + + assertEquals(expectedTimeInSec, actualTimeInSec, "The expected and actual dates should be equal"); + } + + @Test + void nowAsZuluZonedDateTime() { + var tp = spy(TimeProvider.class); + + + var zuluTime = tp.nowAsZuluZonedDateTime(); + System.out.println(zuluTime); + + ZonedDateTime nowGMTPlus1 = ZonedDateTime.now(ZoneId.of("GMT+1")); + Date nowZulu = Date.from(nowGMTPlus1.toInstant()); + System.out.println(nowGMTPlus1); + + assertTrue(zuluTime.isBefore(nowGMTPlus1)); + assertTrue(zuluTime.plusMinutes(60).isAfter(nowGMTPlus1)); + } + + /** + * Trivial implementation of TimeProvider for testing purposes. + */ + private final TimeProvider timeProvider = new TimeProvider() {}; + + @Test + void testNowAsCurrentInstant() { + Instant testInstant = Instant.now(); + Instant methodInstant = timeProvider.nowAsCurrentInstant(); + + // We only check minutes as the precision of the test might result in a difference in milliseconds + assertEquals(testInstant.atZone(ZoneId.systemDefault()).getMinute(), methodInstant.atZone(ZoneId.systemDefault()).getMinute()); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9fb3d4ee..7220f93e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.openwms org.openwms.parent - 25 + 26 org.openwms